From 1345bfce4f51853707c97b2e1ad34bbc5c76d3db Mon Sep 17 00:00:00 2001 From: maxwelbm Date: Thu, 12 Sep 2024 18:18:27 -0300 Subject: [PATCH 1/6] refactor: preparing login command code structure for testing --- pkg/cmd/deploy/requests.go | 5 +-- pkg/cmd/deploy_remote/requests.go | 5 +-- pkg/cmd/init/init.go | 7 +--- pkg/cmd/login/browser.go | 17 ++++---- pkg/cmd/login/login.go | 69 ++++++++++++++++++++----------- pkg/cmd/login/mock/login_mock.go | 8 ++++ pkg/cmd/login/mock/token_mock.go | 21 ++++++++++ pkg/cmd/login/terminal.go | 16 ++----- pkg/cmd/root/pre_command.go | 7 +--- pkg/cmd/root/root.go | 2 +- pkg/config/config.go | 31 +++++++++++--- pkg/metric/count.go | 6 +-- pkg/metric/segment.go | 5 +-- pkg/schedule/schedule.go | 11 +---- pkg/token/token.go | 35 ++++++---------- pkg/vulcan/vulcan.go | 6 +-- 16 files changed, 137 insertions(+), 114 deletions(-) create mode 100644 pkg/cmd/login/mock/login_mock.go create mode 100644 pkg/cmd/login/mock/token_mock.go diff --git a/pkg/cmd/deploy/requests.go b/pkg/cmd/deploy/requests.go index 755688292..fec659efc 100644 --- a/pkg/cmd/deploy/requests.go +++ b/pkg/cmd/deploy/requests.go @@ -569,13 +569,10 @@ func (cmd *DeployCmd) updateInstance(ctx context.Context, client *apiapp.Client, func checkToken(f *cmdutil.Factory) error { configureToken := f.Config.GetString("token") - t, err := token.New(&token.Config{ + t := token.New(&token.Config{ Client: f.HttpClient, Out: f.IOStreams.Out, }) - if err != nil { - return fmt.Errorf("%s: %w", utils.ErrorTokenManager, err) - } if configureToken == "" { return utils.ErrorTokenNotProvided diff --git a/pkg/cmd/deploy_remote/requests.go b/pkg/cmd/deploy_remote/requests.go index 755688292..fec659efc 100644 --- a/pkg/cmd/deploy_remote/requests.go +++ b/pkg/cmd/deploy_remote/requests.go @@ -569,13 +569,10 @@ func (cmd *DeployCmd) updateInstance(ctx context.Context, client *apiapp.Client, func checkToken(f *cmdutil.Factory) error { configureToken := f.Config.GetString("token") - t, err := token.New(&token.Config{ + t := token.New(&token.Config{ Client: f.HttpClient, Out: f.IOStreams.Out, }) - if err != nil { - return fmt.Errorf("%s: %w", utils.ErrorTokenManager, err) - } if configureToken == "" { return utils.ErrorTokenNotProvided diff --git a/pkg/cmd/init/init.go b/pkg/cmd/init/init.go index a99971880..bc5fe22b2 100644 --- a/pkg/cmd/init/init.go +++ b/pkg/cmd/init/init.go @@ -67,7 +67,7 @@ type initCmd struct { changeDir func(dir string) error askOne func(p survey.Prompt, response interface{}, opts ...survey.AskOpt) error load func(filenames ...string) (err error) - dir func() (config.DirPath, error) + dir func() config.DirPath mkdirTemp func(dir, pattern string) (string, error) readAll func(r io.Reader) ([]byte, error) get func(url string) (resp *http.Response, err error) @@ -212,10 +212,7 @@ func (cmd *initCmd) Run(c *cobra.Command, _ []string) error { return err } - dirPath, err := cmd.dir() - if err != nil { - return err - } + dirPath := cmd.dir() // Create a temporary directory tempDir, err := cmd.mkdirTemp(dirPath.Dir, "tempclonesamples") diff --git a/pkg/cmd/login/browser.go b/pkg/cmd/login/browser.go index 70e3d19dc..48b99724e 100644 --- a/pkg/cmd/login/browser.go +++ b/pkg/cmd/login/browser.go @@ -6,9 +6,7 @@ import ( "net/http" msg "github.com/aziontech/azion-cli/messages/login" - "github.com/aziontech/azion-cli/pkg/cmdutil" "github.com/aziontech/azion-cli/pkg/logger" - "github.com/skratchdot/open-golang/open" "go.uber.org/zap" ) @@ -16,8 +14,12 @@ const ( urlSsoNext = "https://sso.azion.com/login?next=cli" ) -func browserLogin(f *cmdutil.Factory) error { +type Server interface { + ListenAndServe() error + Shutdown(ctx context.Context) error +} +func (l *login) browserLogin(srv Server) error { ctx, cancel := context.WithCancel(context.Background()) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { @@ -29,8 +31,7 @@ func browserLogin(f *cmdutil.Factory) error { cancel() }) - srv := &http.Server{Addr: ":8080"} - err := openBrowser(f) + err := l.openBrowser() if err != nil { return err } @@ -53,9 +54,9 @@ func browserLogin(f *cmdutil.Factory) error { return nil } -func openBrowser(f *cmdutil.Factory) error { - logger.FInfo(f.IOStreams.Out, msg.VisitMsg) - err := open.Run(urlSsoNext) +func (l *login) openBrowser() error { + logger.FInfo(l.factory.IOStreams.Out, msg.VisitMsg) + err := l.run(urlSsoNext) if err != nil { return err } diff --git a/pkg/cmd/login/login.go b/pkg/cmd/login/login.go index 1c8d2e575..586b4ad6b 100644 --- a/pkg/cmd/login/login.go +++ b/pkg/cmd/login/login.go @@ -2,6 +2,7 @@ package login import ( "fmt" + "net/http" "strings" "github.com/AlecAivazis/survey/v2" @@ -14,13 +15,41 @@ import ( "github.com/pelletier/go-toml/v2" "github.com/spf13/cobra" "go.uber.org/zap" + + "github.com/skratchdot/open-golang/open" ) -var username, password, tokenValue, uuid string -var userInfo token.UserInfo +var ( + username, password, tokenValue, uuid string + userInfo token.UserInfo +) -func NewCmd(f *cmdutil.Factory) *cobra.Command { +type login struct { + factory *cmdutil.Factory + askOne func(p survey.Prompt, response interface{}, opts ...survey.AskOpt) error + run func(input string) error + server Server + token token.TokenInterface + marshalToml func(v interface{}) ([]byte, error) +} +func New(f *cmdutil.Factory) *cobra.Command { + return cmd(factory(f)) +} + +func factory(f *cmdutil.Factory) *login { + tk := token.New(&token.Config{Client: f.HttpClient}) + return &login{ + factory: f, + askOne: survey.AskOne, + run: open.Run, + server: &http.Server{Addr: ":8080"}, + token: tk, + marshalToml: toml.Marshal, + } +} + +func cmd(l *login) *cobra.Command { cmd := &cobra.Command{ Use: msg.Usage, Short: msg.ShortDescription, @@ -30,20 +59,19 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { $ azion login --username fulanodasilva@gmail.com --password "senhasecreta" `), RunE: func(cmd *cobra.Command, args []string) error { - - answer, err := selectLoginMode() + answer, err := l.selectLoginMode() if err != nil { return err } switch { case strings.Contains(answer, "browser"): - err := browserLogin(f) + err := l.browserLogin(l.server) if err != nil { return err } case strings.Contains(answer, "terminal"): - err := terminalLogin(cmd, f) + err := l.terminalLogin(cmd) if err != nil { return err } @@ -51,25 +79,20 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { return msg.ErrorInvalidLogin } - client, err := token.New(&token.Config{Client: f.HttpClient}) - if err != nil { - return err - } - - err = validateToken(client, tokenValue) + err = l.validateToken(tokenValue) if err != nil { return err } - err = saveSettings(client) + err = l.saveSettings() if err != nil { return err } loginOut := output.GeneralOutput{ Msg: fmt.Sprintf(msg.Success), - Out: f.IOStreams.Out, - Flags: f.Flags, + Out: l.factory.IOStreams.Out, + Flags: l.factory.Flags, } return output.Print(&loginOut) }, @@ -83,20 +106,20 @@ func NewCmd(f *cmdutil.Factory) *cobra.Command { return cmd } -func selectLoginMode() (string, error) { +func (l *login) selectLoginMode() (string, error) { answer := "" prompt := &survey.Select{ Message: "Choose a login method:", Options: []string{"Log in via browser", "Log in via terminal"}, } - err := survey.AskOne(prompt, &answer) + err := l.askOne(prompt, &answer) if err != nil { return "", err } return answer, nil } -func saveSettings(client *token.Token) error { +func (l *login) saveSettings() error { settings := token.Settings{ UUID: uuid, Token: tokenValue, @@ -104,13 +127,13 @@ func saveSettings(client *token.Token) error { Email: userInfo.Results.Email, } - byteSettings, err := toml.Marshal(settings) + byteSettings, err := l.marshalToml(settings) if err != nil { logger.Debug("Error while marshalling toml file", zap.Error(err)) return err } - _, err = client.Save(byteSettings) + _, err = l.token.Save(byteSettings) if err != nil { logger.Debug("Error while saving settings", zap.Error(err)) return err @@ -118,8 +141,8 @@ func saveSettings(client *token.Token) error { return nil } -func validateToken(client *token.Token, token string) error { - tokenValid, user, err := client.Validate(&token) +func (l *login) validateToken(token string) error { + tokenValid, user, err := l.token.Validate(&token) userInfo = user if err != nil { logger.Debug("Error while validating the token", zap.Error(err)) diff --git a/pkg/cmd/login/mock/login_mock.go b/pkg/cmd/login/mock/login_mock.go new file mode 100644 index 000000000..268b31082 --- /dev/null +++ b/pkg/cmd/login/mock/login_mock.go @@ -0,0 +1,8 @@ +package mock + +import "context" + +type ServerMock struct{} + +func (ServerMock) ListenAndServe() error { return nil } +func (ServerMock) Shutdown(ctx context.Context) error diff --git a/pkg/cmd/login/mock/token_mock.go b/pkg/cmd/login/mock/token_mock.go new file mode 100644 index 000000000..f54b5d608 --- /dev/null +++ b/pkg/cmd/login/mock/token_mock.go @@ -0,0 +1,21 @@ +package mock + +import ( + "net/http" + + "github.com/aziontech/azion-cli/pkg/token" +) + +type TokenMock struct{} + +func Validate(t *string) (bool, token.UserInfo, error) { + return false, token.UserInfo{}, nil +} + +func Save(b []byte) (string, error) { + return "", nil +} + +func Create(b64 string) (*http.Response, error) { + return &http.Response{}, nil +} diff --git a/pkg/cmd/login/terminal.go b/pkg/cmd/login/terminal.go index a8a9d7457..3b81d2d10 100644 --- a/pkg/cmd/login/terminal.go +++ b/pkg/cmd/login/terminal.go @@ -9,17 +9,14 @@ import ( msg "github.com/aziontech/azion-cli/messages/login" api "github.com/aziontech/azion-cli/pkg/api/personal_token" cmdPersToken "github.com/aziontech/azion-cli/pkg/cmd/create/personal_token" - "github.com/aziontech/azion-cli/pkg/cmdutil" "github.com/aziontech/azion-cli/pkg/logger" - "github.com/aziontech/azion-cli/pkg/token" "github.com/aziontech/azion-cli/utils" "github.com/spf13/cobra" "github.com/spf13/viper" "go.uber.org/zap" ) -func terminalLogin(cmd *cobra.Command, f *cmdutil.Factory) error { - +func (l *login) terminalLogin(cmd *cobra.Command) error { if !cmd.Flags().Changed("username") { answer, err := utils.AskInput(msg.AskUsername) if err != nil { @@ -38,18 +35,13 @@ func terminalLogin(cmd *cobra.Command, f *cmdutil.Factory) error { password = answer } - client, err := token.New(&token.Config{Client: f.HttpClient}) - if err != nil { - return err - } - - resp, err := client.Create(b64(username, password)) + resp, err := l.token.Create(b64(username, password)) if err != nil { logger.Debug("Error while creating basic token", zap.Error(err)) return err } - err = validateToken(client, resp.Token) + err = l.validateToken(resp.Token) if err != nil { return err } @@ -66,7 +58,7 @@ func terminalLogin(cmd *cobra.Command, f *cmdutil.Factory) error { request.SetName(username) request.SetExpiresAt(date) - clientPersonalToken := api.NewClient(f.HttpClient, f.Config.GetString("api_url"), f.Config.GetString("token")) + clientPersonalToken := api.NewClient(l.factory.HttpClient, l.factory.Config.GetString("api_url"), l.factory.Config.GetString("token")) response, err := clientPersonalToken.Create(context.Background(), &request) if err != nil { return fmt.Errorf(msg.ErrorLogin.Error(), err.Error()) diff --git a/pkg/cmd/root/pre_command.go b/pkg/cmd/root/pre_command.go index 8110a807e..c339f1b70 100644 --- a/pkg/cmd/root/pre_command.go +++ b/pkg/cmd/root/pre_command.go @@ -47,13 +47,10 @@ func doPreCommandCheck(cmd *cobra.Command, fact *factoryRoot) error { } fact.globalSettings = &settings - t, err := token.New(&token.Config{ + t := token.New(&token.Config{ Client: fact.Factory.HttpClient, Out: fact.Factory.IOStreams.Out, }) - if err != nil { - return fmt.Errorf("%s: %w", utils.ErrorTokenManager, err) - } if cmd.Flags().Changed("token") { if err := checkTokenSent(fact, fact.globalSettings, t); err != nil { @@ -61,8 +58,6 @@ func doPreCommandCheck(cmd *cobra.Command, fact *factoryRoot) error { } } - - if err := checkAuthorizeMetricsCollection(cmd, fact.Factory.GlobalFlagAll, fact.globalSettings); err != nil { return err } diff --git a/pkg/cmd/root/root.go b/pkg/cmd/root/root.go index 7f15b3625..1d0f9dc68 100644 --- a/pkg/cmd/root/root.go +++ b/pkg/cmd/root/root.go @@ -116,7 +116,7 @@ func (fact *factoryRoot) setCmds(cobraCmd *cobra.Command) { cobraCmd.AddCommand(unlink.NewCmd(fact.Factory)) cobraCmd.AddCommand(completion.NewCmd(fact.Factory)) cobraCmd.AddCommand(describe.NewCmd(fact.Factory)) - cobraCmd.AddCommand(login.NewCmd(fact.Factory)) + cobraCmd.AddCommand(login.New(fact.Factory)) cobraCmd.AddCommand(logout.NewCmd(fact.Factory)) cobraCmd.AddCommand(create.NewCmd(fact.Factory)) cobraCmd.AddCommand(list.NewCmd(fact.Factory)) diff --git a/pkg/config/config.go b/pkg/config/config.go index 1562688ac..e528e2c43 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -3,6 +3,7 @@ package config import ( "os" "path/filepath" + "runtime" "github.com/aziontech/azion-cli/messages/root" ) @@ -45,11 +46,8 @@ type DirPath struct { Schedule string } -func Dir() (DirPath, error) { - home, err := os.UserHomeDir() - if err != nil { - return DirPath{}, err - } +func Dir() DirPath { + home := userHomeDir() if pathDir != DEFAULT_DIR { home = "" @@ -61,5 +59,26 @@ func Dir() (DirPath, error) { Metrics: DEFAULT_METRICS, Schedule: DEFAULT_SCHEDULE, } - return dirPath, nil + return dirPath +} + +func userHomeDir() string { + env := "HOME" + switch runtime.GOOS { + case "windows": + env = "USERPROFILE" + case "plan9": + env = "home" + } + if v := os.Getenv(env); v != "" { + return v + } + // On some geese the home directory is not always defined. + switch runtime.GOOS { + case "android": + return "/sdcard" + case "ios": + return "/" + } + return "" } diff --git a/pkg/metric/count.go b/pkg/metric/count.go index dbf4da304..7009886a6 100644 --- a/pkg/metric/count.go +++ b/pkg/metric/count.go @@ -34,11 +34,7 @@ func TotalCommandsCount(cmd *cobra.Command, commandName string, executionTime fl success = false } - dir, err := config.Dir() - if err != nil { - return err - } - + dir := config.Dir() ignoredWords := map[string]bool{ "__complete": true, "completion": true, diff --git a/pkg/metric/segment.go b/pkg/metric/segment.go index 7dcf4bf5b..a7c9bab55 100644 --- a/pkg/metric/segment.go +++ b/pkg/metric/segment.go @@ -18,10 +18,7 @@ import ( const SEGMENT_KEY = "Irg63QfdvWpoANAVeCBEwfxXBKvoSSzt" func location() string { - dir, err := config.Dir() - if err != nil { - logger.Debug("Failed get path file metric.json", zap.Error(err)) - } + dir := config.Dir() return filepath.Join(dir.Dir, dir.Metrics) } diff --git a/pkg/schedule/schedule.go b/pkg/schedule/schedule.go index 1b617f719..bae4c0491 100644 --- a/pkg/schedule/schedule.go +++ b/pkg/schedule/schedule.go @@ -45,20 +45,13 @@ func createFileSchedule(shedule []Schedule) error { if err != nil { return err } - configPath, err := config.Dir() - if err != nil { - return err - } + configPath := config.Dir() path := filepath.Join(configPath.Dir, configPath.Schedule) return os.WriteFile(path, b, os.FileMode(os.O_CREATE)) } func readFileSchedule() ([]Schedule, error) { - configPath, err := config.Dir() - if err != nil { - return nil, err - } - + configPath := config.Dir() schedules := []Schedule{} path := filepath.Join(configPath.Dir, configPath.Schedule) diff --git a/pkg/token/token.go b/pkg/token/token.go index b49cad9f1..6ebbedbda 100644 --- a/pkg/token/token.go +++ b/pkg/token/token.go @@ -18,18 +18,21 @@ import ( "github.com/aziontech/azion-cli/pkg/constants" ) -func New(c *Config) (*Token, error) { - dir, err := config.Dir() - if err != nil { - return nil, err - } +type TokenInterface interface { + Validate(token *string) (bool, UserInfo, error) + Save(b []byte) (string, error) + Create(b64 string) (*Response, error) +} + +func New(c *Config) *Token { + dir := config.Dir() return &Token{ client: c.Client, Endpoint: constants.AuthURL, filePath: filepath.Join(dir.Dir, dir.Settings), out: c.Out, - }, nil + } } func (t *Token) Validate(token *string) (bool, UserInfo, error) { @@ -63,12 +66,8 @@ func (t *Token) Validate(token *string) (bool, UserInfo, error) { } func (t *Token) Save(b []byte) (string, error) { - dir, err := config.Dir() - if err != nil { - return "", err - } - - err = os.MkdirAll(dir.Dir, os.ModePerm) + dir := config.Dir() + err := os.MkdirAll(dir.Dir, os.ModePerm) if err != nil { return "", err } @@ -120,11 +119,7 @@ func (t *Token) Create(b64 string) (*Response, error) { } func WriteSettings(settings Settings) error { - dir, err := config.Dir() - if err != nil { - return fmt.Errorf("Failed to get token dir: %w", err) - } - + dir := config.Dir() b, err := toml.Marshal(settings) if err != nil { return err @@ -143,11 +138,7 @@ func WriteSettings(settings Settings) error { } func ReadSettings() (Settings, error) { - dir, err := config.Dir() - if err != nil { - return Settings{}, fmt.Errorf("failed to get token dir: %w", err) - } - + dir := config.Dir() filePath := filepath.Join(dir.Dir, dir.Settings) // Check if the file exists diff --git a/pkg/vulcan/vulcan.go b/pkg/vulcan/vulcan.go index 63774efae..6d0e8b3ed 100644 --- a/pkg/vulcan/vulcan.go +++ b/pkg/vulcan/vulcan.go @@ -77,11 +77,7 @@ func checkVulcanMajor(currentVersion string, f *cmdutil.Factory, vulcan *VulcanP } config.LastVulcanVersion = currentVersion - client, err := token.New(&token.Config{Client: f.HttpClient}) - if err != nil { - return err - } - + client := token.New(&token.Config{Client: f.HttpClient}) byteSettings, err := toml.Marshal(config) if err != nil { logger.Debug("Error while marshalling settings.toml", zap.Error(err)) From 7341ee97e9eda84e55688a624f5e44cfa5945921 Mon Sep 17 00:00:00 2001 From: maxwelbm Date: Fri, 13 Sep 2024 18:38:13 -0300 Subject: [PATCH 2/6] test: browser test starts --- pkg/cmd/init/init_test.go | 158 +------------------------------ pkg/cmd/login/browser.go | 23 ++++- pkg/cmd/login/login.go | 5 +- pkg/cmd/login/login_mock.go | 15 +++ pkg/cmd/login/login_test.go | 57 +++++++++++ pkg/cmd/login/mock/login_mock.go | 15 ++- pkg/cmd/login/token_mock.go | 21 ++++ pkg/cmd/reset/reset.go | 2 - pkg/cmd/reset/reset_test.go | 3 +- pkg/cmd/root/pre_command_test.go | 2 +- pkg/config/config_test.go | 13 +-- pkg/token/token_test.go | 25 +---- 12 files changed, 137 insertions(+), 202 deletions(-) create mode 100644 pkg/cmd/login/login_mock.go create mode 100644 pkg/cmd/login/login_test.go create mode 100644 pkg/cmd/login/token_mock.go diff --git a/pkg/cmd/init/init_test.go b/pkg/cmd/init/init_test.go index b8cee08ab..3a7602ea7 100644 --- a/pkg/cmd/init/init_test.go +++ b/pkg/cmd/init/init_test.go @@ -64,7 +64,7 @@ func Test_initCmd_Run(t *testing.T) { changeDir func(dir string) error askOne func(p survey.Prompt, response interface{}, opts ...survey.AskOpt) error load func(filenames ...string) (err error) - dir func() (config.DirPath, error) + dir func() config.DirPath mkdirTemp func(dir, pattern string) (string, error) readAll func(r io.Reader) ([]byte, error) get func(url string) (resp *http.Response, err error) @@ -686,160 +686,6 @@ func Test_initCmd_Run(t *testing.T) { }, wantErr: true, }, - { - name: "error dir", - fields: fields{ - auto: true, - f: &cmdutil.Factory{ - Flags: cmdutil.Flags{ - GlobalFlagAll: false, - Format: "", - Out: "", - NoColor: false, - }, - IOStreams: iostreams.System(), - }, - globalFlagAll: false, - name: "", - preset: "vite", - mode: "deliver", - getWorkDir: func() (string, error) { - return "/path/full", nil - }, - get: func(url string) (resp *http.Response, err error) { - b, err := os.ReadFile("./.fixtures/project_samples.json") - if err != nil { - return nil, err - } - - responseBody := io.NopCloser(bytes.NewReader(b)) - resp = &http.Response{ - StatusCode: 200, - Body: responseBody, - Header: make(http.Header), - } - return resp, nil - }, - readAll: io.ReadAll, - unmarshal: json.Unmarshal, - askOne: func(p survey.Prompt, - response interface{}, - opts ...survey.AskOpt, - ) error { - return nil - }, - dir: func() (config.DirPath, error) { - return config.DirPath{}, errors.New("error dir") - }, - mkdirTemp: func(dir, pattern string) (string, error) { - return "", nil - }, - removeAll: os.RemoveAll, - rename: func(oldpath, newpath string) error { - return nil - }, - mkdir: func(path string, perm os.FileMode) error { return nil }, - marshalIndent: json.MarshalIndent, - writeFile: func(filename string, data []byte, perm fs.FileMode) error { - return nil - }, - changeDir: func(dir string) error { return nil }, - commandRunnerOutput: func(f *cmdutil.Factory, comm string, envVars []string) (string, error) { - return "3.2.1", nil - }, - commandRunInteractive: func(f *cmdutil.Factory, comm string) error { - return nil - }, - load: func(filenames ...string) (err error) { - os.Setenv("preset", "vite") - os.Setenv("mode", "deliver") - return nil - }, - git: github.Github{ - Clone: func(url, path string) error { - return nil - }, - }, - }, - wantErr: true, - }, - { - name: "error mkdirTemp", - fields: fields{ - auto: true, - f: &cmdutil.Factory{ - Flags: cmdutil.Flags{ - GlobalFlagAll: false, - Format: "", - Out: "", - NoColor: false, - }, - IOStreams: iostreams.System(), - }, - globalFlagAll: false, - name: "", - preset: "vite", - mode: "deliver", - getWorkDir: func() (string, error) { - return "/path/full", nil - }, - get: func(url string) (resp *http.Response, err error) { - b, err := os.ReadFile("./.fixtures/project_samples.json") - if err != nil { - return nil, err - } - - responseBody := io.NopCloser(bytes.NewReader(b)) - resp = &http.Response{ - StatusCode: 200, - Body: responseBody, - Header: make(http.Header), - } - return resp, nil - }, - readAll: io.ReadAll, - unmarshal: json.Unmarshal, - askOne: func(p survey.Prompt, - response interface{}, - opts ...survey.AskOpt, - ) error { - return nil - }, - dir: func() (config.DirPath, error) { - return config.DirPath{}, errors.New("error dir") - }, - mkdirTemp: func(dir, pattern string) (string, error) { - return "", nil - }, - removeAll: os.RemoveAll, - rename: func(oldpath, newpath string) error { - return nil - }, - mkdir: func(path string, perm os.FileMode) error { return nil }, - marshalIndent: json.MarshalIndent, - writeFile: func(filename string, data []byte, perm fs.FileMode) error { - return nil - }, - changeDir: func(dir string) error { return nil }, - commandRunnerOutput: func(f *cmdutil.Factory, comm string, envVars []string) (string, error) { - return "3.2.1", nil - }, - commandRunInteractive: func(f *cmdutil.Factory, comm string) error { - return nil - }, - load: func(filenames ...string) (err error) { - os.Setenv("preset", "vite") - os.Setenv("mode", "deliver") - return nil - }, - git: github.Github{ - Clone: func(url, path string) error { - return nil - }, - }, - }, - wantErr: true, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -920,7 +766,7 @@ func Test_initCmd_deps(t *testing.T) { changeDir func(dir string) error askOne func(p survey.Prompt, response interface{}, opts ...survey.AskOpt) error load func(filenames ...string) (err error) - dir func() (config.DirPath, error) + dir func() config.DirPath mkdirTemp func(dir, pattern string) (string, error) readAll func(r io.Reader) ([]byte, error) get func(url string) (resp *http.Response, err error) diff --git a/pkg/cmd/login/browser.go b/pkg/cmd/login/browser.go index 48b99724e..72bae38a7 100644 --- a/pkg/cmd/login/browser.go +++ b/pkg/cmd/login/browser.go @@ -19,8 +19,24 @@ type Server interface { Shutdown(ctx context.Context) error } +var ( + globalCtx context.Context + globalCancel context.CancelFunc +) + +func initializeContext() { + globalCtx, globalCancel = context.WithCancel(context.Background()) +} + +func shutdownContext() { + if globalCancel != nil { + globalCancel() + } +} + func (l *login) browserLogin(srv Server) error { - ctx, cancel := context.WithCancel(context.Background()) + initializeContext() + defer shutdownContext() http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { paramValue := r.URL.Query().Get("c") @@ -28,13 +44,14 @@ func (l *login) browserLogin(srv Server) error { if paramValue != "" { tokenValue = paramValue } - cancel() + globalCancel() }) err := l.openBrowser() if err != nil { return err } + go func() { err := srv.ListenAndServe() if err != http.ErrServerClosed { @@ -42,7 +59,7 @@ func (l *login) browserLogin(srv Server) error { } }() - <-ctx.Done() // wait for the signal to gracefully shutdown the server + <-globalCtx.Done() // wait for the signal to gracefully shutdown the server // gracefully shutdown the server: // waiting indefinitely for connections to return to idle and then shut down. diff --git a/pkg/cmd/login/login.go b/pkg/cmd/login/login.go index 586b4ad6b..1de530f2b 100644 --- a/pkg/cmd/login/login.go +++ b/pkg/cmd/login/login.go @@ -106,13 +106,12 @@ func cmd(l *login) *cobra.Command { return cmd } -func (l *login) selectLoginMode() (string, error) { - answer := "" +func (l *login) selectLoginMode() (answer string, err error) { prompt := &survey.Select{ Message: "Choose a login method:", Options: []string{"Log in via browser", "Log in via terminal"}, } - err := l.askOne(prompt, &answer) + err = l.askOne(prompt, &answer) if err != nil { return "", err } diff --git a/pkg/cmd/login/login_mock.go b/pkg/cmd/login/login_mock.go new file mode 100644 index 000000000..533b327e5 --- /dev/null +++ b/pkg/cmd/login/login_mock.go @@ -0,0 +1,15 @@ +package login + +import ( + "context" + "net/http" +) + +type ServerMock struct{} + +func (s *ServerMock) ListenAndServe() error { + shutdownContext() + return http.ErrServerClosed +} + +func (ServerMock) Shutdown(ctx context.Context) error { return nil } diff --git a/pkg/cmd/login/login_test.go b/pkg/cmd/login/login_test.go new file mode 100644 index 000000000..3d0ec5c61 --- /dev/null +++ b/pkg/cmd/login/login_test.go @@ -0,0 +1,57 @@ +package login + +import ( + "fmt" + "testing" + + "github.com/AlecAivazis/survey/v2" + "github.com/aziontech/azion-cli/pkg/httpmock" + "github.com/aziontech/azion-cli/pkg/logger" + "github.com/aziontech/azion-cli/pkg/testutils" + "github.com/spf13/cobra" + "go.uber.org/zap/zapcore" +) + +func Test_cmd(t *testing.T) { + logger.New(zapcore.DebugLevel) + type args struct { + l *login + } + + f, _, _ := testutils.NewFactory(&httpmock.Registry{}) + tests := []struct { + name string + args args + cmd func(l *login) *cobra.Command + }{ + { + name: "success flow", + args: args{ + l: &login{ + factory: f, + askOne: func( + p survey.Prompt, + response interface{}, + opts ...survey.AskOpt, + ) error { + // Usamos type assertion para garantir que 'response' seja um ponteiro para string + if respPtr, ok := response.(*string); ok { + *respPtr = "browser" + } + return nil + }, + run: func(input string) error { return nil }, + server: &ServerMock{}, + }, + }, + cmd: cmd, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cmd := tt.cmd(tt.args.l) + err := cmd.Execute() + fmt.Println(err) + }) + } +} diff --git a/pkg/cmd/login/mock/login_mock.go b/pkg/cmd/login/mock/login_mock.go index 268b31082..a359c8fc7 100644 --- a/pkg/cmd/login/mock/login_mock.go +++ b/pkg/cmd/login/mock/login_mock.go @@ -1,8 +1,17 @@ package mock -import "context" +import ( + "context" + "net/http" +) + +var CancelForce context.CancelFunc type ServerMock struct{} -func (ServerMock) ListenAndServe() error { return nil } -func (ServerMock) Shutdown(ctx context.Context) error +func (s *ServerMock) ListenAndServe() error { + CancelForce() + return http.ErrServerClosed +} + +func (ServerMock) Shutdown(ctx context.Context) error { return nil } diff --git a/pkg/cmd/login/token_mock.go b/pkg/cmd/login/token_mock.go new file mode 100644 index 000000000..aee5642d8 --- /dev/null +++ b/pkg/cmd/login/token_mock.go @@ -0,0 +1,21 @@ +package login + +import ( + "net/http" + + "github.com/aziontech/azion-cli/pkg/token" +) + +type TokenMock struct{} + +func Validate(t *string) (bool, token.UserInfo, error) { + return false, token.UserInfo{}, nil +} + +func Save(b []byte) (string, error) { + return "", nil +} + +func Create(b64 string) (*http.Response, error) { + return &http.Response{}, nil +} diff --git a/pkg/cmd/reset/reset.go b/pkg/cmd/reset/reset.go index 5d05fce07..af4c3d81d 100644 --- a/pkg/cmd/reset/reset.go +++ b/pkg/cmd/reset/reset.go @@ -45,9 +45,7 @@ func NewCobraCmd(reset *ResetCmd, f *cmdutil.Factory) *cobra.Command { return reset.run() }, } - cobraCmd.Flags().BoolP("help", "h", false, msg.FLAGHELP) - return cobraCmd } diff --git a/pkg/cmd/reset/reset_test.go b/pkg/cmd/reset/reset_test.go index de3c1536c..7a3c43258 100644 --- a/pkg/cmd/reset/reset_test.go +++ b/pkg/cmd/reset/reset_test.go @@ -100,15 +100,14 @@ func TestReset(t *testing.T) { mock := &httpmock.Registry{} f, out, _ := testutils.NewFactory(mock) - resetCmd := &ResetCmd{ Io: f.IOStreams, ReadSettings: mockReadSettings, WriteSettings: mockWriteSettings, DeleteToken: mockDeleteToken, } - cmd := NewCobraCmd(resetCmd, f) + cmd := NewCobraCmd(resetCmd, f) _, err := cmd.ExecuteC() if tt.expectedError != nil { require.Error(t, err) diff --git a/pkg/cmd/root/pre_command_test.go b/pkg/cmd/root/pre_command_test.go index 4520598e4..b99e02615 100644 --- a/pkg/cmd/root/pre_command_test.go +++ b/pkg/cmd/root/pre_command_test.go @@ -175,7 +175,7 @@ func TestCheckTokenSent(t *testing.T) { f, _, _ := testutils.NewFactory(mock) tt.args.fact.Factory = f - token, _ := token.New(&token.Config{ + token := token.New(&token.Config{ Client: &http.Client{Transport: mock}, Out: os.Stdout, }) diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 8357b5c69..55b86e340 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -122,13 +122,6 @@ func TestDir(t *testing.T) { }, wantErr: false, }, - { - name: "error getting home dir", - setPath: "", - envHome: "", - wantDir: DirPath{}, - wantErr: true, - }, } for _, tt := range tests { @@ -151,11 +144,7 @@ func TestDir(t *testing.T) { } } - gotDir, err := Dir() - if (err != nil) != tt.wantErr { - t.Errorf("Dir() error = %v, wantErr %v", err, tt.wantErr) - return - } + gotDir := Dir() if gotDir != tt.wantDir { t.Errorf("Dir() = %v, want %v", gotDir, tt.wantDir) } diff --git a/pkg/token/token_test.go b/pkg/token/token_test.go index c62c87ca6..315fba4e0 100644 --- a/pkg/token/token_test.go +++ b/pkg/token/token_test.go @@ -24,13 +24,10 @@ func Test_Validate(t *testing.T) { httpmock.StatusStringResponse(http.StatusUnauthorized, "{}"), ) - token, err := New(&Config{ + token := New(&Config{ Client: &http.Client{Transport: mock}, Out: os.Stdout, }) - if err != nil { - t.Fatalf("NewToken() = %v; want nil", err) - } token.Endpoint = "http://api.azion.net/token" tokenString := "thisIsNotTheValidToken" @@ -48,13 +45,10 @@ func Test_Validate(t *testing.T) { httpmock.StatusStringResponse(http.StatusOK, "{}"), ) - token, err := New(&Config{ + token := New(&Config{ Client: &http.Client{Transport: mock}, Out: os.Stdout, }) - if err != nil { - t.Fatalf("NewToken() = %v; want nil", err) - } token.Endpoint = "http://api.azion.net/token" tokenString := "rightToken" @@ -76,14 +70,10 @@ func Test_Save(t *testing.T) { } t.Run("save token to disk", func(t *testing.T) { - token, err := New(&Config{ + token := New(&Config{ Out: os.Stdout, }) - if err != nil { - t.Fatalf("New() = %v; want nil", err) - } - settings := Settings{ Token: "asdfdsafsdfasd", UUID: "asdfadsfads", @@ -108,13 +98,10 @@ func Test_Create(t *testing.T) { httpmock.JSONFromFile("./fixtures/response.json"), ) - token, err := New(&Config{ + token := New(&Config{ Client: &http.Client{Transport: mock}, Out: os.Stdout, }) - if err != nil { - t.Fatalf("NewToken() = %v; want nil", err) - } token.Endpoint = "http://api.azion.net/token" response, err := token.Create("base64Credentials") @@ -147,9 +134,7 @@ func Test_WriteSettings(t *testing.T) { t.Fatalf("WriteSettings() = %v; want nil", err) } - dir, err := config.Dir() - require.NoError(t, err) - + dir := config.Dir() data, err := os.ReadFile(filepath.Join(dir.Dir, dir.Settings)) require.NoError(t, err) From e7336e4cd01719a9527ac45283d8598c09fef6d4 Mon Sep 17 00:00:00 2001 From: maxwelbm Date: Tue, 17 Sep 2024 07:06:12 -0300 Subject: [PATCH 3/6] test: browser command login --- pkg/cmd/login/.fixtures/response.json | 9 +++ pkg/cmd/login/browser.go | 21 +++--- pkg/cmd/login/browser_test.go | 88 ++++++++++++++++++++++++ pkg/cmd/login/login.go | 5 ++ pkg/cmd/login/login_mock.go | 20 +++++- pkg/cmd/login/login_test.go | 60 ++++++++++++++--- pkg/cmd/login/mock/login_mock.go | 17 ----- pkg/cmd/login/mock/token_mock.go | 21 ------ pkg/cmd/login/terminal.go | 5 +- pkg/cmd/login/terminal_test.go | 96 +++++++++++++++++++++++++++ pkg/cmd/login/token_mock.go | 21 ------ pkg/token/fixtures/response.json | 2 +- pkg/token/token_mock.go | 16 +++++ 13 files changed, 298 insertions(+), 83 deletions(-) create mode 100644 pkg/cmd/login/.fixtures/response.json create mode 100644 pkg/cmd/login/browser_test.go delete mode 100644 pkg/cmd/login/mock/login_mock.go delete mode 100644 pkg/cmd/login/mock/token_mock.go create mode 100644 pkg/cmd/login/terminal_test.go delete mode 100644 pkg/cmd/login/token_mock.go create mode 100644 pkg/token/token_mock.go diff --git a/pkg/cmd/login/.fixtures/response.json b/pkg/cmd/login/.fixtures/response.json new file mode 100644 index 000000000..add57072d --- /dev/null +++ b/pkg/cmd/login/.fixtures/response.json @@ -0,0 +1,9 @@ +{ + "uuid": "5b8934cf-3561-4b48-aceb-7ba52a227b6c", + "name": "One day token", + "key": "tokenazion", + "user_id": 23192, + "created": "2023-08-29T15:23:41.878136Z", + "expires_at": "2024-07-26T00:00:00Z", + "description": "example" +} diff --git a/pkg/cmd/login/browser.go b/pkg/cmd/login/browser.go index 72bae38a7..1f6025d87 100644 --- a/pkg/cmd/login/browser.go +++ b/pkg/cmd/login/browser.go @@ -14,6 +14,9 @@ const ( urlSsoNext = "https://sso.azion.com/login?next=cli" ) +// quando for test unitario setar true +var enableHandlerRouter = true + type Server interface { ListenAndServe() error Shutdown(ctx context.Context) error @@ -38,14 +41,16 @@ func (l *login) browserLogin(srv Server) error { initializeContext() defer shutdownContext() - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - paramValue := r.URL.Query().Get("c") - _, _ = io.WriteString(w, msg.BrowserMsg) - if paramValue != "" { - tokenValue = paramValue - } - globalCancel() - }) + if enableHandlerRouter { + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + paramValue := r.URL.Query().Get("c") + _, _ = io.WriteString(w, msg.BrowserMsg) + if paramValue != "" { + tokenValue = paramValue + } + globalCancel() + }) + } err := l.openBrowser() if err != nil { diff --git a/pkg/cmd/login/browser_test.go b/pkg/cmd/login/browser_test.go new file mode 100644 index 000000000..050dd215a --- /dev/null +++ b/pkg/cmd/login/browser_test.go @@ -0,0 +1,88 @@ +package login + +import ( + "testing" + + "github.com/AlecAivazis/survey/v2" + "github.com/aziontech/azion-cli/pkg/cmdutil" + "github.com/aziontech/azion-cli/pkg/httpmock" + "github.com/aziontech/azion-cli/pkg/logger" + "github.com/aziontech/azion-cli/pkg/testutils" + "github.com/aziontech/azion-cli/pkg/token" + "github.com/pkg/errors" + "go.uber.org/zap/zapcore" +) + +func Test_login_browserLogin(t *testing.T) { + logger.New(zapcore.DebugLevel) + + type fields struct { + factory *cmdutil.Factory + askOne func(p survey.Prompt, response interface{}, opts ...survey.AskOpt) error + run func(input string) error + server Server + token token.TokenInterface + marshalToml func(v interface{}) ([]byte, error) + askInput func(msg string) (string, error) + } + type args struct { + srv Server + } + tests := []struct { + name string + fields fields + args args + wantErr bool + }{ + { + name: "error Open browser", + fields: fields{ + run: func(input string) error { + return errors.New("error open browser") + }, + }, + args: args{ + srv: &ServerMock{ + Cancel: true, + ErrorListenAndServer: nil, + ErrorShutdown: nil, + }, + }, + wantErr: true, + }, + { + name: "error shotdown", + fields: fields{ + run: func(input string) error { + return nil + }, + }, + args: args{ + srv: &ServerMock{ + Cancel: true, + ErrorListenAndServer: nil, + ErrorShutdown: errors.Errorf("iiiisssssh"), + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f, _, _ := testutils.NewFactory(&httpmock.Registry{}) + l := &login{ + factory: f, + askOne: tt.fields.askOne, + run: tt.fields.run, + server: tt.fields.server, + token: tt.fields.token, + marshalToml: tt.fields.marshalToml, + askInput: tt.fields.askInput, + } + enableHandlerRouter = false + if err := l.browserLogin(tt.args.srv); (err != nil) != tt.wantErr { + t.Errorf("login.browserLogin() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/pkg/cmd/login/login.go b/pkg/cmd/login/login.go index 1de530f2b..3715e6667 100644 --- a/pkg/cmd/login/login.go +++ b/pkg/cmd/login/login.go @@ -12,6 +12,7 @@ import ( "github.com/aziontech/azion-cli/pkg/logger" "github.com/aziontech/azion-cli/pkg/output" "github.com/aziontech/azion-cli/pkg/token" + "github.com/aziontech/azion-cli/utils" "github.com/pelletier/go-toml/v2" "github.com/spf13/cobra" "go.uber.org/zap" @@ -31,6 +32,8 @@ type login struct { server Server token token.TokenInterface marshalToml func(v interface{}) ([]byte, error) + askInput func(msg string) (string, error) + askPassword func(msg string) (string, error) } func New(f *cmdutil.Factory) *cobra.Command { @@ -46,6 +49,8 @@ func factory(f *cmdutil.Factory) *login { server: &http.Server{Addr: ":8080"}, token: tk, marshalToml: toml.Marshal, + askInput: utils.AskInput, + askPassword: utils.AskPassword, } } diff --git a/pkg/cmd/login/login_mock.go b/pkg/cmd/login/login_mock.go index 533b327e5..7b47d0253 100644 --- a/pkg/cmd/login/login_mock.go +++ b/pkg/cmd/login/login_mock.go @@ -5,11 +5,25 @@ import ( "net/http" ) -type ServerMock struct{} +type ServerMock struct { + Cancel bool + ErrorListenAndServer error + ErrorShutdown error +} func (s *ServerMock) ListenAndServe() error { - shutdownContext() + if s.Cancel { + shutdownContext() + } + if s.ErrorListenAndServer != nil { + return s.ErrorListenAndServer + } return http.ErrServerClosed } -func (ServerMock) Shutdown(ctx context.Context) error { return nil } +func (s *ServerMock) Shutdown(ctx context.Context) error { + if s.ErrorShutdown != nil { + return s.ErrorShutdown + } + return nil +} diff --git a/pkg/cmd/login/login_test.go b/pkg/cmd/login/login_test.go index 3d0ec5c61..924fe1897 100644 --- a/pkg/cmd/login/login_test.go +++ b/pkg/cmd/login/login_test.go @@ -1,31 +1,34 @@ package login import ( - "fmt" + "errors" "testing" "github.com/AlecAivazis/survey/v2" "github.com/aziontech/azion-cli/pkg/httpmock" "github.com/aziontech/azion-cli/pkg/logger" "github.com/aziontech/azion-cli/pkg/testutils" + "github.com/aziontech/azion-cli/pkg/token" "github.com/spf13/cobra" "go.uber.org/zap/zapcore" ) func Test_cmd(t *testing.T) { logger.New(zapcore.DebugLevel) + type args struct { l *login } f, _, _ := testutils.NewFactory(&httpmock.Registry{}) tests := []struct { - name string - args args - cmd func(l *login) *cobra.Command + name string + args args + cmd func(l *login) *cobra.Command + wantErr bool }{ { - name: "success flow", + name: "success flow browser", args: args{ l: &login{ factory: f, @@ -41,17 +44,56 @@ func Test_cmd(t *testing.T) { return nil }, run: func(input string) error { return nil }, - server: &ServerMock{}, + server: &ServerMock{Cancel: true}, + token: &token.TokenMock{}, + marshalToml: func(v interface{}) ([]byte, error) { + return []byte(""), nil + }, }, }, - cmd: cmd, + cmd: cmd, + wantErr: false, + }, + { + name: "error select login mode", + args: args{ + l: &login{ + factory: f, + askOne: func( + p survey.Prompt, + response interface{}, + opts ...survey.AskOpt, + ) error { + // Usamos type assertion para garantir que 'response' seja um ponteiro para string + if respPtr, ok := response.(*string); ok { + *respPtr = "browser" + } + return errors.New("error select login mode") + }, + run: func(input string) error { return nil }, + server: &ServerMock{Cancel: true}, + token: &token.TokenMock{}, + marshalToml: func(v interface{}) ([]byte, error) { + return []byte(""), nil + }, + }, + }, + cmd: cmd, + wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { cmd := tt.cmd(tt.args.l) - err := cmd.Execute() - fmt.Println(err) + if err := cmd.Execute(); (err != nil) != tt.wantErr { + t.Errorf("error = %v, wantErr %v", err, tt.wantErr) + } }) } } + +func Test_New(t *testing.T) { + mock := &httpmock.Registry{} + f, _, _ := testutils.NewFactory(mock) + New(f) +} diff --git a/pkg/cmd/login/mock/login_mock.go b/pkg/cmd/login/mock/login_mock.go deleted file mode 100644 index a359c8fc7..000000000 --- a/pkg/cmd/login/mock/login_mock.go +++ /dev/null @@ -1,17 +0,0 @@ -package mock - -import ( - "context" - "net/http" -) - -var CancelForce context.CancelFunc - -type ServerMock struct{} - -func (s *ServerMock) ListenAndServe() error { - CancelForce() - return http.ErrServerClosed -} - -func (ServerMock) Shutdown(ctx context.Context) error { return nil } diff --git a/pkg/cmd/login/mock/token_mock.go b/pkg/cmd/login/mock/token_mock.go deleted file mode 100644 index f54b5d608..000000000 --- a/pkg/cmd/login/mock/token_mock.go +++ /dev/null @@ -1,21 +0,0 @@ -package mock - -import ( - "net/http" - - "github.com/aziontech/azion-cli/pkg/token" -) - -type TokenMock struct{} - -func Validate(t *string) (bool, token.UserInfo, error) { - return false, token.UserInfo{}, nil -} - -func Save(b []byte) (string, error) { - return "", nil -} - -func Create(b64 string) (*http.Response, error) { - return &http.Response{}, nil -} diff --git a/pkg/cmd/login/terminal.go b/pkg/cmd/login/terminal.go index 3b81d2d10..a63b9dfc2 100644 --- a/pkg/cmd/login/terminal.go +++ b/pkg/cmd/login/terminal.go @@ -18,7 +18,7 @@ import ( func (l *login) terminalLogin(cmd *cobra.Command) error { if !cmd.Flags().Changed("username") { - answer, err := utils.AskInput(msg.AskUsername) + answer, err := l.askInput(msg.AskUsername) if err != nil { return err } @@ -27,7 +27,7 @@ func (l *login) terminalLogin(cmd *cobra.Command) error { } if !cmd.Flags().Changed("password") { - answer, err := utils.AskPassword(msg.AskPassword) + answer, err := l.askPassword(msg.AskPassword) if err != nil { return err } @@ -57,7 +57,6 @@ func (l *login) terminalLogin(cmd *cobra.Command) error { request := api.Request{} request.SetName(username) request.SetExpiresAt(date) - clientPersonalToken := api.NewClient(l.factory.HttpClient, l.factory.Config.GetString("api_url"), l.factory.Config.GetString("token")) response, err := clientPersonalToken.Create(context.Background(), &request) if err != nil { diff --git a/pkg/cmd/login/terminal_test.go b/pkg/cmd/login/terminal_test.go new file mode 100644 index 000000000..bd01a934b --- /dev/null +++ b/pkg/cmd/login/terminal_test.go @@ -0,0 +1,96 @@ +package login + +import ( + "testing" + + "github.com/AlecAivazis/survey/v2" + "github.com/aziontech/azion-cli/pkg/cmdutil" + "github.com/aziontech/azion-cli/pkg/httpmock" + "github.com/aziontech/azion-cli/pkg/logger" + "github.com/aziontech/azion-cli/pkg/testutils" + "github.com/aziontech/azion-cli/pkg/token" + "go.uber.org/zap/zapcore" +) + +func Test_login_terminalLogin(t *testing.T) { + logger.New(zapcore.DebugLevel) + + type fields struct { + factory *cmdutil.Factory + askOne func(p survey.Prompt, response interface{}, opts ...survey.AskOpt) error + run func(input string) error + server Server + token token.TokenInterface + marshalToml func(v interface{}) ([]byte, error) + askInput func(msg string) (string, error) + askPassword func(msg string) (string, error) + } + + type register struct { + matcher httpmock.Matcher + reponder httpmock.Responder + } + + tests := []struct { + name string + fields fields + flags []string + register register + wantErr bool + }{ + { + name: "success flow", + fields: fields{ + run: func(input string) error { + return nil + }, + askOne: func( + p survey.Prompt, + response interface{}, + opts ...survey.AskOpt, + ) error { + // Usamos type assertion para garantir que 'response' seja um ponteiro para string + if respPtr, ok := response.(*string); ok { + *respPtr = "terminal" + } + return nil + }, + askInput: func(msg string) (string, error) { + return "admin", nil + }, + askPassword: func(msg string) (string, error) { + return "admin", nil + }, + token: &token.TokenMock{}, + }, + flags: []string{"--username", "max", "--password", "1235"}, + register: register{ + httpmock.REST("POST", "iam/personal_tokens"), + httpmock.JSONFromFile("./fixtures/response.json"), + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + mock := &httpmock.Registry{} + mock.Register(tt.register.matcher, tt.register.reponder) + f, _, _ := testutils.NewFactory(mock) + l := &login{ + factory: f, + askOne: tt.fields.askOne, + run: tt.fields.run, + server: tt.fields.server, + token: tt.fields.token, + marshalToml: tt.fields.marshalToml, + askInput: tt.fields.askInput, + askPassword: tt.fields.askPassword, + } + cmd := cmd(l) + cmd.SetArgs(tt.flags) + if err := l.terminalLogin(cmd); (err != nil) != tt.wantErr { + t.Errorf("login.terminalLogin() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/pkg/cmd/login/token_mock.go b/pkg/cmd/login/token_mock.go deleted file mode 100644 index aee5642d8..000000000 --- a/pkg/cmd/login/token_mock.go +++ /dev/null @@ -1,21 +0,0 @@ -package login - -import ( - "net/http" - - "github.com/aziontech/azion-cli/pkg/token" -) - -type TokenMock struct{} - -func Validate(t *string) (bool, token.UserInfo, error) { - return false, token.UserInfo{}, nil -} - -func Save(b []byte) (string, error) { - return "", nil -} - -func Create(b64 string) (*http.Response, error) { - return &http.Response{}, nil -} diff --git a/pkg/token/fixtures/response.json b/pkg/token/fixtures/response.json index 9c7539204..1a87e02b0 100644 --- a/pkg/token/fixtures/response.json +++ b/pkg/token/fixtures/response.json @@ -1,3 +1,3 @@ { "Token": "123321" -} \ No newline at end of file +} diff --git a/pkg/token/token_mock.go b/pkg/token/token_mock.go new file mode 100644 index 000000000..e8e31b57f --- /dev/null +++ b/pkg/token/token_mock.go @@ -0,0 +1,16 @@ +package token + +type TokenMock struct { +} + +func (m *TokenMock) Validate(token *string) (bool, UserInfo, error) { + return true, UserInfo{}, nil +} + +func (m *TokenMock) Save(b []byte) (string, error) { + return "", nil +} + +func (m *TokenMock) Create(b64 string) (*Response, error) { + return &Response{}, nil +} From 9e3059a7f9868f12a49bf47926b4dfcbee3cfd00 Mon Sep 17 00:00:00 2001 From: maxwelbm Date: Tue, 17 Sep 2024 07:56:28 -0300 Subject: [PATCH 4/6] test: terminal test command login --- pkg/cmd/login/terminal_test.go | 40 ++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/pkg/cmd/login/terminal_test.go b/pkg/cmd/login/terminal_test.go index bd01a934b..e57642e17 100644 --- a/pkg/cmd/login/terminal_test.go +++ b/pkg/cmd/login/terminal_test.go @@ -40,6 +40,35 @@ func Test_login_terminalLogin(t *testing.T) { }{ { name: "success flow", + fields: fields{ + run: func(input string) error { + return nil + }, + askOne: func( + p survey.Prompt, + response interface{}, + opts ...survey.AskOpt, + ) error { + // Usamos type assertion para garantir que 'response' seja um ponteiro para string + if respPtr, ok := response.(*string); ok { + *respPtr = "terminal" + } + return nil + }, + token: &token.TokenMock{}, + marshalToml: func(v interface{}) ([]byte, error) { + return []byte(""), nil + }, + }, + flags: []string{"--username", "max", "--password", "1235"}, + register: register{ + httpmock.REST("POST", "iam/personal_tokens"), + httpmock.JSONFromFile("./.fixtures/response.json"), + }, + wantErr: false, + }, + { + name: "success flow, no informed flags", fields: fields{ run: func(input string) error { return nil @@ -62,11 +91,14 @@ func Test_login_terminalLogin(t *testing.T) { return "admin", nil }, token: &token.TokenMock{}, + marshalToml: func(v interface{}) ([]byte, error) { + return []byte(""), nil + }, }, - flags: []string{"--username", "max", "--password", "1235"}, + flags: []string{}, register: register{ httpmock.REST("POST", "iam/personal_tokens"), - httpmock.JSONFromFile("./fixtures/response.json"), + httpmock.JSONFromFile("./.fixtures/response.json"), }, wantErr: false, }, @@ -88,8 +120,8 @@ func Test_login_terminalLogin(t *testing.T) { } cmd := cmd(l) cmd.SetArgs(tt.flags) - if err := l.terminalLogin(cmd); (err != nil) != tt.wantErr { - t.Errorf("login.terminalLogin() error = %v, wantErr %v", err, tt.wantErr) + if err := cmd.Execute(); (err != nil) != tt.wantErr { + t.Errorf("error = %v, wantErr %v", err, tt.wantErr) } }) } From 9baf9a2c64c4b552d98d347dec843848e49e2ab0 Mon Sep 17 00:00:00 2001 From: maxwelbm Date: Tue, 17 Sep 2024 08:01:19 -0300 Subject: [PATCH 5/6] refactor: lint --- pkg/cmd/login/browser_test.go | 2 -- pkg/cmd/login/terminal_test.go | 2 -- 2 files changed, 4 deletions(-) diff --git a/pkg/cmd/login/browser_test.go b/pkg/cmd/login/browser_test.go index 050dd215a..bbaa38a2b 100644 --- a/pkg/cmd/login/browser_test.go +++ b/pkg/cmd/login/browser_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/AlecAivazis/survey/v2" - "github.com/aziontech/azion-cli/pkg/cmdutil" "github.com/aziontech/azion-cli/pkg/httpmock" "github.com/aziontech/azion-cli/pkg/logger" "github.com/aziontech/azion-cli/pkg/testutils" @@ -17,7 +16,6 @@ func Test_login_browserLogin(t *testing.T) { logger.New(zapcore.DebugLevel) type fields struct { - factory *cmdutil.Factory askOne func(p survey.Prompt, response interface{}, opts ...survey.AskOpt) error run func(input string) error server Server diff --git a/pkg/cmd/login/terminal_test.go b/pkg/cmd/login/terminal_test.go index e57642e17..2478cb221 100644 --- a/pkg/cmd/login/terminal_test.go +++ b/pkg/cmd/login/terminal_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/AlecAivazis/survey/v2" - "github.com/aziontech/azion-cli/pkg/cmdutil" "github.com/aziontech/azion-cli/pkg/httpmock" "github.com/aziontech/azion-cli/pkg/logger" "github.com/aziontech/azion-cli/pkg/testutils" @@ -16,7 +15,6 @@ func Test_login_terminalLogin(t *testing.T) { logger.New(zapcore.DebugLevel) type fields struct { - factory *cmdutil.Factory askOne func(p survey.Prompt, response interface{}, opts ...survey.AskOpt) error run func(input string) error server Server From 05b0f6ed90c18f43b6290454700204d027c3f2c5 Mon Sep 17 00:00:00 2001 From: Maxwel Mazur <52722027+maxwelbm@users.noreply.github.com> Date: Tue, 17 Sep 2024 10:37:28 -0300 Subject: [PATCH 6/6] chore: change comment to english --- pkg/cmd/login/browser.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cmd/login/browser.go b/pkg/cmd/login/browser.go index 1f6025d87..deb9abb5c 100644 --- a/pkg/cmd/login/browser.go +++ b/pkg/cmd/login/browser.go @@ -14,7 +14,7 @@ const ( urlSsoNext = "https://sso.azion.com/login?next=cli" ) -// quando for test unitario setar true +// when it's a single test set true var enableHandlerRouter = true type Server interface {