pomo icon indicating copy to clipboard operation
pomo copied to clipboard

Delete multiple tasks using one command

Open strogiyotec opened this issue 4 years ago • 3 comments

Hey, it would be nice to have an ability to delete multiple tasks using one command. So instead of

pomo delete 1
pomo delete 2

We can use pomo delete 1 2 I already implemented it in my fork , will be glad to create pull request as soon as my first one will be approved

strogiyotec avatar Sep 05 '20 04:09 strogiyotec

Thank you @strogiyotec, happy to accept your PR, the first one is just about ready.

kevinschoon avatar Sep 06 '20 16:09 kevinschoon

@kevinschoon I will do a research how to test cli apps in golang (I have never done it before, only for Java based apps), for now the method that we are interested in (_delete) is tight to main and can't be tested without cli instance , so I would either write a mock for cli or write a test for main method but in this case I can't inject custom config . What do you think ?

strogiyotec avatar Sep 07 '20 00:09 strogiyotec

The tests for this library aren't really very robust so yeah I can see the challenge. Ideally we could create a mock driver but that might be too involved for testing some simple functionality. I would be fine accepting a PR with the change as long as we can verify it locally and then creating another PR to improve the test coverage.

In case it is useful I copied a mock SQL driver I wrote for another project below, there are probably better libraries around for this too.

// MockDriver implements a fake SQL driver for testing.
type MockDriver struct {
	t *testing.T
	// expected SQL query
	query string
	// results holds values that are
	// returned from a database query
	results struct {
		// column names for each row of values
		columns []string
		// each value for each row
		values [][]driver.Value
	}
	// args holds expected values
	args struct {
		// values we expect to be given
		// to the database
		values [][]driver.Value
	}
}

func (m MockDriver) Open(name string) (driver.Conn, error) {
	stmt := &MockStmt{
		t:      m.t,
		values: m.args.values,
		rows: &MockRows{
			t:       m.t,
			columns: m.results.columns,
			values:  m.results.values,
		},
	}
	return &MockConn{
		t:     m.t,
		stmt:  stmt,
		query: m.query,
	}, nil
}

type MockRows struct {
	t       *testing.T
	idx     int
	columns []string
	values  [][]driver.Value
}

func (m *MockRows) Next(dest []driver.Value) error {
	if m.idx == len(m.values) {
		return io.EOF
	}
	for i := 0; i < len(dest); i++ {
		dest[i] = m.values[m.idx][i]
	}
	m.idx++
	return nil
}

func (m MockRows) Close() error { return nil }

func (m MockRows) Columns() []string { return m.columns }

type MockTx struct{}

func (m MockTx) Commit() error { return nil }

func (m MockTx) Rollback() error { return nil }

type MockStmt struct {
	t      *testing.T
	rows   *MockRows
	idx    int
	values [][]driver.Value
}

func (s MockStmt) Close() error { return nil }

func (s MockStmt) NumInput() int {
	if len(s.values) > 0 {
		return len(s.values[0])
	}
	return 0
}

func (s *MockStmt) Exec(args []driver.Value) (driver.Result, error) {
	for i, arg := range args {
		if s.values[s.idx][i] != arg {
			s.t.Errorf("arg %t != %t", arg, s.values[s.idx][i])
		}
	}
	s.idx++
	return nil, nil
}

func (s MockStmt) Query(args []driver.Value) (driver.Rows, error) {
	return s.rows, nil
}

type MockConn struct {
	t     *testing.T
	query string
	stmt  *MockStmt
}

func (m MockConn) Prepare(query string) (driver.Stmt, error) {
	if query != m.query {
		m.t.Errorf("invalid query: %s != %s", query, m.query)
	}
	return m.stmt, nil
}

func (c MockConn) Close() error { return nil }
func (c MockConn) Begin() (driver.Tx, error) {
	return &MockTx{}, nil
}

var (
	_ driver.Conn = (*MockConn)(nil)
	_ driver.Rows = (*MockRows)(nil)
	_ driver.Tx   = (*MockTx)(nil)
	_ driver.Stmt = (*MockStmt)(nil)
	_ driver.Conn = (*MockConn)(nil)
)

kevinschoon avatar Sep 07 '20 20:09 kevinschoon