-
Notifications
You must be signed in to change notification settings - Fork 1
CLI fonctionnelle #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 6 commits
e7574c1
4a47b7f
2e09aa5
aa5891d
e8e466b
bb4c0a7
9424aff
69b6634
b569aa0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| { | ||
| "email": "clem@calia.com", | ||
| "mdp": "123456" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| package cmd | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "os" | ||
| "strconv" | ||
| "webstack/metier/todos" | ||
| "webstack/metier/users" | ||
| ) | ||
|
|
||
| func Add(user users.User) { | ||
| if len(os.Args) != 4 { | ||
| fmt.Println(`Usage: go run main.go add "text" <priority>`) | ||
| fmt.Println("") | ||
| fmt.Println("text : une chaîne de caractère décrivant votre nouveau todo") | ||
| fmt.Println("priority : le niveau de priorité de votre tâche entre 1 et 3, du moins au plus urgent") | ||
| os.Exit(1) | ||
| } | ||
| text := os.Args[2] | ||
| priority, err := strconv.Atoi(os.Args[3]) | ||
| if err != nil { | ||
| fmt.Println("Arguments invalides :") | ||
| fmt.Println(`Usage: go run main.go add "text" <priority>`) | ||
| fmt.Println("") | ||
| fmt.Println("text : une chaîne de caractère décrivant votre nouveau todo") | ||
| fmt.Println("priority : un nombre entre 1 et 3, du moins au plus urgent") | ||
|
|
||
| os.Exit(1) | ||
| } | ||
| task, err := todos.NewTask(text) | ||
| if err != nil { | ||
| fmt.Print(err.Error()) | ||
| } | ||
| _, err = todos.Add(task, priority, user) | ||
| if err != nil { | ||
| fmt.Print(err.Error()) | ||
| } | ||
| Get(user) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,239 @@ | ||
| package cmd | ||
|
|
||
| import ( | ||
| "bytes" | ||
| "fmt" | ||
| "io" | ||
| "os" | ||
| "strings" | ||
| "testing" | ||
| "webstack/metier/todos" | ||
| "webstack/metier/users" | ||
| ) | ||
|
|
||
| type fakeDb struct { | ||
| todos []todos.Todo | ||
| users []users.User | ||
| } | ||
|
|
||
| func (f *fakeDb) AddUserDb(u users.User) error { | ||
| for _, user := range f.users { | ||
| if users.GetEmail(user) == users.GetEmail(u) { | ||
| return fmt.Errorf("email déjà utilisé") | ||
| } | ||
| } | ||
| f.users = append(f.users, u) | ||
| return nil | ||
| } | ||
| func (f *fakeDb) GetUser(u users.User) (users.User, error) { | ||
| for _, user := range f.users { | ||
| fmt.Print(user) | ||
| if users.GetEmail(user) == users.GetEmail(u) { | ||
| return user, nil | ||
| } | ||
| } | ||
| return users.User{}, fmt.Errorf("error") | ||
| } | ||
|
|
||
| func (f *fakeDb) AddTodoDb(td todos.Todo, u users.User) error { | ||
| f.todos = append(f.todos, td) | ||
| return nil | ||
| } | ||
| func (f *fakeDb) DeleteTodoDb(td todos.Todo) error { | ||
| for i, t := range f.todos { | ||
| if t.Id == td.Id { | ||
| f.todos = append(f.todos[:i], f.todos[i+1:]...) | ||
| return nil | ||
| } | ||
| } | ||
| return nil | ||
|
|
||
| } | ||
| func (f *fakeDb) ModifyTodoDb(td todos.Todo) error { | ||
| for _, t := range f.todos { | ||
| if t.Id == td.Id { | ||
| t.Task = td.Task | ||
| return nil | ||
| } | ||
| } | ||
| return nil | ||
| } | ||
| func (f *fakeDb) GetTodosDb(u users.User) (t []todos.Todo, e error) { | ||
| t = f.todos | ||
| return t, nil | ||
| } | ||
|
|
||
| var user users.User | ||
|
|
||
| func setupFakeDb() fakeDb { | ||
| db := fakeDb{} | ||
|
|
||
| task1, _ := todos.NewTask("Faire les courses") | ||
| task2, _ := todos.NewTask("Sortir le chien") | ||
| task3, _ := todos.NewTask("(/$-_~+)=") | ||
| task4, _ := todos.NewTask("Une chaine très longue mais sans caractères spéciaux, d'ailleurs ma mère me dit toujours que je suis spécial, ça va c'est assez long ? Bon aller on va dire que oui") | ||
|
|
||
| mdp, _ := users.HashPassword("123456") | ||
| todo1 := todos.Todo{Id: 1, Task: task1, Priority: 3} | ||
| todo2 := todos.Todo{Id: 2, Task: task2, Priority: 2} | ||
| todo3 := todos.Todo{Id: 3, Task: task3, Priority: 2} | ||
| todo4 := todos.Todo{Id: 12, Task: task4, Priority: 1} | ||
| user, _ = users.NewUser("clem@caramail.fr", mdp) | ||
|
|
||
| db.AddTodoDb(todo1, user) | ||
| db.AddTodoDb(todo2, user) | ||
| db.AddTodoDb(todo3, user) | ||
| db.AddTodoDb(todo4, user) | ||
| db.AddUserDb(user) | ||
| return db | ||
| } | ||
|
|
||
| func TestGet(t *testing.T) { | ||
| db := setupFakeDb() | ||
| todos.Init(&db) | ||
| users.Init(&db) | ||
|
|
||
| old := os.Stdout | ||
| r, w, _ := os.Pipe() | ||
| os.Stdout = w | ||
|
|
||
| defer func() { | ||
| os.Stdout = old | ||
| w.Close() | ||
| }() | ||
| Get(db.users[0]) | ||
|
|
||
| outCh := make(chan string) | ||
| go func() { | ||
| var buf bytes.Buffer | ||
| io.Copy(&buf, r) | ||
| outCh <- buf.String() | ||
| }() | ||
| w.Close() | ||
|
|
||
| fmt.Print(old) | ||
| want := todos.GetTask(db.todos[0].Task) | ||
| want2 := todos.GetTask(db.todos[1].Task) | ||
| actual := <-outCh | ||
|
|
||
| if !strings.Contains(actual, want) || !strings.Contains(actual, want2) { | ||
| t.Errorf("expected : %s and %s, but got : %s", want, want2, actual) | ||
| } | ||
| } | ||
|
|
||
| func TestAdd(t *testing.T) { | ||
| db := setupFakeDb() | ||
| todos.Init(&db) | ||
| users.Init(&db) | ||
|
|
||
| var tests = []struct { | ||
| name string | ||
| entryText string | ||
| entryPrio string | ||
| want string | ||
| }{ | ||
| {"Cas normal", "Sortir le chien", "2", todos.GetTask(db.todos[1].Task)}, | ||
| {"Chaîne vide", "", "1", todos.ERR_NO_TEXT}, | ||
| {"Caractères spéciaux autorisés", "(/$-_~+)=", "1", todos.GetTask(db.todos[2].Task)}, | ||
| {"Caractères spéciaux non autorisés", "(/$-_]&[~]%)=", "3", todos.ERR_SPECIAL_CHAR}, | ||
| {"Plusieurs espaces en entrée", " ", "2", todos.ERR_NO_TEXT}, | ||
| {"Chaîne longue", "Une chaine très longue mais sans caractères spéciaux, d'ailleurs ma mère me dit toujours que je suis spécial, ça va c'est assez long ? Bon aller on va dire que oui", "1", todos.GetTask(db.todos[3].Task)}, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| os.Args = []string{"go run main.go", "add", tt.entryText, tt.entryPrio} | ||
| old := os.Stdout | ||
| r, w, _ := os.Pipe() | ||
| os.Stdout = w | ||
|
|
||
| defer func() { | ||
| os.Stdout = old | ||
| w.Close() | ||
| }() | ||
| Add(db.users[0]) | ||
| outCh := make(chan string) | ||
| go func() { | ||
| var buf bytes.Buffer | ||
| io.Copy(&buf, r) | ||
| outCh <- buf.String() | ||
| }() | ||
| w.Close() | ||
|
|
||
| actual := <-outCh | ||
|
|
||
| if !strings.Contains(actual, tt.want) { | ||
| t.Errorf("expected : %s, but got : %s", tt.want, actual) | ||
| } | ||
|
|
||
| }) | ||
| } | ||
| } | ||
|
|
||
| func TestDelete(t *testing.T) { | ||
| db := setupFakeDb() | ||
| todos.Init(&db) | ||
| users.Init(&db) | ||
|
|
||
| os.Args = []string{"go run main.go", "delete", "2"} | ||
| old := os.Stdout | ||
| r, w, _ := os.Pipe() | ||
| os.Stdout = w | ||
|
|
||
| defer func() { | ||
| os.Stdout = old | ||
| w.Close() | ||
| }() | ||
|
|
||
| Delete(db.users[0]) | ||
|
|
||
| outCh := make(chan string) | ||
| go func() { | ||
| var buf bytes.Buffer | ||
| io.Copy(&buf, r) | ||
| outCh <- buf.String() | ||
| }() | ||
| w.Close() | ||
|
|
||
| dontWant := "Sortir le chien" | ||
| actual := <-outCh | ||
|
|
||
| if strings.Contains(actual, dontWant) { | ||
| t.Errorf("expected : %s, but got : %s", dontWant, actual) | ||
| } | ||
| } | ||
|
|
||
| func TestModify(t *testing.T) { | ||
| db := setupFakeDb() | ||
| todos.Init(&db) | ||
| users.Init(&db) | ||
|
|
||
| old := os.Stdout | ||
| r, w, _ := os.Pipe() | ||
| os.Stdout = w | ||
|
|
||
| defer func() { | ||
| os.Stdout = old | ||
| w.Close() | ||
| }() | ||
|
|
||
| os.Args = []string{"go run main.go", "modify", "2", "Todo modifié", "1"} | ||
| fmt.Println(os.Args) | ||
| Modify(db.users[0]) | ||
|
|
||
| outCh := make(chan string) | ||
| go func() { | ||
| var buf bytes.Buffer | ||
| io.Copy(&buf, r) | ||
| outCh <- buf.String() | ||
| fmt.Println(outCh) | ||
| }() | ||
| w.Close() | ||
|
|
||
| want := "Todo modifié" | ||
| actual := <-outCh | ||
|
|
||
| if !strings.Contains(actual, want) { | ||
| t.Errorf("expected : %s, but got : %s", want, actual) | ||
| } | ||
| } |
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cf remarque sur add.go pour une fonction "usage", pour y ajouter tous les usages (ici, la suppression) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| package cmd | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "os" | ||
| "strconv" | ||
| "webstack/metier/todos" | ||
| "webstack/metier/users" | ||
| ) | ||
|
|
||
| const ERR_SUPR = "erreur de suppression de votre tâche" | ||
|
|
||
| func Delete(u users.User) { | ||
| if len(os.Args) != 3 { | ||
| fmt.Println("Usage: go run main.go delete <id>") | ||
| fmt.Println("") | ||
| fmt.Println("id : l'identifiant numérique du todo que vous souhaitez supprimer") | ||
| os.Exit(1) | ||
| } | ||
| id, err := strconv.Atoi(os.Args[2]) | ||
| if err != nil { | ||
| fmt.Println("Arguments invalides :") | ||
| fmt.Println("Usage: go run main.go delete <id>") | ||
| fmt.Println("") | ||
| fmt.Println("id : l'identifiant numérique du todo que vous souhaitez supprimer") | ||
| } | ||
| _, err = todos.Delete(id) | ||
| if err != nil { | ||
| fmt.Println(ERR_SUPR, err) | ||
| return | ||
| } | ||
| Get(u) | ||
| } |
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. est ce que les templates de Go ne pourraient pas remplacer la génération de texte brut ? |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| package cmd | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "strings" | ||
| "webstack/metier/todos" | ||
| "webstack/metier/users" | ||
| ) | ||
|
|
||
| type TodoCli struct { | ||
| id int | ||
| task string | ||
| priority string | ||
| } | ||
|
|
||
| func NewTodoCli(td todos.Todo) (todocli TodoCli) { | ||
| todocli.id = td.Id | ||
| todocli.task = todos.GetTask(td.Task) | ||
| if td.Priority == 3 { | ||
| todocli.priority = "urgent" | ||
| } else if td.Priority == 2 { | ||
| todocli.priority = "pas particulièrment pressé" | ||
| } else if td.Priority == 1 { | ||
| todocli.priority = "chill man" | ||
| } | ||
| return todocli | ||
| } | ||
|
|
||
| func Todos2TodosCli(list []todos.Todo) (displayedList []TodoCli) { | ||
| for _, todo := range list { | ||
| displayedList = append(displayedList, NewTodoCli(todo)) | ||
| } | ||
| return displayedList | ||
| } | ||
|
|
||
| func Get(u users.User) { | ||
| columns := []string{"Id", "Todo", "Priorité"} | ||
| list, err := todos.Get(u) | ||
| if err != nil { | ||
| err = fmt.Errorf("error get : %v", err) | ||
| fmt.Println(err) | ||
| return | ||
| } | ||
| displayed := Todos2TodosCli(list) | ||
| fmt.Println("+", strings.Repeat("-", 10), "+", strings.Repeat("-", 40), "+", strings.Repeat("-", 10), "+") | ||
| fmt.Printf("| %-60s |\n", "My Todolist") | ||
| fmt.Println("+", strings.Repeat("-", 10), "+", strings.Repeat("-", 40), "+", strings.Repeat("-", 10), "+") | ||
| fmt.Printf("| %-10s | %-40s | %-10s |\n", columns[0], columns[1], columns[2]) | ||
| fmt.Println("+", strings.Repeat("-", 10), "+", strings.Repeat("-", 40), "+", strings.Repeat("-", 10), "+") | ||
| for _, todo := range displayed { | ||
| fmt.Printf("| %-10d | %-40s | %-10s |\n", todo.id, todo.task, todo.priority) | ||
| } | ||
| fmt.Println("+", strings.Repeat("-", 10), "+", strings.Repeat("-", 40), "+", strings.Repeat("-", 10), "+") | ||
| } |
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cela pourrait être la fonction "usage" dont j'ai parlé dans mes précédents commentaires |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package cmd | ||
|
|
||
| import ( | ||
| "fmt" | ||
| ) | ||
|
|
||
| func Help() { | ||
| fmt.Println("Mytodolist en CLI !") | ||
| fmt.Println("Usage: mytodolist <command> [arguments]") | ||
| fmt.Println("") | ||
| fmt.Println("Commandes disponibles:") | ||
| fmt.Println(" get Affiche vos tâches") | ||
| fmt.Println(" add Ajouter une nouvelle tâche") | ||
| fmt.Println(" delete Supprime une tâche existante") | ||
| fmt.Println(" modify Modifie une tâche existante") | ||
| fmt.Println(" signin S'inscrire") | ||
| fmt.Println(" login Se connecter") | ||
| fmt.Println(" logout Se déconnecter") | ||
| fmt.Println(" help Affiche ce message") | ||
| fmt.Println("") | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
il y a moyen de mutualiser l'affichage de l'usage, par exemple, en créant une fonction "usage" et en l'utilisant partout où on en a besoin
attention au fait que le programme au final sera un binaire et pas utilisé à partir du code source : donc le "go run" ne convient pas. Remarque, il y a moyen de récupérer depuis le programme le nom du binaire exécuté (via le shell de mémoire)