update tests
This commit is contained in:
parent
23647d74fc
commit
605ea31fe1
3 changed files with 258 additions and 124 deletions
22
handler.go
22
handler.go
|
|
@ -31,7 +31,13 @@ func (h *handler) form(w http.ResponseWriter, r *http.Request) {
|
|||
Order order
|
||||
Catalogue []cake
|
||||
}
|
||||
data := formData{o, h.s.getCakes()}
|
||||
|
||||
cakes, err := h.s.getCakes()
|
||||
if err != nil {
|
||||
fmt.Fprint(w, "server side error getting available cakes: ", err)
|
||||
return
|
||||
}
|
||||
data := formData{o, cakes}
|
||||
fmt.Println(data)
|
||||
|
||||
w.Header().Set("content-type", "text/html")
|
||||
|
|
@ -85,7 +91,12 @@ func (h *handler) addOrder(w http.ResponseWriter, r *http.Request) {
|
|||
n.Accepted = time.Now()
|
||||
|
||||
n.Cakes = make([]cake, 0)
|
||||
for _, e := range h.s.getCakes() {
|
||||
cakes, err := h.s.getCakes()
|
||||
if err != nil {
|
||||
fmt.Fprint(w, "server side error getting available cakes: ", err)
|
||||
return
|
||||
}
|
||||
for _, e := range cakes {
|
||||
value := r.FormValue(fmt.Sprintf("cake[%d]", e.ID))
|
||||
if value == "" {
|
||||
continue
|
||||
|
|
@ -109,7 +120,12 @@ func (h *handler) addOrder(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
func (h *handler) index(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("content-type", "text/html")
|
||||
err := h.tmpl.ExecuteTemplate(w, "index.html", h.s.getOrders())
|
||||
orders, err := h.s.getOrders()
|
||||
if err != nil {
|
||||
fmt.Fprint(w, "server side error getting orders: ", err)
|
||||
return
|
||||
}
|
||||
err = h.tmpl.ExecuteTemplate(w, "index.html", orders)
|
||||
if err != nil {
|
||||
fmt.Println("error executing the template: ", err)
|
||||
}
|
||||
|
|
|
|||
47
store.go
47
store.go
|
|
@ -1,9 +1,9 @@
|
|||
// #todo: check for errors in every rows.Scan()
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
|
@ -37,25 +37,27 @@ func NewStore(filename string) (*store, error) {
|
|||
return &out, nil
|
||||
}
|
||||
|
||||
// #todo: should return an error
|
||||
func (s *store) getCakes() []cake {
|
||||
// #todo: error handling
|
||||
func (s *store) close() {
|
||||
s.db.Close()
|
||||
}
|
||||
|
||||
func (s *store) getCakes() ([]cake, error) {
|
||||
rows, err := s.db.Query("select id, name, price from cake")
|
||||
defer rows.Close()
|
||||
if err != nil {
|
||||
return nil
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
cakes := make([]cake, 0)
|
||||
for rows.Next() {
|
||||
var c cake
|
||||
err = rows.Scan(&c.ID, &c.Name, &c.Price)
|
||||
c.Amount = 0
|
||||
err = rows.Scan(&c.ID, &c.Name, &c.Price)
|
||||
if err != nil {
|
||||
fmt.Println("error scanning rows into cake: ", err)
|
||||
return nil, err
|
||||
}
|
||||
cakes = append(cakes, c)
|
||||
}
|
||||
return cakes
|
||||
return cakes, err
|
||||
}
|
||||
|
||||
func (s *store) saveCake(newCake cake) (int, error) {
|
||||
|
|
@ -74,8 +76,8 @@ func (s *store) saveCake(newCake cake) (int, error) {
|
|||
|
||||
// #todo: see if next is required or not to get the first element
|
||||
row.Next()
|
||||
row.Scan(&newCake.ID)
|
||||
return newCake.ID, nil
|
||||
err = row.Scan(&newCake.ID)
|
||||
return newCake.ID, err
|
||||
}
|
||||
|
||||
// #todo: retrieve and save order contents
|
||||
|
|
@ -98,26 +100,29 @@ func (s *store) getOrder(id int) (order, error) {
|
|||
}
|
||||
|
||||
// #todo: should return an error
|
||||
func (s *store) getOrders() []order {
|
||||
func (s *store) getOrders() ([]order, error) {
|
||||
var out []order
|
||||
// #todo: error handling
|
||||
row, err := s.db.Query("select id, name, surname, phone, location, order_date, delivery_date, status, paid from customer_order;")
|
||||
defer row.Close()
|
||||
rows, err := s.db.Query("select id, name, surname, phone, location, order_date, delivery_date, status, paid from customer_order;")
|
||||
if err != nil {
|
||||
return out
|
||||
return out, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
for row.Next() {
|
||||
for rows.Next() {
|
||||
var o order
|
||||
var order_date, delivery_date string
|
||||
row.Scan(&o.ID, &o.Name, &o.Surname, &o.Phone, &o.Location, &order_date, &delivery_date, &o.Status, &o.Paid)
|
||||
err = rows.Scan(&o.ID, &o.Name, &o.Surname, &o.Phone, &o.Location, &order_date, &delivery_date, &o.Status, &o.Paid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// #todo: error handling
|
||||
// figure out what to do with errors, as they shouldn't really crash the app, but there should probably be an indication that something went wrong
|
||||
o.Accepted, _ = time.Parse("2006-01-02 15:04", order_date)
|
||||
o.Date, _ = time.Parse("2006-01-02 15:04", delivery_date)
|
||||
out = append(out, o)
|
||||
}
|
||||
|
||||
return out
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *store) saveOrder(newOrder order) (int, error) {
|
||||
|
|
@ -139,6 +144,6 @@ func (s *store) saveOrder(newOrder order) (int, error) {
|
|||
|
||||
// #todo: see if next is required or not to get the first element
|
||||
row.Next()
|
||||
row.Scan(&newOrder.ID)
|
||||
return newOrder.ID, nil
|
||||
err = row.Scan(&newOrder.ID)
|
||||
return newOrder.ID, err
|
||||
}
|
||||
|
|
|
|||
313
store_test.go
313
store_test.go
|
|
@ -5,136 +5,249 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func TestCakeOperations(t *testing.T) {
|
||||
func TestStore(t *testing.T) {
|
||||
s, err := NewStore(":memory:")
|
||||
if err != nil {
|
||||
t.Fatal("Failed to open database", err)
|
||||
t.Fatalf("Failed to create store: %v", err)
|
||||
}
|
||||
defer s.db.Close()
|
||||
defer s.close()
|
||||
|
||||
c := cake{
|
||||
ID: -1,
|
||||
Name: "Test Cake",
|
||||
Price: 10,
|
||||
}
|
||||
|
||||
id, err := s.saveCake(c)
|
||||
if id == -1 || err != nil {
|
||||
t.Fatal("Failed to save cake", err)
|
||||
}
|
||||
|
||||
cakes := s.getCakes()
|
||||
if len(cakes) != 1 {
|
||||
t.Errorf("Expected 1 cake, got %d", len(cakes))
|
||||
}
|
||||
|
||||
if cakes[0].Name != "Test Cake" || cakes[0].Price != 10 {
|
||||
t.Errorf("Cake data mismatch. Got %+v", cakes[0])
|
||||
}
|
||||
|
||||
updatedCake := cake{
|
||||
ID: id,
|
||||
Name: "Updated Cake",
|
||||
Price: 15,
|
||||
}
|
||||
|
||||
newID, err := s.saveCake(updatedCake)
|
||||
if newID != id {
|
||||
t.Errorf("Update returned different ID. Expected %d, got %d", id, newID)
|
||||
}
|
||||
|
||||
cakes = s.getCakes()
|
||||
if cakes[0].Name != "Updated Cake" || cakes[0].Price != 15 {
|
||||
t.Errorf("Cake update failed. Got %+v", cakes[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrderOperations(t *testing.T) {
|
||||
s, err := NewStore(":memory:")
|
||||
// ensure db is empty
|
||||
cakes, err := s.getCakes()
|
||||
if err != nil {
|
||||
t.Fatal("Failed to open database", err)
|
||||
t.Errorf("Error getting cakes: %v", err)
|
||||
}
|
||||
if len(cakes) != 0 {
|
||||
t.Errorf("Expected empty cakes list, got: %v", cakes)
|
||||
}
|
||||
orders, err := s.getOrders()
|
||||
if err != nil {
|
||||
t.Errorf("Error getting orders: %v", err)
|
||||
}
|
||||
if len(orders) != 0 {
|
||||
t.Errorf("Expected empty orders list, got: %v", orders)
|
||||
}
|
||||
defer s.db.Close()
|
||||
|
||||
// create new cake
|
||||
newCake := cake{Name: "Chocolate Cake", ID: -1, Price: 2500, Amount: -1}
|
||||
newCake.ID, err = s.saveCake(newCake)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to save new cake: %v", err)
|
||||
}
|
||||
if newCake.ID <= 0 {
|
||||
t.Errorf("Expected positive cake ID, got: %d", newCake.ID)
|
||||
}
|
||||
|
||||
// create another cake
|
||||
anotherCake := cake{Name: "Another Cake", ID: -1, Price: 3000, Amount: -1}
|
||||
anotherCake.ID, err = s.saveCake(anotherCake)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to save new cake: %v", err)
|
||||
}
|
||||
if anotherCake.ID <= 0 {
|
||||
t.Errorf("Expected positive cake ID, got: %d", anotherCake.ID)
|
||||
}
|
||||
|
||||
// Update Existing Cake
|
||||
newCake.Name = "Updated Cake"
|
||||
newCake.Price = 100
|
||||
newID, err := s.saveCake(newCake)
|
||||
if newID != newCake.ID {
|
||||
t.Error("wrong id")
|
||||
}
|
||||
if err != nil {
|
||||
t.Error("error updating cake", err)
|
||||
}
|
||||
|
||||
// Update Non-existing Cake
|
||||
var updatedCake cake
|
||||
updatedCake.ID = 10
|
||||
_, err = s.saveCake(updatedCake)
|
||||
if err == nil {
|
||||
t.Error("did not return an error when attempted to update non existant cake")
|
||||
}
|
||||
|
||||
// get cakes
|
||||
cakes, err = s.getCakes()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get all cakes after creation: %v", err)
|
||||
}
|
||||
if len(cakes) != 2 {
|
||||
t.Error("Expected two cakes returned, got ", len(cakes))
|
||||
}
|
||||
for i, c := range cakes {
|
||||
if c.ID == newCake.ID {
|
||||
newCake.Amount = i
|
||||
}
|
||||
if c.ID == anotherCake.ID {
|
||||
anotherCake.Amount = i
|
||||
}
|
||||
}
|
||||
if newCake.Amount == -1 {
|
||||
t.Error("not found newCake")
|
||||
}
|
||||
if cakes[newCake.Amount].ID != newCake.ID || cakes[newCake.Amount].Name != newCake.Name || cakes[newCake.Amount].Price != newCake.Price {
|
||||
t.Errorf("Want %v\nGot %v", newCake, cakes)
|
||||
}
|
||||
if anotherCake.Amount == -1 {
|
||||
t.Error("not found anotherCake")
|
||||
}
|
||||
if cakes[anotherCake.Amount].ID != anotherCake.ID || cakes[anotherCake.Amount].Name != anotherCake.Name || cakes[anotherCake.Amount].Price != anotherCake.Price {
|
||||
t.Errorf("Want %v\nGot %v", anotherCake, cakes)
|
||||
}
|
||||
|
||||
// create new order
|
||||
now := time.Now()
|
||||
delivery := now.Add(24 * time.Hour)
|
||||
|
||||
o := order{
|
||||
newOrder := order{
|
||||
ID: -1,
|
||||
Name: "John",
|
||||
Surname: "Doe",
|
||||
Phone: "1234567890",
|
||||
Location: "123 Test St",
|
||||
Phone: "123-456-7890",
|
||||
Location: "Some Location",
|
||||
Accepted: now,
|
||||
Date: delivery,
|
||||
Status: "pending",
|
||||
Paid: 0,
|
||||
Date: now.Add(time.Hour * 24),
|
||||
Status: "Pending",
|
||||
Paid: 1000,
|
||||
Cakes: []cake{{ID: newCake.ID, Amount: 2}, {ID: anotherCake.ID, Amount: 10}},
|
||||
}
|
||||
|
||||
id, err := s.saveOrder(o)
|
||||
if id == -1 || err != nil {
|
||||
t.Fatal("Failed to save order", err)
|
||||
}
|
||||
|
||||
retrieved, err := s.getOrder(id)
|
||||
newOrder.ID, err = s.saveOrder(newOrder)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get order: %v", err)
|
||||
t.Fatalf("Failed to save new order: %v", err)
|
||||
}
|
||||
if newOrder.ID <= 0 {
|
||||
t.Errorf("Expected positive order ID, got: %d", newOrder.ID)
|
||||
}
|
||||
|
||||
if retrieved.Name != "John" || retrieved.Surname != "Doe" {
|
||||
t.Errorf("Order names mismatch. Got %+v", retrieved)
|
||||
// create another order
|
||||
anotherOrder := order{
|
||||
ID: -1,
|
||||
Name: "Jane",
|
||||
Surname: "Doe",
|
||||
Phone: "123-456-7890",
|
||||
Location: "New Location",
|
||||
Accepted: now,
|
||||
Date: now.Add(time.Hour * 192),
|
||||
Status: "Accepted",
|
||||
Paid: 1500,
|
||||
Cakes: []cake{{ID: newCake.ID, Amount: 100}},
|
||||
}
|
||||
|
||||
if !timeEqual(retrieved.Date, o.Date) || !timeEqual(retrieved.Accepted, o.Accepted) {
|
||||
t.Errorf("Order dates mismatch. \nGot %+v\nWant %+v", retrieved, o)
|
||||
}
|
||||
|
||||
orders := s.getOrders()
|
||||
if len(orders) != 1 {
|
||||
t.Errorf("Expected 1 order, got %d", len(orders))
|
||||
}
|
||||
|
||||
// Test updating an order
|
||||
o.ID = id
|
||||
o.Status = "completed"
|
||||
|
||||
newID, err := s.saveOrder(o)
|
||||
anotherOrder.ID, err = s.saveOrder(anotherOrder)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to save order", err)
|
||||
t.Fatalf("Failed to save new order: %v", err)
|
||||
}
|
||||
if newID != id {
|
||||
t.Errorf("Update returned different ID. Expected %d, got %d", id, newID)
|
||||
if anotherOrder.ID <= 0 {
|
||||
t.Errorf("Expected positive order ID, got: %d", anotherOrder.ID)
|
||||
}
|
||||
|
||||
updated, err := s.getOrder(id)
|
||||
// update existing order
|
||||
newOrder.Name = "James"
|
||||
newOrder.Status = "Done"
|
||||
newOrder.Cakes = newOrder.Cakes[1:]
|
||||
newID, err = s.saveOrder(newOrder)
|
||||
if newID != newOrder.ID {
|
||||
t.Error("wrong id")
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get updated order: %v", err)
|
||||
t.Error("error updating order", err)
|
||||
}
|
||||
|
||||
if updated.Status != "completed" {
|
||||
t.Errorf("Order update failed. Got %+v", updated)
|
||||
// update non existing order
|
||||
var updatedOrder order
|
||||
updatedOrder.ID = 10
|
||||
_, err = s.saveOrder(updatedOrder)
|
||||
if err == nil {
|
||||
t.Error("did not return an error when attempted to update non existant cake")
|
||||
}
|
||||
|
||||
// get orders
|
||||
orders, err = s.getOrders()
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get all orders after creation: %v", err)
|
||||
}
|
||||
if len(orders) != 2 {
|
||||
t.Error("Expected two orders returned, got ", len(orders))
|
||||
}
|
||||
newOrderPos := -1
|
||||
anotherOrderPos := -1
|
||||
for i, o := range orders {
|
||||
if o.ID == newOrder.ID {
|
||||
newOrderPos = i
|
||||
}
|
||||
if o.ID == anotherOrder.ID {
|
||||
anotherOrderPos = i
|
||||
}
|
||||
}
|
||||
if newOrderPos == -1 {
|
||||
t.Error("not found newOrder")
|
||||
}
|
||||
if newOrder.Name != orders[newOrderPos].Name ||
|
||||
newOrder.Surname != orders[newOrderPos].Surname ||
|
||||
newOrder.Phone != orders[newOrderPos].Phone ||
|
||||
newOrder.Status != orders[newOrderPos].Status ||
|
||||
newOrder.Location != orders[newOrderPos].Location ||
|
||||
newOrder.Accepted.Format("2006-01-02 15:04") != newOrder.Accepted.Format("2006-01-02 15:04") ||
|
||||
newOrder.Date.Format("2006-01-02 15:04") != newOrder.Date.Format("2006-01-02 15:04") {
|
||||
t.Errorf("Want %v\nGot %v", newOrder, orders[newOrderPos])
|
||||
}
|
||||
|
||||
if anotherOrderPos == -1 {
|
||||
t.Error("not found anotherOrder")
|
||||
}
|
||||
if anotherOrder.Name != orders[anotherOrderPos].Name ||
|
||||
anotherOrder.Surname != orders[anotherOrderPos].Surname ||
|
||||
anotherOrder.Phone != orders[anotherOrderPos].Phone ||
|
||||
anotherOrder.Status != orders[anotherOrderPos].Status ||
|
||||
anotherOrder.Location != orders[anotherOrderPos].Location ||
|
||||
anotherOrder.Accepted.Format("2006-01-02 15:04") != anotherOrder.Accepted.Format("2006-01-02 15:04") ||
|
||||
anotherOrder.Date.Format("2006-01-02 15:04") != anotherOrder.Date.Format("2006-01-02 15:04") {
|
||||
t.Errorf("Want %v\nGot %v", anotherOrder, orders[anotherOrderPos])
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreInitialization(t *testing.T) {
|
||||
s, err := NewStore(":memory:")
|
||||
if err != nil {
|
||||
t.Fatal("Failed to open database", err)
|
||||
}
|
||||
defer s.db.Close()
|
||||
|
||||
cakes := s.getCakes()
|
||||
if len(cakes) != 0 {
|
||||
t.Errorf("New store should have no cakes, got %d", len(cakes))
|
||||
func TestSliceComparison(t *testing.T) {
|
||||
a := []cake{
|
||||
{Name: "ok", Price: 100, ID: 12, Amount: 10},
|
||||
{Name: "ok", Price: 11, ID: 13, Amount: 1},
|
||||
{Name: "ok", Price: 100, ID: 10, Amount: 11},
|
||||
}
|
||||
|
||||
orders := s.getOrders()
|
||||
if len(orders) != 0 {
|
||||
t.Errorf("New store should have no orders, got %d", len(orders))
|
||||
b := []cake{
|
||||
{Name: "okas", Price: 110, ID: 12, Amount: 10},
|
||||
{Name: "oksa", Price: 11, ID: 13, Amount: 1},
|
||||
{Name: "oasdk", Price: 101, ID: 10, Amount: 11},
|
||||
}
|
||||
if !areCakeSlicesEqual(a, b) {
|
||||
t.Error("aren't equal")
|
||||
}
|
||||
}
|
||||
|
||||
func timeEqual(t1, t2 time.Time) bool {
|
||||
format := "2006-01-02 15:04"
|
||||
return t1.Format(format) == t2.Format(format)
|
||||
func areCakesEqual(a, b cake) bool {
|
||||
return a.ID == b.ID && a.Amount == b.Amount
|
||||
}
|
||||
|
||||
func areCakeSlicesEqual(a, b []cake) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
|
||||
matched := make([]bool, len(a))
|
||||
|
||||
mainLoop:
|
||||
for _, e1 := range a {
|
||||
for i, e2 := range b {
|
||||
if matched[i] {
|
||||
continue
|
||||
}
|
||||
if areCakesEqual(e1, e2) {
|
||||
matched[i] = true
|
||||
continue mainLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, e := range matched {
|
||||
if e == false {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue