mirror of
https://github.com/Slug-Boi/cocommit.git
synced 2026-05-13 12:45:47 +00:00
Merge branch 'main' of https://github.com/Slug-Boi/cocommit
This commit is contained in:
+15
-2
@@ -27,6 +27,7 @@ This will require the user to have commitizen installed on their system.`,
|
||||
cflag, _ := cmd.Flags().GetBool("cli")
|
||||
gflag, _ := cmd.Flags().GetString("git")
|
||||
gpflag, _ := cmd.Flags().GetBool("git-push")
|
||||
gpflagsflag, _ := cmd.Flags().GetString("git-push-flags")
|
||||
|
||||
// run execute commands again as root run will not call this part
|
||||
message = utils.Cz_Call()
|
||||
@@ -53,7 +54,10 @@ This will require the user to have commitizen installed on their system.`,
|
||||
if gflag != "" {
|
||||
git_flags = strings.Split(gflag, " ")
|
||||
}
|
||||
utils.GitWrapper(message, git_flags)
|
||||
err := utils.GitWrapper(message, git_flags)
|
||||
if err != nil {
|
||||
fmt.Println("Error committing:", err)
|
||||
}
|
||||
|
||||
if update {
|
||||
update_msg()
|
||||
@@ -63,8 +67,16 @@ This will require the user to have commitizen installed on their system.`,
|
||||
fmt.Println(message)
|
||||
}
|
||||
|
||||
var gp_flags []string
|
||||
if gpflagsflag != "" {
|
||||
gp_flags = strings.Split(gpflagsflag, " ")
|
||||
}
|
||||
|
||||
if gpflag {
|
||||
utils.GitPush()
|
||||
err := utils.GitPush(gp_flags)
|
||||
if err != nil {
|
||||
fmt.Println("Error pushing to git:", err)
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -75,4 +87,5 @@ func init() {
|
||||
czCmd.Flags().BoolP("print-output", "o", false, "Print the commit message")
|
||||
czCmd.Flags().BoolP("cli", "c", false, "[co-author1] [co-author2] ...")
|
||||
czCmd.Flags().BoolP("git-push", "p", false, "Runs the git push command after the commit")
|
||||
czCmd.Flags().StringP("git-push-flags", "f", "", "Passes the flags specified to the git push command")
|
||||
}
|
||||
|
||||
+20
-4
@@ -56,6 +56,7 @@ var rootCmd = &cobra.Command{
|
||||
vflag, _ := cmd.Flags().GetBool("version")
|
||||
gflag, _ := cmd.Flags().GetString("git")
|
||||
gpflag, _ := cmd.Flags().GetBool("git-push")
|
||||
gpflagsflag, _ := cmd.Flags().GetString("git-push-flags")
|
||||
|
||||
if vflag {
|
||||
fmt.Println("Cocommit version:", Coco_Version)
|
||||
@@ -109,13 +110,24 @@ var rootCmd = &cobra.Command{
|
||||
return
|
||||
}
|
||||
|
||||
utils.GitWrapper(message, git_flags)
|
||||
err := utils.GitWrapper(message, git_flags)
|
||||
if err != nil {
|
||||
fmt.Println("Error committing:", err)
|
||||
}
|
||||
// prints the commit message to the console if the print flag is set
|
||||
if pflag {
|
||||
fmt.Println(message)
|
||||
}
|
||||
var gp_flags []string
|
||||
if gpflagsflag != "" {
|
||||
gp_flags = strings.Split(gpflagsflag, " ")
|
||||
}
|
||||
|
||||
if gpflag {
|
||||
utils.GitPush()
|
||||
err := utils.GitPush(gp_flags)
|
||||
if err != nil {
|
||||
fmt.Println("Error pushing to remote:", err)
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -127,11 +139,14 @@ func Execute() {
|
||||
check_update()
|
||||
|
||||
// author file check
|
||||
author_file := utils.CheckAuthorFile()
|
||||
author_file, err := utils.CheckAuthorFile(os.Stdin, os.Stdout)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Error checking author file: %v", err))
|
||||
}
|
||||
// define users
|
||||
utils.Define_users(author_file)
|
||||
|
||||
err := rootCmd.Execute()
|
||||
err = rootCmd.Execute()
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
@@ -185,4 +200,5 @@ func init() {
|
||||
rootCmd.Flags().BoolP("version", "v", false, "Prints the version of the cocommit cli tool")
|
||||
rootCmd.Flags().StringP("git", "g", "", "Adds the given flags to the git command")
|
||||
rootCmd.Flags().BoolP("git-push", "p", false, "Runs git push after the commit")
|
||||
rootCmd.Flags().StringP("git-push-flags", "f", "", "Adds the given flags to the git push command")
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ func errorGetMissingFields(m model_ca) {
|
||||
}
|
||||
|
||||
if len(m.inputs) > 0 {
|
||||
for i := 0; i < inpLen; i++ {
|
||||
for i := 0; i < inpLen-1; i++ {
|
||||
if m.inputs[i].Value() == "" {
|
||||
m.errorModel.missing = append(m.errorModel.missing, "- "+strings.Split(m.inputs[i].Placeholder," (")[0])
|
||||
}
|
||||
|
||||
@@ -87,8 +87,7 @@ func intialModel_US(author_file string) tea.Model {
|
||||
|
||||
model, err := newExample()
|
||||
if err != nil {
|
||||
fmt.Println("Could not initialize Bubble Tea model:", err)
|
||||
os.Exit(1)
|
||||
panic(fmt.Sprintf("Could not initialize Bubble Tea model: %v", err))
|
||||
}
|
||||
return model
|
||||
}
|
||||
@@ -96,8 +95,7 @@ func intialModel_US(author_file string) tea.Model {
|
||||
func loadData(author_file string) {
|
||||
file, err := os.Open(author_file)
|
||||
if err != nil {
|
||||
fmt.Println("Could not open file:", err)
|
||||
os.Exit(1)
|
||||
panic(fmt.Sprintf("Could not open author file: %v", err))
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
|
||||
+247
-6
@@ -2,12 +2,14 @@ package tui
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Slug-Boi/cocommit/src/cmd/utils"
|
||||
"github.com/charmbracelet/bubbles/textinput"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/x/exp/teatest"
|
||||
)
|
||||
@@ -77,12 +79,47 @@ func TestShowUser(t *testing.T) {
|
||||
return bytes.Contains(bts, []byte("\"Authors\": {"))
|
||||
}, teatest.WithCheckInterval(time.Millisecond*100), teatest.WithDuration(time.Second*2))
|
||||
|
||||
keyPress(tm, "enter")
|
||||
|
||||
keyPress(tm, "q")
|
||||
|
||||
tm.WaitFinished(t, teatest.WithFinalTimeout(time.Second))
|
||||
|
||||
}
|
||||
|
||||
func TestShowUserPanicFileNotFound(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
// Use defer with recover to catch panics
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
t.Logf("Recovered from expected panic: %v", r)
|
||||
// You can optionally verify the panic message here
|
||||
if !strings.Contains(fmt.Sprint(r), "Could not open author file:") {
|
||||
t.Errorf("Unexpected panic message: %v", r)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
m := intialModel_US("non_existent_file")
|
||||
tm := teatest.NewTestModel(
|
||||
t, m,
|
||||
teatest.WithInitialTermSize(300, 300),
|
||||
)
|
||||
|
||||
// Verify error message appears in output
|
||||
teatest.WaitFor(t, tm.Output(), func(bts []byte) bool {
|
||||
return bytes.Contains(bts, []byte("could not open author file"))
|
||||
}, teatest.WithCheckInterval(time.Millisecond*100), teatest.WithDuration(time.Second*2))
|
||||
|
||||
// Send quit command
|
||||
keyPress(tm, "q")
|
||||
|
||||
// Wait for clean shutdown
|
||||
tm.WaitFinished(t, teatest.WithFinalTimeout(time.Second))
|
||||
}
|
||||
|
||||
// tui_show_users TESTS END
|
||||
|
||||
// tui_author TESTS BEGIN
|
||||
@@ -132,6 +169,89 @@ func TestEntryTA(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorGetMissingFields(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
// Test case 1: No inputs
|
||||
m := createAuthorModel(nil)
|
||||
errorGetMissingFields(m)
|
||||
if len(m.errorModel.missing) != 4 {
|
||||
t.Errorf("Expected 4 missing fields, got %d\n%v", len(m.errorModel.missing), m.errorModel.missing)
|
||||
}
|
||||
|
||||
m = createAuthorModel(nil)
|
||||
|
||||
m.inputs[0].SetValue("")
|
||||
m.inputs[1].SetValue("value")
|
||||
m.inputs[2].SetValue("")
|
||||
m.inputs[3].SetValue("value")
|
||||
|
||||
tempAuthorToggle = false
|
||||
errorGetMissingFields(m)
|
||||
expectedMissing := []string{"- Shortname", "- Username"}
|
||||
if len(m.errorModel.missing) != len(expectedMissing) {
|
||||
t.Errorf("Expected %d missing fields, got %d", len(expectedMissing), len(m.errorModel.missing))
|
||||
}
|
||||
for i, missing := range expectedMissing {
|
||||
if m.errorModel.missing[i] != missing {
|
||||
t.Errorf("Expected '%s', got '%s'", missing, m.errorModel.missing[i])
|
||||
}
|
||||
}
|
||||
|
||||
m = createAuthorModel(nil)
|
||||
|
||||
m.inputs[0].SetValue("value1")
|
||||
m.inputs[1].SetValue("value2")
|
||||
m.inputs[2].SetValue("value3")
|
||||
m.inputs[3].SetValue("value4")
|
||||
m.inputs[4].SetValue("value5")
|
||||
|
||||
tempAuthorToggle = true
|
||||
errorGetMissingFields(m)
|
||||
if len(m.errorModel.missing) != 0 {
|
||||
t.Errorf("Expected no missing fields, got %v", m.errorModel.missing)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_EntryCA_TriggerError(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
m := listModel()
|
||||
|
||||
tm := teatest.NewTestModel(
|
||||
t, m, teatest.WithInitialTermSize(300, 300),
|
||||
)
|
||||
keyPress(tm, "C")
|
||||
|
||||
keyPress(tm, "enter")
|
||||
|
||||
tm.Type("test")
|
||||
|
||||
keyPress(tm, "enter")
|
||||
|
||||
tm.Type("testing2")
|
||||
keyPress(tm, "enter")
|
||||
|
||||
keyPress(tm, "enter")
|
||||
keyPress(tm, "tab")
|
||||
keyPress(tm, "enter")
|
||||
keyPress(tm, "esc")
|
||||
keyPress(tm, "esc")
|
||||
keyPress(tm, "esc")
|
||||
|
||||
fm := tm.FinalModel(t)
|
||||
mm, ok := fm.(model)
|
||||
if !ok {
|
||||
t.Errorf("Expected model_ca, got %T", fm)
|
||||
}
|
||||
|
||||
if len(mm.list.Items()) != 2 {
|
||||
t.Errorf("Expected 2 inputs, got %d\n%v", len(mm.list.Items()), mm.list.Items())
|
||||
}
|
||||
}
|
||||
|
||||
func Test_EntryCA(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
@@ -196,6 +316,67 @@ func Test_EntryCA(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestModelCAInit(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
m := model_ca{}
|
||||
cmd := m.Init()
|
||||
|
||||
if cmd == nil {
|
||||
t.Errorf("Expected a non-nil command, got nil")
|
||||
}
|
||||
|
||||
if cmd() != textinput.Blink() {
|
||||
t.Errorf("Expected textinput.Blink command, got a different command")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func TestCreateGHAuthorModel(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
// Define a test user
|
||||
testUser := utils.User{
|
||||
Shortname: "gh",
|
||||
Longname: "GitHubUser",
|
||||
Username: "GitHubUser-gh",
|
||||
Email: "github@user.com",
|
||||
Groups: []string{"grp1", "grp2"},
|
||||
}
|
||||
|
||||
// Create the model using the test user
|
||||
m := createGHAuthorModel(nil, testUser)
|
||||
|
||||
// Verify the inputs are correctly initialized
|
||||
if m.inputs[0].Value() != testUser.Shortname {
|
||||
t.Errorf("Expected Shortname '%s', got '%s'", testUser.Shortname, m.inputs[0].Value())
|
||||
}
|
||||
|
||||
if m.inputs[1].Value() != testUser.Longname {
|
||||
t.Errorf("Expected Longname '%s', got '%s'", testUser.Longname, m.inputs[1].Value())
|
||||
}
|
||||
|
||||
if m.inputs[2].Value() != testUser.Username {
|
||||
t.Errorf("Expected Username '%s', got '%s'", testUser.Username, m.inputs[2].Value())
|
||||
}
|
||||
|
||||
if m.inputs[3].Value() != "" {
|
||||
t.Errorf("Expected Email to be empty, got '%s'", m.inputs[3].Value())
|
||||
}
|
||||
|
||||
expectedGroups := strings.Join(testUser.Groups, "|")
|
||||
if m.inputs[4].Value() != expectedGroups {
|
||||
t.Errorf("Expected Groups '%s', got '%s'", expectedGroups, m.inputs[4].Value())
|
||||
}
|
||||
|
||||
// Verify the first input is focused
|
||||
if !m.inputs[0].Focused() {
|
||||
t.Errorf("Expected first input to be focused")
|
||||
}
|
||||
}
|
||||
|
||||
// tui_author TESTS END
|
||||
|
||||
// tui_commit_message TESTS BEGIN
|
||||
@@ -208,6 +389,8 @@ func Test_EntryCM(t *testing.T) {
|
||||
t, m, teatest.WithInitialTermSize(300, 300),
|
||||
)
|
||||
tm.Type("test commit message")
|
||||
keyPress(tm, "shift+tab")
|
||||
tm.Type("new line")
|
||||
|
||||
keyPress(tm, "enter")
|
||||
|
||||
@@ -217,11 +400,57 @@ func Test_EntryCM(t *testing.T) {
|
||||
t.Errorf("Expected model_cm, got %T", fm)
|
||||
}
|
||||
|
||||
if m.textarea.Value() != "test commit message" {
|
||||
if m.textarea.Value() != "test commit message\nnew line" {
|
||||
t.Errorf("Expected 'test commit message', got %s", m.textarea.Value())
|
||||
}
|
||||
}
|
||||
|
||||
func Test_EntryCM_Quit(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
m := initialModel_cm()
|
||||
tm := teatest.NewTestModel(
|
||||
t, m, teatest.WithInitialTermSize(300, 300),
|
||||
)
|
||||
keyPress(tm, "esc")
|
||||
|
||||
fm := tm.FinalModel(t)
|
||||
m, ok := fm.(model_cm)
|
||||
if !ok {
|
||||
t.Errorf("Expected model_cm, got %T", fm)
|
||||
}
|
||||
|
||||
if m.textarea.Value() != "" {
|
||||
t.Errorf("Expected empty textarea, got %s", m.textarea.Value())
|
||||
}
|
||||
}
|
||||
|
||||
// cannot test sigkill as it does not play nicely with these types of tests :(
|
||||
|
||||
func Test_EntryCM_Unfocuse(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
m := initialModel_cm()
|
||||
tm := teatest.NewTestModel(
|
||||
t, m, teatest.WithInitialTermSize(300, 300),
|
||||
)
|
||||
keyPress(tm, "down")
|
||||
|
||||
keyPress(tm, "esc")
|
||||
|
||||
fm := tm.FinalModel(t)
|
||||
m, ok := fm.(model_cm)
|
||||
if !ok {
|
||||
t.Errorf("Expected model_cm, got %T", fm)
|
||||
}
|
||||
|
||||
if m.textarea.Value() != "" {
|
||||
t.Errorf("Expected empty textarea, got %s", m.textarea.Value())
|
||||
}
|
||||
}
|
||||
|
||||
// tui_commit_message TESTS END
|
||||
|
||||
// tui_list TESTS BEGIN
|
||||
@@ -363,7 +592,7 @@ func Test_GroupSelection(t *testing.T) {
|
||||
keyPress(tm, "enter")
|
||||
|
||||
fm := tm.FinalModel(t)
|
||||
m, ok := fm.(model)
|
||||
_, ok := fm.(model)
|
||||
if !ok {
|
||||
t.Errorf("Expected model, got %T", fm)
|
||||
}
|
||||
@@ -377,7 +606,19 @@ func Test_pagination(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
m := mainModel{}
|
||||
// Add 20 authors to the test data
|
||||
for i := 0; i < 20; i++ {
|
||||
utils.Users[fmt.Sprintf("author%d", i)] = utils.User{
|
||||
Shortname: fmt.Sprintf("a%d", i),
|
||||
Longname: fmt.Sprintf("Author %d", i),
|
||||
Username: fmt.Sprintf("AuthorUser%d", i),
|
||||
Email: fmt.Sprintf("author%d@test.com", i),
|
||||
Ex: false,
|
||||
Groups: []string{},
|
||||
}
|
||||
}
|
||||
|
||||
m := listModel()
|
||||
|
||||
tm := teatest.NewTestModel(
|
||||
t, m, teatest.WithInitialTermSize(25, 25),
|
||||
@@ -387,13 +628,13 @@ func Test_pagination(t *testing.T) {
|
||||
tm.Quit()
|
||||
|
||||
fm := tm.FinalModel(t)
|
||||
m, ok := fm.(mainModel)
|
||||
m, ok := fm.(model)
|
||||
if !ok {
|
||||
t.Errorf("Expected model, got %T", fm)
|
||||
}
|
||||
|
||||
if m.paginator.Page != 1 {
|
||||
t.Errorf("Expected page 1, got %d", m.paginator.Page)
|
||||
if m.list.Paginator.Page != 1 {
|
||||
t.Errorf("Expected page 1, got %d", m.list.Paginator.Page)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package utils
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
@@ -13,64 +14,65 @@ import (
|
||||
// An example of the author file can be found in the examples folder of the repo
|
||||
func Find_authorfile() string {
|
||||
if os.Getenv("author_file") == "" {
|
||||
authors, err := os.UserConfigDir()
|
||||
dirs, err := os.UserConfigDir()
|
||||
if err != nil {
|
||||
fmt.Println("Error getting user config directory")
|
||||
os.Exit(2)
|
||||
panic(fmt.Sprintf("Error getting user config directory: %v", err))
|
||||
}
|
||||
return (authors + "/cocommit/authors.json")
|
||||
return (dirs + "/cocommit/authors.json")
|
||||
} else {
|
||||
return os.Getenv("author_file")
|
||||
}
|
||||
}
|
||||
|
||||
func CheckAuthorFile() string {
|
||||
func CheckAuthorFile(input io.Reader, output io.Writer) (string,error) {
|
||||
var cocommit_folder string
|
||||
authorfile := Find_authorfile()
|
||||
|
||||
if _, err := os.Stat(authorfile); os.IsNotExist(err) {
|
||||
println("Author file not found at: ", authorfile)
|
||||
println("Would you like to create one? (y/n)")
|
||||
fmt.Fprintf(output, "Author file not found at: %s\n", authorfile)
|
||||
fmt.Fprintf(output, "Would you like to create one? (y/n)\n")
|
||||
|
||||
var response string
|
||||
_, err := fmt.Scanln(&response)
|
||||
_, err := fmt.Fscanln(input, &response)
|
||||
if err != nil {
|
||||
println("Error reading response")
|
||||
fmt.Fprintln(output, "Error reading response")
|
||||
}
|
||||
|
||||
if response == "y" {
|
||||
parts := strings.Split(authorfile, "/")
|
||||
if len(parts) > 1 {
|
||||
// remove the last part of the path
|
||||
cocommit_folder = strings.Join(parts[:len(parts)-1], "/")
|
||||
} else {
|
||||
cocommit_folder = "."
|
||||
}
|
||||
|
||||
// create the author file
|
||||
if _, dirErr := os.Stat(cocommit_folder); os.IsNotExist(dirErr) {
|
||||
err := os.Mkdir(cocommit_folder, 0766)
|
||||
if err != nil {
|
||||
fmt.Println("Error creating directory: ", err, cocommit_folder)
|
||||
os.Exit(1)
|
||||
return "", fmt.Errorf("error creating directory: %v %s", err, cocommit_folder)
|
||||
}
|
||||
}
|
||||
file, err := os.Create(authorfile)
|
||||
if err != nil {
|
||||
fmt.Println("Error creating file: ", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
file, err := os.Create(authorfile)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error creating file: %v", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// write the header to the file
|
||||
json_string :=
|
||||
`{
|
||||
json_string := `{
|
||||
"Authors": {
|
||||
}
|
||||
}`
|
||||
|
||||
file.Write([]byte(json_string))
|
||||
|
||||
fmt.Println("Author file created. To add authors please launch the TUI with -a and press 'C'")
|
||||
fmt.Fprintln(output, "Author file created. To add authors please launch the TUI with -a and press 'C'")
|
||||
} else {
|
||||
os.Exit(1)
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
// This string output is mostly for convenience can mostly be ignored
|
||||
return authorfile
|
||||
return authorfile, nil
|
||||
}
|
||||
|
||||
func CreateAuthor(user User) {
|
||||
@@ -106,6 +108,12 @@ func CreateAuthor(user User) {
|
||||
}
|
||||
|
||||
func DeleteOneAuthor(author string) {
|
||||
// check that users aren't empty
|
||||
if len(Users) < 1 {
|
||||
fmt.Println("No users to remove")
|
||||
return
|
||||
}
|
||||
|
||||
author_file := Find_authorfile()
|
||||
|
||||
if _, exists := Users[author]; !exists {
|
||||
@@ -121,12 +129,6 @@ func DeleteOneAuthor(author string) {
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// check that users aren't empty
|
||||
if len(Users) < 1 {
|
||||
fmt.Println("No users to remove")
|
||||
return
|
||||
}
|
||||
|
||||
usr := Users[author]
|
||||
|
||||
// Remove the user from the Author struct (try both short and long name)
|
||||
|
||||
+26
-24
@@ -10,33 +10,31 @@ import (
|
||||
|
||||
// This util file is used to create a commit message using a string builder
|
||||
|
||||
// string builder for the commit message
|
||||
var sb strings.Builder
|
||||
|
||||
// list of excluded authors based on the author file
|
||||
var excludeMode = []string{}
|
||||
|
||||
// Regex pattern used to create temp users to add to the commit message
|
||||
var reg, _ = regexp.Compile("([^:]+):([^:]+)")
|
||||
|
||||
func Commit(message string, authors []string) string {
|
||||
// string builder for the commit message
|
||||
var sb strings.Builder
|
||||
excludeMode := []string{}
|
||||
|
||||
// write the commit message to the string builder
|
||||
sb.WriteString(message + "\n")
|
||||
fst := authors[0]
|
||||
|
||||
if fst == "all" || fst == "All" {
|
||||
add_x_users(excludeMode)
|
||||
goto skip_loop
|
||||
add_x_users(excludeMode, &sb)
|
||||
return sb.String()
|
||||
} else if Groups[fst] != nil {
|
||||
excludeMode = group_selection(Groups[fst], excludeMode)
|
||||
add_x_users(excludeMode)
|
||||
goto skip_loop
|
||||
add_x_users(excludeMode, &sb)
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// Loop that adds users
|
||||
for _, committer := range authors {
|
||||
if _, ok := Users[committer]; ok {
|
||||
sb_author(committer)
|
||||
sb_author(committer, &sb)
|
||||
} else if match := reg.MatchString(committer); match {
|
||||
str := strings.Split(committer, ":")
|
||||
|
||||
@@ -52,16 +50,15 @@ func Commit(message string, authors []string) string {
|
||||
println(committer, " was unknown. User either not defined or name typed wrong")
|
||||
}
|
||||
}
|
||||
if len(excludeMode) > 0 {
|
||||
add_x_users(excludeMode)
|
||||
}
|
||||
|
||||
// Skip label for edge cases at top of function
|
||||
skip_loop:
|
||||
// Add excluded users after processing all authors
|
||||
if len(excludeMode) > 0 {
|
||||
add_x_users(excludeMode, &sb)
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func GitWrapper(commit string, flags []string) {
|
||||
func GitWrapper(commit string, flags []string) error {
|
||||
// commit shell command
|
||||
// specify git command
|
||||
input := []string{"commit"}
|
||||
@@ -76,26 +73,31 @@ func GitWrapper(commit string, flags []string) {
|
||||
cmd_output, err := cmd.CombinedOutput()
|
||||
|
||||
if err != nil {
|
||||
println(fmt.Sprint(err) + " : " + string(cmd_output))
|
||||
return fmt.Errorf("error: %s : %s", err, string(cmd_output))
|
||||
} else {
|
||||
println(string(cmd_output))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GitPush() {
|
||||
cmd := exec.Command("git", "push")
|
||||
func GitPush(flags []string) error {
|
||||
|
||||
input := []string{"push"}
|
||||
input = append(input, flags...)
|
||||
cmd := exec.Command("git", input...)
|
||||
|
||||
cmd_output, err := cmd.CombinedOutput()
|
||||
|
||||
if err != nil {
|
||||
println(fmt.Sprint(err) + " : " + string(cmd_output))
|
||||
return fmt.Errorf("error: %s : %s", err, string(cmd_output))
|
||||
} else {
|
||||
println(string(cmd_output))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// helper function to add an author to the commit message
|
||||
func sb_author(committer string) {
|
||||
func sb_author(committer string, sb *strings.Builder) {
|
||||
sb.WriteString("\nCo-authored-by: ")
|
||||
sb.WriteString(Users[committer].Username)
|
||||
sb.WriteString(" <")
|
||||
@@ -104,13 +106,13 @@ func sb_author(committer string) {
|
||||
}
|
||||
|
||||
// helper function to add x amount of users to the commit message
|
||||
func add_x_users(excludeMode []string) {
|
||||
func add_x_users(excludeMode []string, sb *strings.Builder) {
|
||||
if len(DefExclude) > 0 {
|
||||
excludeMode = append(excludeMode, DefExclude...)
|
||||
}
|
||||
for key, user := range Users {
|
||||
if !slices.Contains(excludeMode, user.Username) {
|
||||
sb_author(key)
|
||||
sb_author(key, sb)
|
||||
excludeMode = append(excludeMode, user.Username)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,17 +4,63 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
)
|
||||
|
||||
type GithubProfile struct {
|
||||
Login string `json:"login"`
|
||||
Name string `json:"name"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
func checkGHCLI() bool {
|
||||
// Check if the gh command line tool is installed
|
||||
cmd := exec.Command("gh", "auth", "status")
|
||||
out ,err := cmd.CombinedOutput()
|
||||
if err == nil {
|
||||
if strings.Contains(string(out), "Logged in to") {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
|
||||
return false
|
||||
|
||||
}
|
||||
|
||||
func useGHCLI(username string) []byte {
|
||||
cmd := exec.Command("gh", "api", fmt.Sprintf("/users/%s", username))
|
||||
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
panic(fmt.Sprint("Error fetching github profile",err))
|
||||
}
|
||||
return out
|
||||
|
||||
}
|
||||
|
||||
func FetchGithubProfile(username string) User {
|
||||
// Fetch the github profile and create a user with everything except the email
|
||||
|
||||
var profile GithubProfile
|
||||
|
||||
check := checkGHCLI()
|
||||
|
||||
var err error
|
||||
if check {
|
||||
// If the gh command line tool is installed, use it to fetch the github profile
|
||||
fmt.Println("Using gh-cli to fetch github profile")
|
||||
data := useGHCLI(username)
|
||||
|
||||
err = json.Unmarshal(data, &profile)
|
||||
|
||||
} else {
|
||||
|
||||
fmt.Println("Using http request to fetch github profile")
|
||||
// If the gh command line tool is not installed, use the http request
|
||||
url := fmt.Sprintf("https://api.github.com/users/%s", username)
|
||||
|
||||
resp, err := http.Get(url)
|
||||
@@ -24,12 +70,20 @@ func FetchGithubProfile(username string) User {
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Parse the response and create a user
|
||||
var profile GithubProfile
|
||||
err = json.NewDecoder(resp.Body).Decode(&profile)
|
||||
if err = json.NewDecoder(resp.Body).Decode(&profile); err != nil {
|
||||
panic(fmt.Sprint("Error decoding github profile: ", err))
|
||||
}
|
||||
}
|
||||
// Check error
|
||||
if err != nil {
|
||||
panic(fmt.Sprint("Error parsing github profile: ", err))
|
||||
}
|
||||
|
||||
// Check if the profile has a name
|
||||
if profile.Name == "" {
|
||||
panic(fmt.Sprint("Error: No name found in github profile something went wrong whilst fetching the profile: ", err))
|
||||
}
|
||||
|
||||
// Create a user with the github profile
|
||||
return User{
|
||||
Shortname: strings.ToLower(profile.Name[:2]),
|
||||
|
||||
@@ -58,13 +58,11 @@ func Define_users(author_file string) {
|
||||
|
||||
data, err := os.ReadFile(author_file)
|
||||
if err != nil {
|
||||
fmt.Println("Error reading author file: ", err)
|
||||
os.Exit(2)
|
||||
panic(fmt.Sprintf("Error reading author file: %v", err))
|
||||
}
|
||||
err = json.Unmarshal(data, &auth)
|
||||
if err != nil {
|
||||
fmt.Println("Error unmarshalling json: ", err)
|
||||
os.Exit(2)
|
||||
panic(fmt.Sprintf("Error unmarshalling json: %v", err))
|
||||
}
|
||||
|
||||
Authors = auth
|
||||
|
||||
+503
-1
@@ -1,8 +1,13 @@
|
||||
package utils_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/Slug-Boi/cocommit/src/cmd/utils"
|
||||
@@ -117,6 +122,192 @@ func Test_CreateAuthor(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_FindAuthorFilePanic(t *testing.T) {
|
||||
// Save original environment variables
|
||||
originalAuthorFile := os.Getenv("author_file")
|
||||
originalHome := os.Getenv("HOME")
|
||||
orignalXDG := os.Getenv("XDG_CONFIG_HOME")
|
||||
|
||||
// Test Find_authorfile panic
|
||||
defer func() {
|
||||
// Reset environment variables
|
||||
os.Setenv("author_file", originalAuthorFile)
|
||||
os.Setenv("HOME", originalHome)
|
||||
os.Setenv("XDG_CONFIG_HOME", orignalXDG)
|
||||
|
||||
if r := recover(); r == nil {
|
||||
t.Errorf("Find_authorfile() did not panic")
|
||||
}
|
||||
}()
|
||||
|
||||
// Set environment variables to empty strings
|
||||
// to trigger the panic
|
||||
os.Setenv("author_file", "")
|
||||
os.Setenv("HOME", "")
|
||||
os.Setenv("XDG_CONFIG_HOME", "")
|
||||
utils.Find_authorfile()
|
||||
}
|
||||
|
||||
func Test_FindAuthorFileEnv(t *testing.T) {
|
||||
// Test Find_authorfile with env var
|
||||
setup()
|
||||
defer teardown()
|
||||
os.Setenv("author_file", "")
|
||||
authorfile := utils.Find_authorfile()
|
||||
configdir, err := os.UserConfigDir()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get user config directory: %v", err)
|
||||
}
|
||||
if authorfile != configdir+"/cocommit/authors.json" {
|
||||
t.Errorf("Find_authorfile() = %v; want %v", authorfile, configdir+"/cocommit/authors.json")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Test_CreateAuthorPanicOnFileError(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
// Set an invalid author file path to trigger file open error
|
||||
os.Setenv("author_file", "/invalid/path/author_file_test")
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Errorf("CreateAuthor() did not panic on file open error")
|
||||
}
|
||||
}()
|
||||
|
||||
validUser := utils.User{
|
||||
Shortname: "valid",
|
||||
Longname: "ValidUser",
|
||||
Username: "ValidUser",
|
||||
Email: "valid@test.io",
|
||||
Ex: false,
|
||||
Groups: []string{},
|
||||
}
|
||||
|
||||
utils.CreateAuthor(validUser)
|
||||
}
|
||||
|
||||
func Test_DeleteOneAuthorPrints(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
// Redirect stdout to capture fmt.Println outputs
|
||||
oldStdout := os.Stdout
|
||||
r, w, _ := os.Pipe()
|
||||
os.Stdout = w
|
||||
|
||||
// Test case: User not found
|
||||
utils.Define_users("author_file_test")
|
||||
utils.DeleteOneAuthor("nonexistent_user")
|
||||
w.Close()
|
||||
out, _ := io.ReadAll(r)
|
||||
os.Stdout = oldStdout
|
||||
|
||||
if !strings.Contains(string(out), "User not found") {
|
||||
t.Errorf("Expected 'User not found' message, got: %s", string(out))
|
||||
}
|
||||
|
||||
// Test case: Error opening file
|
||||
|
||||
// Test case: No users to remove
|
||||
setup()
|
||||
defer teardown()
|
||||
utils.Define_users("author_file_test")
|
||||
utils.Users = make(map[string]utils.User) // Clear users
|
||||
r, w, _ = os.Pipe()
|
||||
os.Stdout = w
|
||||
|
||||
utils.DeleteOneAuthor("te")
|
||||
w.Close()
|
||||
out, _ = io.ReadAll(r)
|
||||
os.Stdout = oldStdout
|
||||
|
||||
if !strings.Contains(string(out), "No users to remove") {
|
||||
t.Errorf("Expected 'No users to remove' message, got: %s", string(out))
|
||||
}
|
||||
}
|
||||
|
||||
func Test_CheckAuthorFile_FileExists(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
// Ensure the author file exists
|
||||
authorfile := utils.Find_authorfile()
|
||||
if _, err := os.Stat(authorfile); os.IsNotExist(err) {
|
||||
t.Fatalf("Author file does not exist: %v", authorfile)
|
||||
}
|
||||
|
||||
// Mock user input to simulate "y" response
|
||||
input := strings.NewReader("y\n")
|
||||
output := new(bytes.Buffer) // capture output
|
||||
|
||||
// Test CheckAuthorFile when the file exists
|
||||
result, err := utils.CheckAuthorFile(input, output)
|
||||
if err != nil {
|
||||
t.Fatalf("CheckAuthorFile() returned error: %v", err)
|
||||
}
|
||||
if result != authorfile {
|
||||
t.Errorf("CheckAuthorFile() = %v; want %v", result, authorfile)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_CheckAuthorFile_FileNotExists_CreateFile(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
originalEnv := os.Getenv("author_file")
|
||||
defer os.Setenv("author_file", originalEnv)
|
||||
|
||||
os.Setenv("author_file", "author_file_test")
|
||||
// Remove the author file to simulate non-existence
|
||||
authorfile := utils.Find_authorfile()
|
||||
os.Remove(authorfile)
|
||||
|
||||
// Mock user input to simulate "y" response
|
||||
input := strings.NewReader("y\n")
|
||||
output := new(bytes.Buffer) // capture output
|
||||
|
||||
|
||||
|
||||
// Test CheckAuthorFile when the file does not exist and user agrees to create it
|
||||
result, err := utils.CheckAuthorFile(input, output)
|
||||
if err != nil {
|
||||
t.Fatalf("CheckAuthorFile() returned error: %v", err)
|
||||
}
|
||||
|
||||
if result != authorfile {
|
||||
panic(fmt.Sprintf("CheckAuthorFile() = %v; want %v", result, authorfile))
|
||||
}
|
||||
}
|
||||
|
||||
func Test_CheckAuthorFile_FileNotExists_DeclineCreate(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
// Remove the author file to simulate non-existence
|
||||
authorfile := utils.Find_authorfile()
|
||||
os.Remove(authorfile)
|
||||
|
||||
// Mock user input to simulate "n" response
|
||||
input := strings.NewReader("n\n")
|
||||
output := new(bytes.Buffer) // capture output
|
||||
|
||||
|
||||
|
||||
// Test CheckAuthorFile when the file does not exist and user declines to create it
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Errorf("CheckAuthorFile() did not exit when user declined to create the file")
|
||||
}
|
||||
}()
|
||||
utils.CheckAuthorFile(input, output)
|
||||
// Check if the output contains the expected message
|
||||
if !strings.Contains(output.String(), "") {
|
||||
t.Errorf("Expected no message found output: %s", output.String())
|
||||
}
|
||||
}
|
||||
|
||||
// Author tests END
|
||||
|
||||
@@ -131,6 +322,56 @@ func Test_DefineUsers(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_DefineUsersMultipleGroups(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
utils.Define_users("author_file_test")
|
||||
utils.CreateAuthor(utils.User{
|
||||
Shortname: "epic",
|
||||
Longname: "Test",
|
||||
Username: "TestUser",
|
||||
Email: "dontcare",
|
||||
Ex: false,
|
||||
Groups: []string{"gr1"},
|
||||
})
|
||||
|
||||
if len(utils.Users) != 6 {
|
||||
t.Errorf("Define_users() = %v; want 6", len(utils.Users))
|
||||
}
|
||||
if len(utils.Groups["gr1"]) != 2 {
|
||||
t.Errorf("Define_users() = %v; want 2", len(utils.Groups["gr1"]))
|
||||
}
|
||||
}
|
||||
|
||||
func Test_DefineUsersPanicOnMissingFile(t *testing.T) {
|
||||
// Test Define_users panic on missing file
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Errorf("Define_users() did not panic on missing file")
|
||||
}
|
||||
}()
|
||||
utils.Define_users("non_existent_file")
|
||||
}
|
||||
|
||||
func Test_DefineUsersPanicOnInvalidJSON(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
// Create a file with invalid JSON
|
||||
invalidJSON := `{"Authors": { "invalid": "data"`
|
||||
os.WriteFile("invalid_author_file_test", []byte(invalidJSON), 0644)
|
||||
defer os.Remove("invalid_author_file_test")
|
||||
|
||||
// Test Define_users panic on invalid JSON
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Errorf("Define_users() did not panic on invalid JSON")
|
||||
}
|
||||
}()
|
||||
utils.Define_users("invalid_author_file_test")
|
||||
}
|
||||
|
||||
func Test_RemoveUser(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
@@ -164,6 +405,42 @@ func Test_TempAddUser(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Test_ContainsUser(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
// Test ContainsUser
|
||||
utils.Define_users("author_file_test")
|
||||
user := utils.Users["te"]
|
||||
userList := make([]utils.User, 0, len(utils.Users))
|
||||
for _, u := range utils.Users {
|
||||
userList = append(userList, u)
|
||||
}
|
||||
if !utils.ContainsUser(userList, user) {
|
||||
t.Errorf("ContainsUser() = %v; want true", false)
|
||||
}
|
||||
|
||||
if utils.ContainsUser(userList, utils.User{}) {
|
||||
t.Errorf("ContainsUser() = %v; want false", true)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_CheckUserFields(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
// Test CheckUserFields
|
||||
utils.Define_users("author_file_test")
|
||||
user := utils.Users["te"]
|
||||
if !utils.CheckUserFields(user) {
|
||||
t.Errorf("CheckUserFields() = %v; want true", false)
|
||||
}
|
||||
|
||||
emptyUser := utils.User{}
|
||||
if utils.CheckUserFields(emptyUser) {
|
||||
t.Errorf("CheckUserFields() = %v; want false", true)
|
||||
}
|
||||
}
|
||||
|
||||
// User tests END
|
||||
|
||||
// Commit tests BEGIN
|
||||
@@ -180,6 +457,133 @@ func Test_Commit(t* testing.T) {
|
||||
t.Errorf("Commit() = %v; want Test commit message\n", commit)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_CommitWithAllAuthors(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
utils.Define_users("author_file_test")
|
||||
|
||||
// Test Commit with "all" authors
|
||||
authors := []string{"all"}
|
||||
message := "Test commit message with all authors"
|
||||
commit := utils.Commit(message, authors)
|
||||
|
||||
// Verify that all authors are included in the commit message
|
||||
for _, user := range utils.Users {
|
||||
coAuthorLine := fmt.Sprintf("Co-authored-by: %s <%s>", user.Username, user.Email)
|
||||
if !strings.Contains(commit, coAuthorLine) {
|
||||
t.Errorf("Commit() missing co-author line: %v", coAuthorLine)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_CommitWithGroupAuthors(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
utils.Define_users("author_file_test")
|
||||
|
||||
// Test Commit with a group of authors
|
||||
authors := []string{"gr1"}
|
||||
message := "Test commit message with group authors"
|
||||
commit := utils.Commit(message, authors)
|
||||
|
||||
// Verify that all group members are included in the commit message
|
||||
for _, user := range utils.Groups["gr1"] {
|
||||
coAuthorLine := fmt.Sprintf("Co-authored-by: %s <%s>", user.Username, user.Email)
|
||||
if !strings.Contains(commit, coAuthorLine) {
|
||||
t.Errorf("Commit() missing co-author line for group member: %v", coAuthorLine)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Test_CommitWithInvalidGroup(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
// Reset utils.Users and utils.Groups to avoid interference from other tests
|
||||
utils.Users = make(map[string]utils.User)
|
||||
utils.Groups = make(map[string][]utils.User)
|
||||
|
||||
utils.Define_users("author_file_test")
|
||||
|
||||
// Test Commit with an invalid group
|
||||
authors := []string{"invalid_group"}
|
||||
message := "Test commit message with invalid group"
|
||||
commit := utils.Commit(message, authors)
|
||||
|
||||
// Verify that no co-author lines are added for the invalid group
|
||||
if strings.Contains(commit, "Co-authored-by:") {
|
||||
t.Errorf("Commit() should not include co-author lines for an invalid group msg: %s ", commit)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_CommitWithInlineAdd(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
utils.Define_users("author_file_test")
|
||||
|
||||
// Test Commit with inline addition of authors
|
||||
authors := []string{"te:testtest"}
|
||||
message := "Test commit message with inline addition"
|
||||
commit := utils.Commit(message, authors)
|
||||
|
||||
// Verify that the commit message includes the inline addition
|
||||
splitAuthors := strings.Split(authors[0], ":")
|
||||
|
||||
if !strings.Contains(commit, fmt.Sprintf("Co-authored-by: %s <%s>", splitAuthors[0], splitAuthors[1])) {
|
||||
t.Errorf("Commit() missing co-author line for inline addition: %v:%v\n%s", splitAuthors[0],splitAuthors[1] ,commit)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_CommitWithNegation(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
utils.Define_users("author_file_test")
|
||||
|
||||
// Test Commit with negation
|
||||
authors := []string{"^testtest"}
|
||||
message := "Test commit message with negation"
|
||||
commit := utils.Commit(message, authors)
|
||||
|
||||
// Verify that the commit message does not include the negated author
|
||||
if strings.Contains(commit, "Co-authored-by: testtest") {
|
||||
t.Errorf("Commit() should not include co-author line for negated author")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_GitWrapper(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
utils.Define_users("author_file_test")
|
||||
|
||||
|
||||
// Test GitWrapper with --dry-run flag
|
||||
authors := []string{"te"}
|
||||
message := "Test commit message for GitWrapper"
|
||||
|
||||
commit := utils.Commit(message, authors)
|
||||
flags := []string{"-a","--dry-run"}
|
||||
|
||||
err := utils.GitWrapper(commit, flags)
|
||||
if err != nil {
|
||||
t.Errorf("GitWrapper() returned error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_GitPush(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
utils.Define_users("author_file_test")
|
||||
|
||||
// Test GitPush with --dry-run flag
|
||||
flags := []string{"--all","--dry-run"}
|
||||
|
||||
err := utils.GitPush(flags)
|
||||
if err != nil {
|
||||
t.Errorf("GitPush() returned error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Commit tests END
|
||||
|
||||
// Github tests BEGIN
|
||||
@@ -207,5 +611,103 @@ func Test_FetchGHProfile(t *testing.T) {
|
||||
t.Errorf("FetchGithubProfile() = %v; want 0", len(profile.Groups))
|
||||
}
|
||||
}
|
||||
// Github tests END
|
||||
|
||||
func Test_FetchGHProfilePanicOnRequestError(t *testing.T) {
|
||||
// Test FetchGithubProfile panic on HTTP request error
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Errorf("FetchGithubProfile() did not panic on HTTP request error")
|
||||
}
|
||||
}()
|
||||
|
||||
// Simulate an invalid URL by using an invalid username
|
||||
utils.FetchGithubProfile("invalid_username_with_special_characters_@#$")
|
||||
}
|
||||
|
||||
func Test_FetchGHProfilePanicOnInvalidJSON(t *testing.T) {
|
||||
// Test FetchGithubProfile panic on invalid JSON response
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Errorf("FetchGithubProfile() did not panic on invalid JSON response")
|
||||
}
|
||||
}()
|
||||
|
||||
// Mock the HTTP response to return invalid JSON
|
||||
http.DefaultClient = &http.Client{
|
||||
Transport: roundTripperFunc(func(req *http.Request) (*http.Response, error) {
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Body: io.NopCloser(strings.NewReader(`{"invalid_json":`)),
|
||||
}, nil
|
||||
}),
|
||||
}
|
||||
|
||||
utils.FetchGithubProfile("valid_username")
|
||||
}
|
||||
|
||||
func Test_FetchGHProfilePanicOnHTTPGetError(t *testing.T) {
|
||||
// Test FetchGithubProfile panic on HTTP GET error
|
||||
defer func() {
|
||||
if r := recover(); r == nil {
|
||||
t.Errorf("FetchGithubProfile() did not panic on HTTP GET error")
|
||||
}
|
||||
}()
|
||||
|
||||
// Mock the HTTP client to simulate an error during the GET request
|
||||
http.DefaultClient = &http.Client{
|
||||
Transport: roundTripperFunc(func(req *http.Request) (*http.Response, error) {
|
||||
return nil, fmt.Errorf("simulated HTTP GET error")
|
||||
}),
|
||||
}
|
||||
|
||||
utils.FetchGithubProfile("any_username")
|
||||
}
|
||||
|
||||
type roundTripperFunc func(req *http.Request) (*http.Response, error)
|
||||
|
||||
func (f roundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
return f(req)
|
||||
}
|
||||
|
||||
func Test_FetchGHProfileHTTP(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
// Mock the HTTP client to simulate a successful response
|
||||
mockResponse := `{
|
||||
"login": "Slug-Boi",
|
||||
"name": "Theis",
|
||||
"email": "",
|
||||
"bio": "Test bio"
|
||||
}`
|
||||
http.DefaultClient = &http.Client{
|
||||
Transport: roundTripperFunc(func(req *http.Request) (*http.Response, error) {
|
||||
if req.URL.String() != "https://api.github.com/users/Slug-Boi" {
|
||||
t.Errorf("Unexpected URL: %v", req.URL.String())
|
||||
}
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Body: io.NopCloser(strings.NewReader(mockResponse)),
|
||||
}, nil
|
||||
}),
|
||||
}
|
||||
|
||||
// Alias the `gh` command to an error to ensure the GitHub CLI is not used
|
||||
os.Setenv("PATH", "/nonexistent")
|
||||
|
||||
// Test FetchGithubProfile using HTTP request
|
||||
profile := utils.FetchGithubProfile("Slug-Boi")
|
||||
if profile.Username != "Slug-Boi" {
|
||||
t.Errorf("FetchGithubProfile() = %v; want Slug-Boi", profile.Username)
|
||||
}
|
||||
if profile.Longname != "Theis" {
|
||||
t.Errorf("FetchGithubProfile() = %v; want Theis", profile.Longname)
|
||||
}
|
||||
if profile.Email != "" {
|
||||
t.Errorf("FetchGithubProfile() = %v; want empty email", profile.Email)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Github tests END
|
||||
|
||||
Reference in New Issue
Block a user