func main() { var ( mongo = flag.String("mongo", "localhost", "Address of mongo instance") ) db, err := models.MongoDB(*mongo) if err != nil { log.Fatal(err) } iter, err := db.Query(models.TaskKind).Execute() if err != nil { log.Fatal(err) } count := 0 t := models.NewTask() for iter.Next(t) { if task.IsComplete(t) { t.CompletedAt = t.UpdatedAt if err := db.Save(t); err != nil { log.Fatal(err) } count++ } } log.Print("Migrated %d tasks", count) if err := iter.Close(); err != nil { log.Fatal(err) } }
func TestRecordQuery(t *testing.T) { db, _, s := testInstance(t, context.Background()) defer s.Close() user, cred := testUser(t, db) taskName := "task to retreive" task := models.NewTask() task.SetID(db.NewID()) task.CreatedAt = time.Now() task.OwnerId = user.Id task.Name = taskName task.UpdatedAt = time.Now() if err := db.Save(task); err != nil { t.Fatal(err) } params := url.Values{} params.Set("kind", models.TaskKind.String()) params.Set("id", task.ID().String()) url := s.URL + "/record/query/?" + params.Encode() t.Logf("Constructed URL: %s", url) requestBody, err := json.Marshal(data.AttrMap{ "name": taskName, }) if err != nil { t.Fatal(err) } req, err := http.NewRequest("POST", url, bytes.NewBuffer(requestBody)) if err != nil { t.Fatal(err) } req.SetBasicAuth(cred.Public, cred.Private) resp, err := http.DefaultClient.Do(req) if err != nil { t.Fatal(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { t.Fatal(err) } t.Logf("Code: %d", resp.StatusCode) t.Logf("Body:\n%s", body) if resp.StatusCode != http.StatusOK { t.Fatalf("Expected status code of %d", http.StatusOK) } if !strings.Contains(string(body), taskName) { t.Fatal("Response body should have contained the task name") } }
func TestRecordDELETE(t *testing.T) { db, _, s := testInstance(t, context.Background()) defer s.Close() user, cred := testUser(t, db) taskName := "task to modify" task := models.NewTask() task.SetID(db.NewID()) task.CreatedAt = time.Now() task.OwnerId = user.Id task.Name = taskName task.UpdatedAt = time.Now() if err := db.Save(task); err != nil { t.Fatal(err) } params := url.Values{} params.Set("kind", models.TaskKind.String()) params.Set("id", task.ID().String()) url := s.URL + "/record/?" + params.Encode() t.Logf("Constructed URL: %s", url) req, err := http.NewRequest("DELETE", url, nil) if err != nil { t.Fatal(err) } req.SetBasicAuth(cred.Public, cred.Private) resp, err := http.DefaultClient.Do(req) if err != nil { t.Fatal(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { t.Fatal(err) } t.Logf("Code: %d", resp.StatusCode) t.Logf("Body:\n%s", body) if resp.StatusCode != http.StatusNoContent { t.Fatalf("Expected status code of %d", http.StatusNoContent) } if string(body) != "" { t.Fatalf("Response body should be empty, but got: '%s'", string(body)) } if err := db.PopulateByID(task); err != data.ErrNotFound { t.Fatal("The task should not be able to be found") } }
func (c *XCommand) runReview(args []string) int { db := c.DB switch args[1] { case "taskweek": iter, err := db.Query(models.TaskKind).Select(data.AttrMap{"owner_id": c.UserID}).Execute() if err != nil { log.Fatal(err) return failure } oneWeekAgo := time.Now().Add(-7 * 24 * time.Hour) completedInLastWeek := make([]*models.Task, 0) t := models.NewTask() for iter.Next(t) { if t.CompletedAt.Local().After(oneWeekAgo.Local()) { completedInLastWeek = append(completedInLastWeek, t) t = models.NewTask() } } if len(completedInLastWeek) == 0 { c.UI.Output("No tasks completed in last week") return success } sort.Sort(task.ByCompletedAt(completedInLastWeek)) for _, t := range completedInLastWeek { c.UI.Output(fmt.Sprintf("\t* %s [%s]", t.Name, t.CompletedAt.Local().Format("Mon Jan 2"))) } } return success }
func TestDB(t *testing.T) { db, _, s := testInstance(t, context.Background()) defer s.Close() user, cred := testUser(t, db) gdb := &gaia.DB{ URL: s.URL, Username: cred.Public, Password: cred.Private, Client: http.DefaultClient, } t.Log("Creating a test task") taskName := "task name" task := models.NewTask() task.SetID(db.NewID()) task.CreatedAt = time.Now() task.OwnerId = user.Id task.Name = taskName task.UpdatedAt = time.Now() if err := db.Save(task); err != nil { t.Fatal(err) } t.Log("Test task created") t.Log("Creating a task to retrieve using the gaia db") getTask := models.NewTask() getTask.SetID(task.ID()) // use task's id t.Logf("Retrieving task using ID: %s and the gaia db", task.ID().String()) if err := gdb.PopulateByID(getTask); err != nil { t.Fatal(err) } t.Logf("Task retrieved: %+v", getTask) if getTask.Name != taskName { t.Fatal("Task names should match") } t.Log("Deleting task using the gaia db") if err := gdb.Delete(getTask); err != nil { t.Fatal(err) } t.Log("Task deleted") t.Log("Checking that task is no longer in real database") if err := db.PopulateByID(task); err != data.ErrNotFound { t.Fatal("Task should be gone") } t.Log("Checked") t.Log("Using gaia db to recreate that task") if err := gdb.Save(task); err != nil { t.Fatal(err) } t.Log("Recreated") t.Log("Checking that task back in real database") if err := db.PopulateByID(task); err != nil { t.Fatal("Task should be back") } if task.Name != taskName { t.Fatalf("Task name should be %s", taskName) } t.Log("Checked") t.Log("Changing task name") newName := "new name" getTask.Name = newName t.Log("Changed") t.Log("Using gaia db to update the task") if err := gdb.Save(getTask); err != nil { t.Fatal(err) } t.Log("Updated") t.Log("Re-retrieving that task from the real db") if err := db.PopulateByID(task); err != nil { t.Fatal(err) } t.Log("Retrieved") t.Log("Checking that the task was updated") if task.Name != newName { t.Fatalf("Save should have updated the task") } t.Log("Checked") t.Log("Querying for the task using gaia db") q := gdb.Query(models.TaskKind) q.Select(data.AttrMap{ "name": newName, }) iter, err := q.Execute() if err != nil { t.Fatal(err) } t.Log("Query executed") t.Log("Examining query results") result := models.NewTask() iter.Next(result) if iter.Next(result) != false { t.Fatal("Should only be one result") } if err := iter.Close(); err != nil { t.Fatal(err) } if result.ID().String() != task.ID().String() { t.Fatal("Ids should match") } if result.Name != newName { t.Fatal("should ahve retrievied the task with the new name") } t.Log("Examined") changes := db.Changes() eventName := "hello" e := models.NewEvent() e.SetID(db.NewID()) e.SetOwner(user) e.Name = eventName if err := db.Save(e); err != nil { t.Fatal(err) } select { case c := <-*changes: t.Logf("Change received:\n%++v", c) if c.Record.(*models.Event).Name != eventName { t.Fatalf("Change should have been recieved with event record and name '%s'", eventName) } case <-time.After(50 * time.Millisecond): t.Fatalf("Timed out waiting for change") } }
func TestCommandSMSInput(t *testing.T) { db := mem.NewDB() sms := newMockSMS() mux := services.NewSMSMux() ctx := context.Background() ctx, cancel := context.WithCancel(ctx) defer cancel() go mux.Start(ctx, db, sms) ctx, cancelContext := context.WithCancel(context.Background()) defer cancelContext() g := gaia.New( ctx, &gaia.Middleware{}, &gaia.Services{ Logger: services.NewTestLogger(t), DB: db, SMSCommandSessions: mux, WebCommandSessions: services.NewWebMux(), }, ) s := httptest.NewServer(g) defer s.Close() u, _ := testUser(t, db) t.Log("Creating profile") p := models.NewProfile() p.SetID(db.NewID()) phone := "650 123 4567" p.Phone = phone p.SetOwner(u) if err := db.Save(p); err != nil { t.Fatal(err) } t.Log("Created") messageBody := "todo new" fakeSMS(t, s, phone, phone, messageBody) select { case m := <-sms.bus: t.Logf("Message:\n%+v", m) if !strings.Contains(m.body, "Name") { t.Fatal("The message should have asked for name of task") } case <-time.After(1 * time.Second): t.Fatal("Timed out waiting for sms message") } taskName := "task name" // for the name fakeSMS(t, s, phone, phone, taskName) select { case m := <-sms.bus: t.Logf("Message:\n%+v", m) if !strings.Contains(m.body, "deadline") { t.Fatal("The message should have asked if it had a deadline") } case <-time.After(1 * time.Second): t.Fatal("Timed out waiting for sms message") } fakeSMS(t, s, phone, phone, "n") // no deadline select { case m := <-sms.bus: t.Logf("Message:\n%+v", m) if !strings.Contains(m.body, "prerequisites") { t.Fatal("The message should have asked if it had a prereqs") } case <-time.After(1 * time.Second): t.Fatal("Timed out waiting for sms message") } fakeSMS(t, s, phone, phone, "n") // no prereqs select { case m := <-sms.bus: t.Logf("Message:\n%+v", m) if !strings.Contains(m.body, "created") { t.Fatal("Should have indicated task was created") } case <-time.After(1 * time.Second): t.Fatal("Timed out waiting for sms message") } task := models.NewTask() // ensure the task exists if err := db.PopulateByField("name", taskName, task); err != nil { t.Fatal(err) } t.Logf("Task:\n%+v", task) }
func TestRecordChanges(t *testing.T) { ctx, cancelAllConnections := context.WithCancel(context.Background()) defer cancelAllConnections() db, _, s := testInstance(t, ctx) defer s.Close() user, cred := testUser(t, db) serverURL := s.URL origin := serverURL wsURL := strings.Replace(serverURL, "http", "ws", 1) params := url.Values{} params.Set("public", cred.Public) params.Set("private", cred.Private) params.Set("kind", models.TaskKind.String()) wsURL += routes.RecordChanges + "?" + params.Encode() t.Logf("Constructed URL: %s", wsURL) t.Log("Opening websocket") ws, err := websocket.Dial(wsURL, "", origin) if err != nil { t.Fatal(err) } defer ws.Close() t.Log("Websocket openened") time.Sleep(500 * time.Millisecond) t.Log("Creating task") taskName := "task to retreive" task := models.NewTask() task.SetID(db.NewID()) task.CreatedAt = time.Now() task.OwnerId = user.Id task.Name = taskName task.UpdatedAt = time.Now() if err := db.Save(task); err != nil { t.Fatal(err) } t.Log("Task created") var ct transfer.ChangeTransport if err := websocket.JSON.Receive(ws, &ct); err != nil { t.Fatal(err) } tc := transfer.ChangeFrom(&ct, models.ModelFor(ct.RecordKind)) t.Logf("Task Change Recieved: %++v", tc) t.Log("Cancelling the connection") cancelAllConnections() t.Log("\tcancelled") if tc.ChangeKind != data.Update { t.Fatal("Expected ChangeKind to be Update") } if tc.Record.(*models.Task).Name != taskName { t.Fatalf("Expected task name to be: '%s'", taskName) } }
func TestRecordQuerySkip(t *testing.T) { db, _, s := testInstance(t, context.Background()) defer s.Close() user, cred := testUser(t, db) task1 := models.NewTask() task1.SetID(db.NewID()) task1.CreatedAt = time.Now() task1.OwnerId = user.Id task1.Name = "task1" task1.UpdatedAt = time.Now() if err := db.Save(task1); err != nil { t.Fatal(err) } task2 := models.NewTask() task2.SetID(db.NewID()) task2.CreatedAt = time.Now() task2.OwnerId = user.Id task2.Name = "task2" task2.UpdatedAt = time.Now() if err := db.Save(task2); err != nil { t.Fatal(err) } params := url.Values{} params.Set("kind", models.TaskKind.String()) params.Set("skip", "1") url := s.URL + "/record/query/?" + params.Encode() t.Logf("Constructed URL: %s", url) req, err := http.NewRequest("POST", url, nil) if err != nil { t.Fatal(err) } req.SetBasicAuth(cred.Public, cred.Private) resp, err := http.DefaultClient.Do(req) if err != nil { t.Fatal(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { t.Fatal(err) } t.Logf("Code: %d", resp.StatusCode) t.Logf("Body:\n%s", body) if resp.StatusCode != http.StatusOK { t.Fatalf("Expected status code of %d", http.StatusOK) } // Should contain one or the other, but not both if strings.Contains(string(body), "task1") { if strings.Contains(string(body), "task2") { t.Fatal("Response body should have contained task2") } } else { if !strings.Contains(string(body), "task2") { t.Fatal("Response body should have contained task2") } } }