Exemple #1
0
func newTestTask(t *testing.T, db data.DB, u *models.User) *models.Task {
	tsk := new(models.Task)
	tsk.SetID(db.NewID())
	tsk.CreatedAt = models.TimestampFrom(time.Now())
	tsk.OwnerId = u.ID().String()
	tsk.UpdatedAt = models.TimestampFrom(time.Now())
	if err := db.Save(tsk); err != nil {
		t.Fatalf("Error newTestTask: %s", err)
	}
	return tsk
}
Exemple #2
0
// --- `elos todo today` {{{
func TestTodoToday(t *testing.T) {
	ui, db, user, c := newMockTodoCommand(t)

	// load a task into the db
	tsk := newTestTask(t, db, user)
	taskName := "Take out the trash"
	tsk.Name = taskName
	task.StopAndComplete(tsk)
	if err := db.Save(tsk); err != nil {
		t.Fatal(err)
	}

	tsk2 := newTestTask(t, db, user)
	task2Name := "shouldn't show up"
	tsk2.Name = task2Name
	tsk2.CompletedAt = models.TimestampFrom(time.Now().Add(-48 * time.Hour))
	if err := db.Save(tsk2); err != nil {
		t.Fatal(err)
	}

	t.Log("running: `elos todo today`")
	code := c.Run([]string{"today"})
	t.Log("command 'today' terminated")

	errput := ui.ErrorWriter.String()
	output := ui.OutputWriter.String()
	t.Logf("Error output:\n %s", errput)
	t.Logf("Output:\n %s", output)

	// verify there were no errors
	if errput != "" {
		t.Fatalf("Expected no error output, got: %s", errput)
	}

	// verify success
	if code != success {
		t.Fatalf("Expected successful exit code along with empty error output.")
	}

	// verify some of the output
	if !strings.Contains(output, taskName) {
		t.Fatalf("Output should have contained a task we completed today: %s", taskName)
	}

	if strings.Contains(output, task2Name) {
		t.Fatalf("Output should not have contained: '%s', the name of a task completed 2 days ago", task2Name)
	}
}
Exemple #3
0
// promptNewTask implements the process of creating a task using text
// input and output
//
// Use for creating a new task, which promptNewTask returns a handle to.
//
// promptNewTask adds the task to c.tasks.
//
func (c *TodoCommand) promptNewTask() (task *models.Task, err error) {
	var (
		hasDeadline bool
		hasPrereqs  bool
	)

	task = new(models.Task)
	task.SetID(c.DB.NewID())
	task.CreatedAt = models.TimestampFrom(time.Now())
	task.OwnerId = c.UserID

	if task.Name, err = stringInput(c.UI, "Name:"); err != nil {
		return
	}

	if hasDeadline, err = yesNo(c.UI, "Does it have a deadline?"); err != nil {
		return
	} else if hasDeadline {
		if task.DeadlineAt, err = timestamp(dateInput(c.UI, "Deadline:")); err != nil {
			return
		}
	}

	if hasPrereqs, err = yesNo(c.UI, "Does it have any prerequisites?"); err != nil {
		return
	} else if hasPrereqs {
		var currentTaskPrereq, newTaskPrereq bool

		if len(c.tasks) > 0 {
			c.printTaskList()
			if currentTaskPrereq, err = yesNo(c.UI, "Any dependencies that are current?"); err != nil {
				return
			} else if currentTaskPrereq {
				for currentTaskPrereq {
					var indexOfCurrent int

					if indexOfCurrent, err = intInput(c.UI, "Which number?"); err != nil {
						return
					}

					if indexOfCurrent < 0 || indexOfCurrent > len(c.tasks)-1 {
						c.UI.Warn("That isn't a valid index")
						continue
					}

					addId := c.tasks[indexOfCurrent].Id
					for _, id := range task.PrerequisiteIds {
						if id == addId {
							goto noadd
						}
					}
					task.PrerequisiteIds = append(task.PrerequisiteIds, addId)
				noadd:

					if currentTaskPrereq, err = yesNo(c.UI, "Any more current prereqs?"); err != nil {
						return
					}
				}
			}
		}

		if newTaskPrereq, err = yesNo(c.UI, "Any dependencies that are new tasks?"); err != nil {
			return
		} else if newTaskPrereq {
			var newTask *models.Task
			for newTaskPrereq {
				if newTask, err = c.promptNewTask(); err != nil {
					return
				}

				task.PrerequisiteIds = append(task.PrerequisiteIds, newTask.Id)

				if newTaskPrereq, err = yesNo(c.UI, "Any more new prereqs?"); err != nil {
					return
				}

			}
		}
	}

	task.UpdatedAt = models.TimestampFrom(time.Now())

	// if successful save
	if err = c.DB.Save(task); err == nil {
		c.tasks = append(c.tasks, task)
		c.UI.Output("Task created")
	}

	return
}
Exemple #4
0
func timestamp(t time.Time, err error) (*models.Timestamp, error) {
	return models.TimestampFrom(t), err
}
Exemple #5
0
func TestRecords(t *testing.T) {
	cases := map[string]struct {
		args             []string
		code             int
		in, err, out     []byte
		prior, posterior data.State
	}{

		// elos records kinds {{{
		"elos records kinds": {
			args: []string{"kinds"},
			out:  []byte(strings.Join(apply(s(models.Kinds), func(s string) string { return "* " + s }), "\n") + "\n"),
			prior: data.State{
				models.Kind_USER: []*data.Record{
					&data.Record{
						Kind: models.Kind_USER,
						User: &models.User{
							Id: "1",
						},
					},
				},
				models.Kind_CREDENTIAL: []*data.Record{
					&data.Record{
						Kind: models.Kind_CREDENTIAL,
						Credential: &models.Credential{
							Id:      "2",
							Type:    models.Credential_PASSWORD,
							Public:  "pu",
							Private: "pr",
							OwnerId: "1",
						},
					},
				},
			},
		},
		// }}}

		// elos records count {{{
		"elos records count": {
			args: []string{"count"},
			in:   []byte("SESSION\n"),
			out:  []byte("Which kind? [string]:2\n"),
			prior: data.State{
				models.Kind_USER: []*data.Record{
					&data.Record{
						Kind: models.Kind_USER,
						User: &models.User{
							Id: "1",
						},
					},
					&data.Record{
						Kind: models.Kind_USER,
						User: &models.User{
							Id: "2",
						},
					},
				},
				models.Kind_CREDENTIAL: []*data.Record{
					&data.Record{
						Kind: models.Kind_CREDENTIAL,
						Credential: &models.Credential{
							Id:      "3",
							Type:    models.Credential_PASSWORD,
							Public:  "pu",
							Private: "pr",
							OwnerId: "1",
						},
					},
					&data.Record{
						Kind: models.Kind_CREDENTIAL,
						Credential: &models.Credential{
							Id:      "4",
							Type:    models.Credential_PASSWORD,
							Public:  "2pu",
							Private: "pr",
							OwnerId: "2",
						},
					},
				},
				models.Kind_SESSION: []*data.Record{
					&data.Record{
						Kind: models.Kind_SESSION,
						Session: &models.Session{
							Id:           "5",
							AccessToken:  "non-empty",
							ExpiresAt:    models.TimestampFrom(time.Now().Add(5 * time.Minute)).WithoutNanos(),
							OwnerId:      "1",
							CredentialId: "3",
						},
					},
					&data.Record{
						Kind: models.Kind_SESSION,
						Session: &models.Session{
							Id:           "4",
							AccessToken:  "non-empty",
							ExpiresAt:    models.TimestampFrom(time.Now().Add(5 * time.Minute)).WithoutNanos(),
							OwnerId:      "1",
							CredentialId: "3",
						},
					},
					&data.Record{
						Kind: models.Kind_SESSION,
						Session: &models.Session{
							Id:           "4",
							AccessToken:  "non-empty",
							ExpiresAt:    models.TimestampFrom(time.Now().Add(5 * time.Minute)).WithoutNanos(),
							OwnerId:      "2",
							CredentialId: "4",
						},
					},
				},
			},
		},
		// }}}

		// TODO(nclandolfi) test query and changes

	}

	for n, c := range cases {
		t.Run(n, func(t *testing.T) {
			db := mem.NewDB()
			dbc, conn, err := data.DBBothLocal(db)
			if err != nil {
				t.Fatalf("data.DBBothLocal error: %v", err)
			}
			defer conn.Close()
			if err := data.Seed(context.Background(), dbc, c.prior); err != nil {
				t.Fatalf("data.Seed error: %v", err)
			}

			ui := &cli.MockUi{
				InputReader: bytes.NewBuffer(c.in),
			}
			cmd := &RecordsCommand{
				UI:       ui,
				UserID:   c.prior[models.Kind_USER][0].User.Id,
				DBClient: dbc,
			}

			if got, want := cmd.Run(c.args), c.code; got != want {
				t.Log(ui.ErrorWriter.String())
				t.Fatalf("cmd.Run(%v): got %d, want %d", c.args, got, want)
			}

			if got, want := ui.ErrorWriter.String(), string(c.err); got != want {
				t.Fatalf("ui.ErrorWriter.String(): got %q, want %q", got, want)
			}

			if got, want := ui.OutputWriter.String(), string(c.out); got != want {
				t.Fatalf("ui.OutputWriter.String(): got %q, want %q", got, want)
			}

			finalState := c.prior
			if c.posterior != nil {
				finalState = c.posterior
			}

			if got, want := data.CompareState(context.Background(), dbc, finalState), error(nil); got != want {
				t.Fatalf("data.CompareState: got %v, want %v", got, want)
			}
		})
	}
}
Exemple #6
0
// TestTodoFix tests the `fix` subcommand
func TestTodoFix(t *testing.T) {
	ui, db, user, c := newMockTodoCommand(t)

	// load a task into the db
	task := newTestTask(t, db, user)
	task.Name = "Take out the trash"
	task.DeadlineAt = models.TimestampFrom(time.Now().Add(-36 * time.Hour))
	if err := db.Save(task); err != nil {
		t.Fatal(err)
	}

	// load input
	input := strings.Join([]string{
		"2020", // year
		"1",    // month
		"1",    // day
		"12",   // hour
		"0",    // minute
	}, "\n")
	ui.InputReader = bytes.NewBufferString(input)

	t.Log("running: `elos todo fix`")
	code := c.Run([]string{"fix"})
	t.Log("command 'fix' terminated")

	errput := ui.ErrorWriter.String()
	output := ui.OutputWriter.String()
	t.Logf("Error output:\n %s", errput)
	t.Logf("Output:\n %s", output)

	// verify there were no errors
	if errput != "" {
		t.Fatalf("Expected no error output, got: %s", errput)
	}

	// verify success
	if code != success {
		t.Fatalf("Expected successful exit code along with empty error output.")
	}

	// verify some of the output
	if !strings.Contains(output, task.Name) {
		t.Fatalf("Output should have contained a the out of date task's name")
	}

	if !strings.Contains(output, "New Deadline") {
		t.Fatalf("Output should have asked for a new deadline")
	}

	t.Log("Checking that the task's deadline was changed")

	if err := db.PopulateByID(task); err != nil {
		t.Fatal(err)
	}

	t.Logf("Here's the task:\n%+v", task)

	if !task.DeadlineAt.Time().After(time.Now()) {
		t.Fatalf("Expected the task's deadline to be after now")
	}
}
Exemple #7
0
func TestCal(t *testing.T) {
	//TODO(nclandolfi): fix test
	t.Skip()
	NOW := time.Now()
	cases := map[string]struct {
		prior  data.State
		userID string
		args   []string
		input  io.Reader
		code   int
		errput string
		output string
		// IF posterior is nil, prior will be used
		posterior data.State
	}{
		"simple cal week": {
			prior: data.State{
				models.Kind_USER: []*data.Record{
					&data.Record{
						Kind: models.Kind_USER,
						User: &models.User{
							Id: "1",
						},
					},
				},
				models.Kind_CREDENTIAL: []*data.Record{
					&data.Record{
						Kind: models.Kind_CREDENTIAL,
						Credential: &models.Credential{
							Id:      "2",
							OwnerId: "1",
							Type:    models.Credential_PASSWORD,
							Public:  "pu",
							Private: "pr",
						},
					},
				},
				models.Kind_FIXTURE: []*data.Record{
					&data.Record{
						Kind: models.Kind_FIXTURE,
						Fixture: &models.Fixture{
							Id:        "3",
							OwnerId:   "1",
							StartTime: models.TimestampFrom(NOW.Add(1 * time.Hour)),
							EndTime:   models.TimestampFrom(NOW.Add(2 * time.Hour)),
						},
					},
				},
			},
			input:  new(bytes.Buffer),
			userID: "1",
			args:   []string{"week"},
		},
	}

	for n, c := range cases {
		t.Run(n, func(t *testing.T) {
			db := mem.NewDB()
			dbc, conn, err := data.DBBothLocal(db)
			if err != nil {
				t.Fatalf("data.DBBothLocal error: %v", err)
			}
			defer conn.Close()
			if err := data.Seed(context.Background(), dbc, c.prior); err != nil {
				t.Fatalf("data.Seed error: %v", err)
			}

			if c.input == nil {
				t.Fatal("c.input must be non-nil")
			}
			ui := &cli.MockUi{
				InputReader: c.input,
			}
			cmd := &CalCommand{
				UI:     ui,
				UserID: c.userID,
				DB:     data.DB(dbc),
			}

			if got, want := cmd.Run(c.args), c.code; got != want {
				t.Log(ui.ErrorWriter.String())
				t.Fatalf("cmd.Run(%v): got %d, want %d", c.args, got, want)
			}

			if got, want := ui.ErrorWriter.String(), c.errput; got != want {
				t.Fatalf("ui.ErrorWriter.String(): got %q, want %q", got, want)
			}

			if got, want := ui.OutputWriter.String(), c.output; got != want {
				t.Fatalf("ui.OutputWriter.String(): got %q, want %q", got, want)
			}

			finalState := c.prior
			if c.posterior != nil {
				finalState = c.posterior
			}

			if got, want := data.CompareState(context.Background(), dbc, finalState), error(nil); got != want {
				t.Fatalf("data.CompareState: got %v, want %v", got, want)
			}
		})
	}
}