Renaming observations to characteristics
This commit is contained in:
parent
c1323f9c1f
commit
950b15a117
27 changed files with 889 additions and 889 deletions
92
api/characteristics.go
Normal file
92
api/characteristics.go
Normal file
|
@ -0,0 +1,92 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/thermokarst/bactdb/models"
|
||||
)
|
||||
|
||||
func serveCharacteristic(w http.ResponseWriter, r *http.Request) error {
|
||||
id, err := strconv.ParseInt(mux.Vars(r)["Id"], 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
characteristic, err := store.Characteristics.Get(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeJSON(w, characteristic)
|
||||
}
|
||||
|
||||
func serveCreateCharacteristic(w http.ResponseWriter, r *http.Request) error {
|
||||
var characteristic models.Characteristic
|
||||
err := json.NewDecoder(r.Body).Decode(&characteristic)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
created, err := store.Characteristics.Create(&characteristic)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if created {
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
}
|
||||
|
||||
return writeJSON(w, characteristic)
|
||||
}
|
||||
|
||||
func serveCharacteristicList(w http.ResponseWriter, r *http.Request) error {
|
||||
var opt models.CharacteristicListOptions
|
||||
if err := schemaDecoder.Decode(&opt, r.URL.Query()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
characteristics, err := store.Characteristics.List(&opt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if characteristics == nil {
|
||||
characteristics = []*models.Characteristic{}
|
||||
}
|
||||
|
||||
return writeJSON(w, characteristics)
|
||||
}
|
||||
|
||||
func serveUpdateCharacteristic(w http.ResponseWriter, r *http.Request) error {
|
||||
id, _ := strconv.ParseInt(mux.Vars(r)["Id"], 10, 0)
|
||||
var characteristic models.Characteristic
|
||||
err := json.NewDecoder(r.Body).Decode(&characteristic)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
updated, err := store.Characteristics.Update(id, &characteristic)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if updated {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
return writeJSON(w, characteristic)
|
||||
}
|
||||
|
||||
func serveDeleteCharacteristic(w http.ResponseWriter, r *http.Request) error {
|
||||
id, _ := strconv.ParseInt(mux.Vars(r)["Id"], 10, 0)
|
||||
|
||||
deleted, err := store.Characteristics.Delete(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if deleted {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
return writeJSON(w, &models.Characteristic{})
|
||||
}
|
153
api/characteristics_test.go
Normal file
153
api/characteristics_test.go
Normal file
|
@ -0,0 +1,153 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/thermokarst/bactdb/models"
|
||||
)
|
||||
|
||||
func newCharacteristic() *models.Characteristic {
|
||||
characteristic := models.NewCharacteristic()
|
||||
return characteristic
|
||||
}
|
||||
|
||||
func TestCharacteristic_Get(t *testing.T) {
|
||||
setup()
|
||||
|
||||
want := newCharacteristic()
|
||||
|
||||
calledGet := false
|
||||
|
||||
store.Characteristics.(*models.MockCharacteristicsService).Get_ = func(id int64) (*models.Characteristic, error) {
|
||||
if id != want.Id {
|
||||
t.Errorf("wanted request for characteristic %d but got %d", want.Id, id)
|
||||
}
|
||||
calledGet = true
|
||||
return want, nil
|
||||
}
|
||||
|
||||
got, err := apiClient.Characteristics.Get(want.Id)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !calledGet {
|
||||
t.Error("!calledGet")
|
||||
}
|
||||
if !normalizeDeepEqual(want, got) {
|
||||
t.Errorf("got %+v but wanted %+v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCharacteristic_Create(t *testing.T) {
|
||||
setup()
|
||||
|
||||
want := newCharacteristic()
|
||||
|
||||
calledPost := false
|
||||
store.Characteristics.(*models.MockCharacteristicsService).Create_ = func(characteristic *models.Characteristic) (bool, error) {
|
||||
if !normalizeDeepEqual(want, characteristic) {
|
||||
t.Errorf("wanted request for characteristic %d but got %d", want, characteristic)
|
||||
}
|
||||
calledPost = true
|
||||
return true, nil
|
||||
}
|
||||
|
||||
success, err := apiClient.Characteristics.Create(want)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !calledPost {
|
||||
t.Error("!calledPost")
|
||||
}
|
||||
if !success {
|
||||
t.Error("!success")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCharacteristic_List(t *testing.T) {
|
||||
setup()
|
||||
|
||||
want := []*models.Characteristic{newCharacteristic()}
|
||||
wantOpt := &models.CharacteristicListOptions{ListOptions: models.ListOptions{Page: 1, PerPage: 10}}
|
||||
|
||||
calledList := false
|
||||
store.Characteristics.(*models.MockCharacteristicsService).List_ = func(opt *models.CharacteristicListOptions) ([]*models.Characteristic, error) {
|
||||
if !normalizeDeepEqual(wantOpt, opt) {
|
||||
t.Errorf("wanted options %d but got %d", wantOpt, opt)
|
||||
}
|
||||
calledList = true
|
||||
return want, nil
|
||||
}
|
||||
|
||||
characteristics, err := apiClient.Characteristics.List(wantOpt)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !calledList {
|
||||
t.Error("!calledList")
|
||||
}
|
||||
|
||||
if !normalizeDeepEqual(&want, &characteristics) {
|
||||
t.Errorf("got characteristics %+v but wanted characteristics %+v", characteristics, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCharacteristic_Update(t *testing.T) {
|
||||
setup()
|
||||
|
||||
want := newCharacteristic()
|
||||
|
||||
calledPut := false
|
||||
store.Characteristics.(*models.MockCharacteristicsService).Update_ = func(id int64, characteristic *models.Characteristic) (bool, error) {
|
||||
if id != want.Id {
|
||||
t.Errorf("wanted request for characteristic %d but got %d", want.Id, id)
|
||||
}
|
||||
if !normalizeDeepEqual(want, characteristic) {
|
||||
t.Errorf("wanted request for characteristic %d but got %d", want, characteristic)
|
||||
}
|
||||
calledPut = true
|
||||
return true, nil
|
||||
}
|
||||
|
||||
success, err := apiClient.Characteristics.Update(want.Id, want)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !calledPut {
|
||||
t.Error("!calledPut")
|
||||
}
|
||||
if !success {
|
||||
t.Error("!success")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCharacteristic_Delete(t *testing.T) {
|
||||
setup()
|
||||
|
||||
want := newCharacteristic()
|
||||
|
||||
calledDelete := false
|
||||
store.Characteristics.(*models.MockCharacteristicsService).Delete_ = func(id int64) (bool, error) {
|
||||
if id != want.Id {
|
||||
t.Errorf("wanted request for characteristic %d but got %d", want.Id, id)
|
||||
}
|
||||
calledDelete = true
|
||||
return true, nil
|
||||
}
|
||||
|
||||
success, err := apiClient.Characteristics.Delete(want.Id)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !calledDelete {
|
||||
t.Error("!calledDelete")
|
||||
}
|
||||
if !success {
|
||||
t.Error("!success")
|
||||
}
|
||||
}
|
|
@ -45,11 +45,11 @@ func Handler() *mux.Router {
|
|||
m.Get(router.UpdateCharacteristicType).Handler(handler(serveUpdateCharacteristicType))
|
||||
m.Get(router.DeleteCharacteristicType).Handler(handler(serveDeleteCharacteristicType))
|
||||
|
||||
m.Get(router.Observation).Handler(handler(serveObservation))
|
||||
m.Get(router.CreateObservation).Handler(handler(serveCreateObservation))
|
||||
m.Get(router.Observations).Handler(handler(serveObservationList))
|
||||
m.Get(router.UpdateObservation).Handler(handler(serveUpdateObservation))
|
||||
m.Get(router.DeleteObservation).Handler(handler(serveDeleteObservation))
|
||||
m.Get(router.Characteristic).Handler(handler(serveCharacteristic))
|
||||
m.Get(router.CreateCharacteristic).Handler(handler(serveCreateCharacteristic))
|
||||
m.Get(router.Characteristics).Handler(handler(serveCharacteristicList))
|
||||
m.Get(router.UpdateCharacteristic).Handler(handler(serveUpdateCharacteristic))
|
||||
m.Get(router.DeleteCharacteristic).Handler(handler(serveDeleteCharacteristic))
|
||||
|
||||
m.Get(router.TextMeasurementType).Handler(handler(serveTextMeasurementType))
|
||||
m.Get(router.CreateTextMeasurementType).Handler(handler(serveCreateTextMeasurementType))
|
||||
|
|
|
@ -11,7 +11,7 @@ func newMeasurement() *models.Measurement {
|
|||
measurement := models.NewMeasurement()
|
||||
measurement.Id = 1
|
||||
measurement.StrainId = 2
|
||||
measurement.ObservationId = 3
|
||||
measurement.CharacteristicId = 3
|
||||
measurement.TextMeasurementTypeId = models.NullInt64{sql.NullInt64{Int64: 4, Valid: false}}
|
||||
measurement.UnitTypeId = models.NullInt64{sql.NullInt64{Int64: 5, Valid: true}}
|
||||
return measurement
|
||||
|
|
|
@ -1,92 +0,0 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/thermokarst/bactdb/models"
|
||||
)
|
||||
|
||||
func serveObservation(w http.ResponseWriter, r *http.Request) error {
|
||||
id, err := strconv.ParseInt(mux.Vars(r)["Id"], 10, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
observation, err := store.Observations.Get(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return writeJSON(w, observation)
|
||||
}
|
||||
|
||||
func serveCreateObservation(w http.ResponseWriter, r *http.Request) error {
|
||||
var observation models.Observation
|
||||
err := json.NewDecoder(r.Body).Decode(&observation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
created, err := store.Observations.Create(&observation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if created {
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
}
|
||||
|
||||
return writeJSON(w, observation)
|
||||
}
|
||||
|
||||
func serveObservationList(w http.ResponseWriter, r *http.Request) error {
|
||||
var opt models.ObservationListOptions
|
||||
if err := schemaDecoder.Decode(&opt, r.URL.Query()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
observations, err := store.Observations.List(&opt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if observations == nil {
|
||||
observations = []*models.Observation{}
|
||||
}
|
||||
|
||||
return writeJSON(w, observations)
|
||||
}
|
||||
|
||||
func serveUpdateObservation(w http.ResponseWriter, r *http.Request) error {
|
||||
id, _ := strconv.ParseInt(mux.Vars(r)["Id"], 10, 0)
|
||||
var observation models.Observation
|
||||
err := json.NewDecoder(r.Body).Decode(&observation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
updated, err := store.Observations.Update(id, &observation)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if updated {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
return writeJSON(w, observation)
|
||||
}
|
||||
|
||||
func serveDeleteObservation(w http.ResponseWriter, r *http.Request) error {
|
||||
id, _ := strconv.ParseInt(mux.Vars(r)["Id"], 10, 0)
|
||||
|
||||
deleted, err := store.Observations.Delete(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if deleted {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
return writeJSON(w, &models.Observation{})
|
||||
}
|
|
@ -1,153 +0,0 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/thermokarst/bactdb/models"
|
||||
)
|
||||
|
||||
func newObservation() *models.Observation {
|
||||
observation := models.NewObservation()
|
||||
return observation
|
||||
}
|
||||
|
||||
func TestObservation_Get(t *testing.T) {
|
||||
setup()
|
||||
|
||||
want := newObservation()
|
||||
|
||||
calledGet := false
|
||||
|
||||
store.Observations.(*models.MockObservationsService).Get_ = func(id int64) (*models.Observation, error) {
|
||||
if id != want.Id {
|
||||
t.Errorf("wanted request for observation %d but got %d", want.Id, id)
|
||||
}
|
||||
calledGet = true
|
||||
return want, nil
|
||||
}
|
||||
|
||||
got, err := apiClient.Observations.Get(want.Id)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !calledGet {
|
||||
t.Error("!calledGet")
|
||||
}
|
||||
if !normalizeDeepEqual(want, got) {
|
||||
t.Errorf("got %+v but wanted %+v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestObservation_Create(t *testing.T) {
|
||||
setup()
|
||||
|
||||
want := newObservation()
|
||||
|
||||
calledPost := false
|
||||
store.Observations.(*models.MockObservationsService).Create_ = func(observation *models.Observation) (bool, error) {
|
||||
if !normalizeDeepEqual(want, observation) {
|
||||
t.Errorf("wanted request for observation %d but got %d", want, observation)
|
||||
}
|
||||
calledPost = true
|
||||
return true, nil
|
||||
}
|
||||
|
||||
success, err := apiClient.Observations.Create(want)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !calledPost {
|
||||
t.Error("!calledPost")
|
||||
}
|
||||
if !success {
|
||||
t.Error("!success")
|
||||
}
|
||||
}
|
||||
|
||||
func TestObservation_List(t *testing.T) {
|
||||
setup()
|
||||
|
||||
want := []*models.Observation{newObservation()}
|
||||
wantOpt := &models.ObservationListOptions{ListOptions: models.ListOptions{Page: 1, PerPage: 10}}
|
||||
|
||||
calledList := false
|
||||
store.Observations.(*models.MockObservationsService).List_ = func(opt *models.ObservationListOptions) ([]*models.Observation, error) {
|
||||
if !normalizeDeepEqual(wantOpt, opt) {
|
||||
t.Errorf("wanted options %d but got %d", wantOpt, opt)
|
||||
}
|
||||
calledList = true
|
||||
return want, nil
|
||||
}
|
||||
|
||||
observations, err := apiClient.Observations.List(wantOpt)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !calledList {
|
||||
t.Error("!calledList")
|
||||
}
|
||||
|
||||
if !normalizeDeepEqual(&want, &observations) {
|
||||
t.Errorf("got observations %+v but wanted observations %+v", observations, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestObservation_Update(t *testing.T) {
|
||||
setup()
|
||||
|
||||
want := newObservation()
|
||||
|
||||
calledPut := false
|
||||
store.Observations.(*models.MockObservationsService).Update_ = func(id int64, observation *models.Observation) (bool, error) {
|
||||
if id != want.Id {
|
||||
t.Errorf("wanted request for observation %d but got %d", want.Id, id)
|
||||
}
|
||||
if !normalizeDeepEqual(want, observation) {
|
||||
t.Errorf("wanted request for observation %d but got %d", want, observation)
|
||||
}
|
||||
calledPut = true
|
||||
return true, nil
|
||||
}
|
||||
|
||||
success, err := apiClient.Observations.Update(want.Id, want)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !calledPut {
|
||||
t.Error("!calledPut")
|
||||
}
|
||||
if !success {
|
||||
t.Error("!success")
|
||||
}
|
||||
}
|
||||
|
||||
func TestObservation_Delete(t *testing.T) {
|
||||
setup()
|
||||
|
||||
want := newObservation()
|
||||
|
||||
calledDelete := false
|
||||
store.Observations.(*models.MockObservationsService).Delete_ = func(id int64) (bool, error) {
|
||||
if id != want.Id {
|
||||
t.Errorf("wanted request for observation %d but got %d", want.Id, id)
|
||||
}
|
||||
calledDelete = true
|
||||
return true, nil
|
||||
}
|
||||
|
||||
success, err := apiClient.Observations.Delete(want.Id)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !calledDelete {
|
||||
t.Error("!calledDelete")
|
||||
}
|
||||
if !success {
|
||||
t.Error("!success")
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@ func insertCharacteristicType(t *testing.T, tx *modl.Transaction) *models.Charac
|
|||
}
|
||||
|
||||
func newCharacteristicType(t *testing.T, tx *modl.Transaction) *models.CharacteristicType {
|
||||
return &models.CharacteristicType{CharacteristicTypeName: "Test Obs"}
|
||||
return &models.CharacteristicType{CharacteristicTypeName: "Test Char"}
|
||||
}
|
||||
|
||||
func TestCharacteristicTypesStore_Get_db(t *testing.T) {
|
||||
|
@ -95,7 +95,7 @@ func TestCharacteristicTypesStore_Update_db(t *testing.T) {
|
|||
d := NewDatastore(tx)
|
||||
|
||||
// Tweak it
|
||||
characteristic_type.CharacteristicTypeName = "Updated Obs Type"
|
||||
characteristic_type.CharacteristicTypeName = "Updated Char Type"
|
||||
updated, err := d.CharacteristicTypes.Update(characteristic_type.Id, characteristic_type)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
87
datastore/characteristics.go
Normal file
87
datastore/characteristics.go
Normal file
|
@ -0,0 +1,87 @@
|
|||
package datastore
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/thermokarst/bactdb/models"
|
||||
)
|
||||
|
||||
func init() {
|
||||
DB.AddTableWithName(models.Characteristic{}, "characteristics").SetKeys(true, "Id")
|
||||
}
|
||||
|
||||
type characteristicsStore struct {
|
||||
*Datastore
|
||||
}
|
||||
|
||||
func (s *characteristicsStore) Get(id int64) (*models.Characteristic, error) {
|
||||
var characteristic []*models.Characteristic
|
||||
if err := s.dbh.Select(&characteristic, `SELECT * FROM characteristics WHERE id=$1;`, id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(characteristic) == 0 {
|
||||
return nil, models.ErrCharacteristicNotFound
|
||||
}
|
||||
return characteristic[0], nil
|
||||
}
|
||||
|
||||
func (s *characteristicsStore) Create(characteristic *models.Characteristic) (bool, error) {
|
||||
currentTime := time.Now()
|
||||
characteristic.CreatedAt = currentTime
|
||||
characteristic.UpdatedAt = currentTime
|
||||
if err := s.dbh.Insert(characteristic); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (s *characteristicsStore) List(opt *models.CharacteristicListOptions) ([]*models.Characteristic, error) {
|
||||
if opt == nil {
|
||||
opt = &models.CharacteristicListOptions{}
|
||||
}
|
||||
var characteristics []*models.Characteristic
|
||||
err := s.dbh.Select(&characteristics, `SELECT * FROM characteristics LIMIT $1 OFFSET $2;`, opt.PerPageOrDefault(), opt.Offset())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return characteristics, nil
|
||||
}
|
||||
|
||||
func (s *characteristicsStore) Update(id int64, characteristic *models.Characteristic) (bool, error) {
|
||||
_, err := s.Get(id)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if id != characteristic.Id {
|
||||
return false, models.ErrCharacteristicNotFound
|
||||
}
|
||||
|
||||
characteristic.UpdatedAt = time.Now()
|
||||
changed, err := s.dbh.Update(characteristic)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if changed == 0 {
|
||||
return false, ErrNoRowsUpdated
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (s *characteristicsStore) Delete(id int64) (bool, error) {
|
||||
characteristic, err := s.Get(id)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
deleted, err := s.dbh.Delete(characteristic)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if deleted == 0 {
|
||||
return false, ErrNoRowsDeleted
|
||||
}
|
||||
return true, nil
|
||||
}
|
129
datastore/characteristics_test.go
Normal file
129
datastore/characteristics_test.go
Normal file
|
@ -0,0 +1,129 @@
|
|||
package datastore
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jmoiron/modl"
|
||||
"github.com/thermokarst/bactdb/models"
|
||||
)
|
||||
|
||||
func insertCharacteristic(t *testing.T, tx *modl.Transaction) *models.Characteristic {
|
||||
// clean up our target table
|
||||
tx.Exec(`DELETE FROM characteristics;`)
|
||||
characteristic := newCharacteristic(t, tx)
|
||||
if err := tx.Insert(characteristic); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return characteristic
|
||||
}
|
||||
|
||||
func newCharacteristic(t *testing.T, tx *modl.Transaction) *models.Characteristic {
|
||||
// we want to create and insert an characteristic type record, too.
|
||||
characteristic_type := insertCharacteristicType(t, tx)
|
||||
return &models.Characteristic{CharacteristicName: "Test Characteristic",
|
||||
CharacteristicTypeId: characteristic_type.Id}
|
||||
}
|
||||
|
||||
func TestCharacteristicsStore_Get_db(t *testing.T) {
|
||||
tx, _ := DB.Begin()
|
||||
defer tx.Rollback()
|
||||
|
||||
want := insertCharacteristic(t, tx)
|
||||
|
||||
d := NewDatastore(tx)
|
||||
|
||||
characteristic, err := d.Characteristics.Get(want.Id)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
normalizeTime(&want.CreatedAt, &want.UpdatedAt, &want.DeletedAt)
|
||||
normalizeTime(&characteristic.CreatedAt, &characteristic.UpdatedAt, &characteristic.DeletedAt)
|
||||
|
||||
if !reflect.DeepEqual(characteristic, want) {
|
||||
t.Errorf("got characteristic %+v, want %+v", characteristic, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCharacteristicsStore_Create_db(t *testing.T) {
|
||||
tx, _ := DB.Begin()
|
||||
defer tx.Rollback()
|
||||
|
||||
characteristic := newCharacteristic(t, tx)
|
||||
|
||||
d := NewDatastore(tx)
|
||||
|
||||
created, err := d.Characteristics.Create(characteristic)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !created {
|
||||
t.Error("!created")
|
||||
}
|
||||
if characteristic.Id == 0 {
|
||||
t.Error("want nonzero characteristic.Id after submitting")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCharacteristicsStore_List_db(t *testing.T) {
|
||||
tx, _ := DB.Begin()
|
||||
defer tx.Rollback()
|
||||
|
||||
want_characteristic := insertCharacteristic(t, tx)
|
||||
want := []*models.Characteristic{want_characteristic}
|
||||
|
||||
d := NewDatastore(tx)
|
||||
|
||||
characteristics, err := d.Characteristics.List(&models.CharacteristicListOptions{ListOptions: models.ListOptions{Page: 1, PerPage: 10}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i := range want {
|
||||
normalizeTime(&want[i].CreatedAt, &want[i].UpdatedAt, &want[i].DeletedAt)
|
||||
normalizeTime(&characteristics[i].CreatedAt, &characteristics[i].UpdatedAt, &characteristics[i].DeletedAt)
|
||||
}
|
||||
if !reflect.DeepEqual(characteristics, want) {
|
||||
t.Errorf("got characteristics %+v, want %+v", characteristics, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCharacteristicsStore_Update_db(t *testing.T) {
|
||||
tx, _ := DB.Begin()
|
||||
defer tx.Rollback()
|
||||
|
||||
characteristic := insertCharacteristic(t, tx)
|
||||
|
||||
d := NewDatastore(tx)
|
||||
|
||||
// Tweak it
|
||||
characteristic.CharacteristicName = "Updated Char"
|
||||
updated, err := d.Characteristics.Update(characteristic.Id, characteristic)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !updated {
|
||||
t.Error("!updated")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCharacteristicsStore_Delete_db(t *testing.T) {
|
||||
tx, _ := DB.Begin()
|
||||
defer tx.Rollback()
|
||||
|
||||
characteristic := insertCharacteristic(t, tx)
|
||||
|
||||
d := NewDatastore(tx)
|
||||
|
||||
// Delete it
|
||||
deleted, err := d.Characteristics.Delete(characteristic.Id)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !deleted {
|
||||
t.Error("!delete")
|
||||
}
|
||||
}
|
|
@ -13,8 +13,8 @@ type Datastore struct {
|
|||
Genera models.GeneraService
|
||||
Species models.SpeciesService
|
||||
Strains models.StrainsService
|
||||
CharacteristicTypes models.CharacteristicTypesService
|
||||
Observations models.ObservationsService
|
||||
CharacteristicTypes models.CharacteristicTypesService
|
||||
Characteristics models.CharacteristicsService
|
||||
TextMeasurementTypes models.TextMeasurementTypesService
|
||||
UnitTypes models.UnitTypesService
|
||||
Measurements models.MeasurementsService
|
||||
|
@ -39,7 +39,7 @@ func NewDatastore(dbh modl.SqlExecutor) *Datastore {
|
|||
d.Species = &speciesStore{d}
|
||||
d.Strains = &strainsStore{d}
|
||||
d.CharacteristicTypes = &characteristicTypesStore{d}
|
||||
d.Observations = &observationsStore{d}
|
||||
d.Characteristics = &characteristicsStore{d}
|
||||
d.TextMeasurementTypes = &textMeasurementTypesStore{d}
|
||||
d.UnitTypes = &unitTypesStore{d}
|
||||
d.Measurements = &measurementsStore{d}
|
||||
|
@ -52,8 +52,8 @@ func NewMockDatastore() *Datastore {
|
|||
Genera: &models.MockGeneraService{},
|
||||
Species: &models.MockSpeciesService{},
|
||||
Strains: &models.MockStrainsService{},
|
||||
CharacteristicTypes: &models.MockCharacteristicTypesService{},
|
||||
Observations: &models.MockObservationsService{},
|
||||
CharacteristicTypes: &models.MockCharacteristicTypesService{},
|
||||
Characteristics: &models.MockCharacteristicsService{},
|
||||
TextMeasurementTypes: &models.MockTextMeasurementTypesService{},
|
||||
UnitTypes: &models.MockUnitTypesService{},
|
||||
Measurements: &models.MockMeasurementsService{},
|
||||
|
|
|
@ -22,16 +22,16 @@ func insertMeasurement(t *testing.T, tx *modl.Transaction) *models.Measurement {
|
|||
func newMeasurement(t *testing.T, tx *modl.Transaction) *models.Measurement {
|
||||
// we have a few things to take care of first...
|
||||
strain := insertStrain(t, tx)
|
||||
observation := insertObservation(t, tx)
|
||||
characteristic := insertCharacteristic(t, tx)
|
||||
|
||||
// we want to create and insert a unit type record, too.
|
||||
unit_type := insertUnitType(t, tx)
|
||||
|
||||
return &models.Measurement{
|
||||
StrainId: strain.Id,
|
||||
ObservationId: observation.Id,
|
||||
NumValue: models.NullFloat64{sql.NullFloat64{Float64: 1.23, Valid: true}},
|
||||
UnitTypeId: models.NullInt64{sql.NullInt64{Int64: unit_type.Id, Valid: true}},
|
||||
StrainId: strain.Id,
|
||||
CharacteristicId: characteristic.Id,
|
||||
NumValue: models.NullFloat64{sql.NullFloat64{Float64: 1.23, Valid: true}},
|
||||
UnitTypeId: models.NullInt64{sql.NullInt64{Int64: unit_type.Id, Valid: true}},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
-- bactdb
|
||||
-- Matthew R Dillon
|
||||
|
||||
DROP TABLE observations;
|
||||
DROP TABLE characteristics;
|
||||
|
|
@ -1,18 +1,18 @@
|
|||
-- bactdb
|
||||
-- Matthew R Dillon
|
||||
|
||||
CREATE TABLE observations (
|
||||
CREATE TABLE characteristics (
|
||||
id BIGSERIAL NOT NULL,
|
||||
observation_name CHARACTER VARYING(100) NOT NULL,
|
||||
characteristic_name CHARACTER VARYING(100) NOT NULL,
|
||||
characteristic_type_id BIGINT NOT NULL,
|
||||
|
||||
created_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
updated_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
deleted_at TIMESTAMP WITH TIME ZONE NULL,
|
||||
|
||||
CONSTRAINT observations_pkey PRIMARY KEY (id),
|
||||
CONSTRAINT characteristics_pkey PRIMARY KEY (id),
|
||||
FOREIGN KEY (characteristic_type_id) REFERENCES characteristic_types(id)
|
||||
);
|
||||
|
||||
CREATE INDEX characteristic_type_id_idx ON observations (characteristic_type_id);
|
||||
CREATE INDEX characteristic_type_id_idx ON characteristics (characteristic_type_id);
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
CREATE TABLE measurements (
|
||||
id BIGSERIAL NOT NULL,
|
||||
strain_id BIGINT NOT NULL,
|
||||
observation_id BIGINT NOT NULL,
|
||||
characteristic_id BIGINT NOT NULL,
|
||||
text_measurement_type_id BIGINT NULL,
|
||||
txt_value CHARACTER VARYING(255) NULL,
|
||||
num_value NUMERIC(8, 3) NULL,
|
||||
|
@ -16,9 +16,9 @@ CREATE TABLE measurements (
|
|||
created_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
updated_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
|
||||
CONSTRAINT strainsobsmeasurements_pkey PRIMARY KEY (id),
|
||||
CONSTRAINT strainscharmeasurements_pkey PRIMARY KEY (id),
|
||||
FOREIGN KEY (strain_id) REFERENCES strains(id),
|
||||
FOREIGN KEY (observation_id) REFERENCES observations(id),
|
||||
FOREIGN KEY (characteristic_id) REFERENCES characteristics(id),
|
||||
FOREIGN KEY (text_measurement_type_id) REFERENCES text_measurement_types(id),
|
||||
FOREIGN KEY (unit_type_id) REFERENCES unit_types(id),
|
||||
FOREIGN KEY (test_method_id) REFERENCES test_methods(id),
|
||||
|
@ -42,7 +42,7 @@ CREATE TABLE measurements (
|
|||
|
||||
CREATE INDEX strain_id_idx ON measurements (strain_id);
|
||||
|
||||
CREATE INDEX observation_id_idx ON measurements (observation_id);
|
||||
CREATE INDEX characteristic_id_idx ON measurements (characteristic_id);
|
||||
|
||||
CREATE INDEX text_measurement_type_id_idx ON measurements (text_measurement_type_id);
|
||||
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
package datastore
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/thermokarst/bactdb/models"
|
||||
)
|
||||
|
||||
func init() {
|
||||
DB.AddTableWithName(models.Observation{}, "observations").SetKeys(true, "Id")
|
||||
}
|
||||
|
||||
type observationsStore struct {
|
||||
*Datastore
|
||||
}
|
||||
|
||||
func (s *observationsStore) Get(id int64) (*models.Observation, error) {
|
||||
var observation []*models.Observation
|
||||
if err := s.dbh.Select(&observation, `SELECT * FROM observations WHERE id=$1;`, id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(observation) == 0 {
|
||||
return nil, models.ErrObservationNotFound
|
||||
}
|
||||
return observation[0], nil
|
||||
}
|
||||
|
||||
func (s *observationsStore) Create(observation *models.Observation) (bool, error) {
|
||||
currentTime := time.Now()
|
||||
observation.CreatedAt = currentTime
|
||||
observation.UpdatedAt = currentTime
|
||||
if err := s.dbh.Insert(observation); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (s *observationsStore) List(opt *models.ObservationListOptions) ([]*models.Observation, error) {
|
||||
if opt == nil {
|
||||
opt = &models.ObservationListOptions{}
|
||||
}
|
||||
var observations []*models.Observation
|
||||
err := s.dbh.Select(&observations, `SELECT * FROM observations LIMIT $1 OFFSET $2;`, opt.PerPageOrDefault(), opt.Offset())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return observations, nil
|
||||
}
|
||||
|
||||
func (s *observationsStore) Update(id int64, observation *models.Observation) (bool, error) {
|
||||
_, err := s.Get(id)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if id != observation.Id {
|
||||
return false, models.ErrObservationNotFound
|
||||
}
|
||||
|
||||
observation.UpdatedAt = time.Now()
|
||||
changed, err := s.dbh.Update(observation)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if changed == 0 {
|
||||
return false, ErrNoRowsUpdated
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (s *observationsStore) Delete(id int64) (bool, error) {
|
||||
observation, err := s.Get(id)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
deleted, err := s.dbh.Delete(observation)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if deleted == 0 {
|
||||
return false, ErrNoRowsDeleted
|
||||
}
|
||||
return true, nil
|
||||
}
|
|
@ -1,129 +0,0 @@
|
|||
package datastore
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jmoiron/modl"
|
||||
"github.com/thermokarst/bactdb/models"
|
||||
)
|
||||
|
||||
func insertObservation(t *testing.T, tx *modl.Transaction) *models.Observation {
|
||||
// clean up our target table
|
||||
tx.Exec(`DELETE FROM observations;`)
|
||||
observation := newObservation(t, tx)
|
||||
if err := tx.Insert(observation); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return observation
|
||||
}
|
||||
|
||||
func newObservation(t *testing.T, tx *modl.Transaction) *models.Observation {
|
||||
// we want to create and insert an characteristic type record, too.
|
||||
characteristic_type := insertCharacteristicType(t, tx)
|
||||
return &models.Observation{ObservationName: "Test Observation",
|
||||
CharacteristicTypeId: characteristic_type.Id}
|
||||
}
|
||||
|
||||
func TestObservationsStore_Get_db(t *testing.T) {
|
||||
tx, _ := DB.Begin()
|
||||
defer tx.Rollback()
|
||||
|
||||
want := insertObservation(t, tx)
|
||||
|
||||
d := NewDatastore(tx)
|
||||
|
||||
observation, err := d.Observations.Get(want.Id)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
normalizeTime(&want.CreatedAt, &want.UpdatedAt, &want.DeletedAt)
|
||||
normalizeTime(&observation.CreatedAt, &observation.UpdatedAt, &observation.DeletedAt)
|
||||
|
||||
if !reflect.DeepEqual(observation, want) {
|
||||
t.Errorf("got observation %+v, want %+v", observation, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestObservationsStore_Create_db(t *testing.T) {
|
||||
tx, _ := DB.Begin()
|
||||
defer tx.Rollback()
|
||||
|
||||
observation := newObservation(t, tx)
|
||||
|
||||
d := NewDatastore(tx)
|
||||
|
||||
created, err := d.Observations.Create(observation)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !created {
|
||||
t.Error("!created")
|
||||
}
|
||||
if observation.Id == 0 {
|
||||
t.Error("want nonzero observation.Id after submitting")
|
||||
}
|
||||
}
|
||||
|
||||
func TestObservationsStore_List_db(t *testing.T) {
|
||||
tx, _ := DB.Begin()
|
||||
defer tx.Rollback()
|
||||
|
||||
want_observation := insertObservation(t, tx)
|
||||
want := []*models.Observation{want_observation}
|
||||
|
||||
d := NewDatastore(tx)
|
||||
|
||||
observations, err := d.Observations.List(&models.ObservationListOptions{ListOptions: models.ListOptions{Page: 1, PerPage: 10}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for i := range want {
|
||||
normalizeTime(&want[i].CreatedAt, &want[i].UpdatedAt, &want[i].DeletedAt)
|
||||
normalizeTime(&observations[i].CreatedAt, &observations[i].UpdatedAt, &observations[i].DeletedAt)
|
||||
}
|
||||
if !reflect.DeepEqual(observations, want) {
|
||||
t.Errorf("got observations %+v, want %+v", observations, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestObservationsStore_Update_db(t *testing.T) {
|
||||
tx, _ := DB.Begin()
|
||||
defer tx.Rollback()
|
||||
|
||||
observation := insertObservation(t, tx)
|
||||
|
||||
d := NewDatastore(tx)
|
||||
|
||||
// Tweak it
|
||||
observation.ObservationName = "Updated Obs"
|
||||
updated, err := d.Observations.Update(observation.Id, observation)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !updated {
|
||||
t.Error("!updated")
|
||||
}
|
||||
}
|
||||
|
||||
func TestObservationsStore_Delete_db(t *testing.T) {
|
||||
tx, _ := DB.Begin()
|
||||
defer tx.Rollback()
|
||||
|
||||
observation := insertObservation(t, tx)
|
||||
|
||||
d := NewDatastore(tx)
|
||||
|
||||
// Delete it
|
||||
deleted, err := d.Observations.Delete(observation.Id)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !deleted {
|
||||
t.Error("!delete")
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ type CharacteristicType struct {
|
|||
|
||||
func NewCharacteristicType() *CharacteristicType {
|
||||
return &CharacteristicType{
|
||||
CharacteristicTypeName: "Test Obs Type",
|
||||
CharacteristicTypeName: "Test Char Type",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ func TestCharacteristicTypeService_Create(t *testing.T) {
|
|||
mux.HandleFunc(urlPath(t, router.CreateCharacteristicType, nil), func(w http.ResponseWriter, r *http.Request) {
|
||||
called = true
|
||||
testMethod(t, r, "POST")
|
||||
testBody(t, r, `{"id":1,"characteristicTypeName":"Test Obs Type","createdAt":"0001-01-01T00:00:00Z","updatedAt":"0001-01-01T00:00:00Z","deletedAt":null}`+"\n")
|
||||
testBody(t, r, `{"id":1,"characteristicTypeName":"Test Char Type","createdAt":"0001-01-01T00:00:00Z","updatedAt":"0001-01-01T00:00:00Z","deletedAt":null}`+"\n")
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
writeJSON(w, want)
|
||||
|
@ -123,13 +123,13 @@ func TestCharacteristicTypeService_Update(t *testing.T) {
|
|||
mux.HandleFunc(urlPath(t, router.UpdateCharacteristicType, map[string]string{"Id": "1"}), func(w http.ResponseWriter, r *http.Request) {
|
||||
called = true
|
||||
testMethod(t, r, "PUT")
|
||||
testBody(t, r, `{"id":1,"characteristicTypeName":"Test Obs Type Updated","createdAt":"0001-01-01T00:00:00Z","updatedAt":"0001-01-01T00:00:00Z","deletedAt":null}`+"\n")
|
||||
testBody(t, r, `{"id":1,"characteristicTypeName":"Test Char Type Updated","createdAt":"0001-01-01T00:00:00Z","updatedAt":"0001-01-01T00:00:00Z","deletedAt":null}`+"\n")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
writeJSON(w, want)
|
||||
})
|
||||
|
||||
characteristic_type := newCharacteristicType()
|
||||
characteristic_type.CharacteristicTypeName = "Test Obs Type Updated"
|
||||
characteristic_type.CharacteristicTypeName = "Test Char Type Updated"
|
||||
updated, err := client.CharacteristicTypes.Update(characteristic_type.Id, characteristic_type)
|
||||
if err != nil {
|
||||
t.Errorf("CharacteristicTypes.Update returned error: %v", err)
|
||||
|
|
204
models/characteristics.go
Normal file
204
models/characteristics.go
Normal file
|
@ -0,0 +1,204 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/thermokarst/bactdb/router"
|
||||
)
|
||||
|
||||
// A Characteristic is a lookup type
|
||||
type Characteristic struct {
|
||||
Id int64 `json:"id,omitempty"`
|
||||
CharacteristicName string `db:"characteristic_name" json:"characteristicName"`
|
||||
CharacteristicTypeId int64 `db:"characteristic_type_id" json:"characteristicTypeId"`
|
||||
CreatedAt time.Time `db:"created_at" json:"createdAt"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updatedAt"`
|
||||
DeletedAt NullTime `db:"deleted_at" json:"deletedAt"`
|
||||
}
|
||||
|
||||
func NewCharacteristic() *Characteristic {
|
||||
return &Characteristic{
|
||||
CharacteristicName: "Test Characteristic",
|
||||
}
|
||||
}
|
||||
|
||||
type CharacteristicsService interface {
|
||||
// Get an characteristic
|
||||
Get(id int64) (*Characteristic, error)
|
||||
|
||||
// List all characteristics
|
||||
List(opt *CharacteristicListOptions) ([]*Characteristic, error)
|
||||
|
||||
// Create an characteristic
|
||||
Create(characteristic *Characteristic) (bool, error)
|
||||
|
||||
// Update an characteristic
|
||||
Update(id int64, Characteristic *Characteristic) (updated bool, err error)
|
||||
|
||||
// Delete an characteristic
|
||||
Delete(id int64) (deleted bool, err error)
|
||||
}
|
||||
|
||||
var (
|
||||
ErrCharacteristicNotFound = errors.New("characteristic not found")
|
||||
)
|
||||
|
||||
type characteristicsService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
func (s *characteristicsService) Get(id int64) (*Characteristic, error) {
|
||||
strId := strconv.FormatInt(id, 10)
|
||||
|
||||
url, err := s.client.url(router.Characteristic, map[string]string{"Id": strId}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequest("GET", url.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var characteristic *Characteristic
|
||||
_, err = s.client.Do(req, &characteristic)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return characteristic, nil
|
||||
}
|
||||
|
||||
func (s *characteristicsService) Create(characteristic *Characteristic) (bool, error) {
|
||||
url, err := s.client.url(router.CreateCharacteristic, nil, nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequest("POST", url.String(), characteristic)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, &characteristic)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return resp.StatusCode == http.StatusCreated, nil
|
||||
}
|
||||
|
||||
type CharacteristicListOptions struct {
|
||||
ListOptions
|
||||
}
|
||||
|
||||
func (s *characteristicsService) List(opt *CharacteristicListOptions) ([]*Characteristic, error) {
|
||||
url, err := s.client.url(router.Characteristics, nil, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequest("GET", url.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var characteristics []*Characteristic
|
||||
_, err = s.client.Do(req, &characteristics)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return characteristics, nil
|
||||
}
|
||||
|
||||
func (s *characteristicsService) Update(id int64, characteristic *Characteristic) (bool, error) {
|
||||
strId := strconv.FormatInt(id, 10)
|
||||
|
||||
url, err := s.client.url(router.UpdateCharacteristic, map[string]string{"Id": strId}, nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequest("PUT", url.String(), characteristic)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, &characteristic)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return resp.StatusCode == http.StatusOK, nil
|
||||
}
|
||||
|
||||
func (s *characteristicsService) Delete(id int64) (bool, error) {
|
||||
strId := strconv.FormatInt(id, 10)
|
||||
|
||||
url, err := s.client.url(router.DeleteCharacteristic, map[string]string{"Id": strId}, nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequest("DELETE", url.String(), nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var characteristic *Characteristic
|
||||
resp, err := s.client.Do(req, &characteristic)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return resp.StatusCode == http.StatusOK, nil
|
||||
}
|
||||
|
||||
type MockCharacteristicsService struct {
|
||||
Get_ func(id int64) (*Characteristic, error)
|
||||
List_ func(opt *CharacteristicListOptions) ([]*Characteristic, error)
|
||||
Create_ func(characteristic *Characteristic) (bool, error)
|
||||
Update_ func(id int64, characteristic *Characteristic) (bool, error)
|
||||
Delete_ func(id int64) (bool, error)
|
||||
}
|
||||
|
||||
var _ CharacteristicsService = &MockCharacteristicsService{}
|
||||
|
||||
func (s *MockCharacteristicsService) Get(id int64) (*Characteristic, error) {
|
||||
if s.Get_ == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return s.Get_(id)
|
||||
}
|
||||
|
||||
func (s *MockCharacteristicsService) Create(characteristic *Characteristic) (bool, error) {
|
||||
if s.Create_ == nil {
|
||||
return false, nil
|
||||
}
|
||||
return s.Create_(characteristic)
|
||||
}
|
||||
|
||||
func (s *MockCharacteristicsService) List(opt *CharacteristicListOptions) ([]*Characteristic, error) {
|
||||
if s.List_ == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return s.List_(opt)
|
||||
}
|
||||
|
||||
func (s *MockCharacteristicsService) Update(id int64, characteristic *Characteristic) (bool, error) {
|
||||
if s.Update_ == nil {
|
||||
return false, nil
|
||||
}
|
||||
return s.Update_(id, characteristic)
|
||||
}
|
||||
|
||||
func (s *MockCharacteristicsService) Delete(id int64) (bool, error) {
|
||||
if s.Delete_ == nil {
|
||||
return false, nil
|
||||
}
|
||||
return s.Delete_(id)
|
||||
}
|
174
models/characteristics_test.go
Normal file
174
models/characteristics_test.go
Normal file
|
@ -0,0 +1,174 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/thermokarst/bactdb/router"
|
||||
)
|
||||
|
||||
func newCharacteristic() *Characteristic {
|
||||
characteristic := NewCharacteristic()
|
||||
characteristic.Id = 1
|
||||
return characteristic
|
||||
}
|
||||
|
||||
func TestCharacteristicService_Get(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
want := newCharacteristic()
|
||||
|
||||
var called bool
|
||||
mux.HandleFunc(urlPath(t, router.Characteristic, map[string]string{"Id": "1"}), func(w http.ResponseWriter, r *http.Request) {
|
||||
called = true
|
||||
testMethod(t, r, "GET")
|
||||
|
||||
writeJSON(w, want)
|
||||
})
|
||||
|
||||
characteristic, err := client.Characteristics.Get(want.Id)
|
||||
if err != nil {
|
||||
t.Errorf("Characteristics.Get returned error: %v", err)
|
||||
}
|
||||
|
||||
if !called {
|
||||
t.Fatal("!called")
|
||||
}
|
||||
|
||||
normalizeTime(&want.CreatedAt, &want.UpdatedAt, &want.DeletedAt)
|
||||
|
||||
if !reflect.DeepEqual(characteristic, want) {
|
||||
t.Errorf("Characteristics.Get return %+v, want %+v", characteristic, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCharacteristicService_Create(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
want := newCharacteristic()
|
||||
|
||||
var called bool
|
||||
mux.HandleFunc(urlPath(t, router.CreateCharacteristic, nil), func(w http.ResponseWriter, r *http.Request) {
|
||||
called = true
|
||||
testMethod(t, r, "POST")
|
||||
testBody(t, r, `{"id":1,"characteristicName":"Test Characteristic","characteristicTypeId":0,"createdAt":"0001-01-01T00:00:00Z","updatedAt":"0001-01-01T00:00:00Z","deletedAt":null}`+"\n")
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
writeJSON(w, want)
|
||||
})
|
||||
|
||||
characteristic := newCharacteristic()
|
||||
created, err := client.Characteristics.Create(characteristic)
|
||||
if err != nil {
|
||||
t.Errorf("Characteristics.Create returned error: %v", err)
|
||||
}
|
||||
|
||||
if !created {
|
||||
t.Error("!created")
|
||||
}
|
||||
|
||||
if !called {
|
||||
t.Fatal("!called")
|
||||
}
|
||||
|
||||
normalizeTime(&want.CreatedAt, &want.UpdatedAt, &want.DeletedAt)
|
||||
if !reflect.DeepEqual(characteristic, want) {
|
||||
t.Errorf("Characteristics.Create returned %+v, want %+v", characteristic, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCharacteristicService_List(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
want := []*Characteristic{newCharacteristic()}
|
||||
|
||||
var called bool
|
||||
mux.HandleFunc(urlPath(t, router.Characteristics, nil), func(w http.ResponseWriter, r *http.Request) {
|
||||
called = true
|
||||
testMethod(t, r, "GET")
|
||||
testFormValues(t, r, values{})
|
||||
|
||||
writeJSON(w, want)
|
||||
})
|
||||
|
||||
characteristics, err := client.Characteristics.List(nil)
|
||||
if err != nil {
|
||||
t.Errorf("Characteristics.List returned error: %v", err)
|
||||
}
|
||||
|
||||
if !called {
|
||||
t.Fatal("!called")
|
||||
}
|
||||
|
||||
for _, u := range want {
|
||||
normalizeTime(&u.CreatedAt, &u.UpdatedAt, &u.DeletedAt)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(characteristics, want) {
|
||||
t.Errorf("Characteristics.List return %+v, want %+v", characteristics, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCharacteristicService_Update(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
want := newCharacteristic()
|
||||
|
||||
var called bool
|
||||
mux.HandleFunc(urlPath(t, router.UpdateCharacteristic, map[string]string{"Id": "1"}), func(w http.ResponseWriter, r *http.Request) {
|
||||
called = true
|
||||
testMethod(t, r, "PUT")
|
||||
testBody(t, r, `{"id":1,"characteristicName":"Test Char Updated","characteristicTypeId":0,"createdAt":"0001-01-01T00:00:00Z","updatedAt":"0001-01-01T00:00:00Z","deletedAt":null}`+"\n")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
writeJSON(w, want)
|
||||
})
|
||||
|
||||
characteristic := newCharacteristic()
|
||||
characteristic.CharacteristicName = "Test Char Updated"
|
||||
updated, err := client.Characteristics.Update(characteristic.Id, characteristic)
|
||||
if err != nil {
|
||||
t.Errorf("Characteristics.Update returned error: %v", err)
|
||||
}
|
||||
|
||||
if !updated {
|
||||
t.Error("!updated")
|
||||
}
|
||||
|
||||
if !called {
|
||||
t.Fatal("!called")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCharacteristicService_Delete(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
want := newCharacteristic()
|
||||
|
||||
var called bool
|
||||
mux.HandleFunc(urlPath(t, router.DeleteCharacteristic, map[string]string{"Id": "1"}), func(w http.ResponseWriter, r *http.Request) {
|
||||
called = true
|
||||
testMethod(t, r, "DELETE")
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
writeJSON(w, want)
|
||||
})
|
||||
|
||||
deleted, err := client.Characteristics.Delete(want.Id)
|
||||
if err != nil {
|
||||
t.Errorf("Characteristics.Delete returned error: %v", err)
|
||||
}
|
||||
|
||||
if !deleted {
|
||||
t.Error("!deleted")
|
||||
}
|
||||
|
||||
if !called {
|
||||
t.Fatal("!called")
|
||||
}
|
||||
}
|
|
@ -20,8 +20,8 @@ type Client struct {
|
|||
Genera GeneraService
|
||||
Species SpeciesService
|
||||
Strains StrainsService
|
||||
CharacteristicTypes CharacteristicTypesService
|
||||
Observations ObservationsService
|
||||
CharacteristicTypes CharacteristicTypesService
|
||||
Characteristics CharacteristicsService
|
||||
TextMeasurementTypes TextMeasurementTypesService
|
||||
UnitTypes UnitTypesService
|
||||
Measurements MeasurementsService
|
||||
|
@ -57,7 +57,7 @@ func NewClient(httpClient *http.Client) *Client {
|
|||
c.Species = &speciesService{c}
|
||||
c.Strains = &strainsService{c}
|
||||
c.CharacteristicTypes = &characteristicTypesService{c}
|
||||
c.Observations = &observationsService{c}
|
||||
c.Characteristics = &characteristicsService{c}
|
||||
c.TextMeasurementTypes = &textMeasurementTypesService{c}
|
||||
c.UnitTypes = &unitTypesService{c}
|
||||
c.Measurements = &measurementsService{c}
|
||||
|
|
|
@ -13,11 +13,11 @@ import (
|
|||
// A Measurement is the main data type for this application
|
||||
// There are two types of supported measurements: text & numerical. The table
|
||||
// has a constraint that will allow one or the other for a particular
|
||||
// combination of strain & observation, but not both.
|
||||
// combination of strain & characteristic, but not both.
|
||||
type Measurement struct {
|
||||
Id int64 `json:"id,omitempty"`
|
||||
StrainId int64 `db:"strain_id" json:"strainId"`
|
||||
ObservationId int64 `db:"observation_id" json:"observationId"`
|
||||
CharacteristicId int64 `db:"characteristic_id" json:"characteristicId"`
|
||||
TextMeasurementTypeId NullInt64 `db:"text_measurement_type_id" json:"textMeasurementTypeId"`
|
||||
TxtValue NullString `db:"txt_value" json:"txtValue"`
|
||||
NumValue NullFloat64 `db:"num_value" json:"numValue"`
|
||||
|
|
|
@ -13,7 +13,7 @@ func newMeasurement() *Measurement {
|
|||
measurement := NewMeasurement()
|
||||
measurement.Id = 1
|
||||
measurement.StrainId = 1
|
||||
measurement.ObservationId = 1
|
||||
measurement.CharacteristicId = 1
|
||||
measurement.UnitTypeId = NullInt64{sql.NullInt64{Int64: 1, Valid: true}}
|
||||
return measurement
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ func TestMeasurementService_Create(t *testing.T) {
|
|||
mux.HandleFunc(urlPath(t, router.CreateMeasurement, nil), func(w http.ResponseWriter, r *http.Request) {
|
||||
called = true
|
||||
testMethod(t, r, "POST")
|
||||
testBody(t, r, `{"id":1,"strainId":1,"observationId":1,"textMeasurementTypeId":null,"txtValue":null,"numValue":1.23,"confidenceInterval":null,"unitTypeId":1,"notes":null,"testMethodId":null,"createdAt":"0001-01-01T00:00:00Z","updatedAt":"0001-01-01T00:00:00Z"}`+"\n")
|
||||
testBody(t, r, `{"id":1,"strainId":1,"characteristicId":1,"textMeasurementTypeId":null,"txtValue":null,"numValue":1.23,"confidenceInterval":null,"unitTypeId":1,"notes":null,"testMethodId":null,"createdAt":"0001-01-01T00:00:00Z","updatedAt":"0001-01-01T00:00:00Z"}`+"\n")
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
writeJSON(w, want)
|
||||
|
@ -127,7 +127,7 @@ func TestMeasurementService_Update(t *testing.T) {
|
|||
mux.HandleFunc(urlPath(t, router.UpdateMeasurement, map[string]string{"Id": "1"}), func(w http.ResponseWriter, r *http.Request) {
|
||||
called = true
|
||||
testMethod(t, r, "PUT")
|
||||
testBody(t, r, `{"id":1,"strainId":1,"observationId":1,"textMeasurementTypeId":null,"txtValue":null,"numValue":4.56,"confidenceInterval":null,"unitTypeId":1,"notes":null,"testMethodId":null,"createdAt":"0001-01-01T00:00:00Z","updatedAt":"0001-01-01T00:00:00Z"}`+"\n")
|
||||
testBody(t, r, `{"id":1,"strainId":1,"characteristicId":1,"textMeasurementTypeId":null,"txtValue":null,"numValue":4.56,"confidenceInterval":null,"unitTypeId":1,"notes":null,"testMethodId":null,"createdAt":"0001-01-01T00:00:00Z","updatedAt":"0001-01-01T00:00:00Z"}`+"\n")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
writeJSON(w, want)
|
||||
})
|
||||
|
|
|
@ -1,204 +0,0 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/thermokarst/bactdb/router"
|
||||
)
|
||||
|
||||
// An Observation is a lookup type
|
||||
type Observation struct {
|
||||
Id int64 `json:"id,omitempty"`
|
||||
ObservationName string `db:"observation_name" json:"observationName"`
|
||||
CharacteristicTypeId int64 `db:"characteristic_type_id" json:"characteristicTypeId"`
|
||||
CreatedAt time.Time `db:"created_at" json:"createdAt"`
|
||||
UpdatedAt time.Time `db:"updated_at" json:"updatedAt"`
|
||||
DeletedAt NullTime `db:"deleted_at" json:"deletedAt"`
|
||||
}
|
||||
|
||||
func NewObservation() *Observation {
|
||||
return &Observation{
|
||||
ObservationName: "Test Observation",
|
||||
}
|
||||
}
|
||||
|
||||
type ObservationsService interface {
|
||||
// Get an observation
|
||||
Get(id int64) (*Observation, error)
|
||||
|
||||
// List all observations
|
||||
List(opt *ObservationListOptions) ([]*Observation, error)
|
||||
|
||||
// Create an observation
|
||||
Create(observation *Observation) (bool, error)
|
||||
|
||||
// Update an observation
|
||||
Update(id int64, Observation *Observation) (updated bool, err error)
|
||||
|
||||
// Delete an observation
|
||||
Delete(id int64) (deleted bool, err error)
|
||||
}
|
||||
|
||||
var (
|
||||
ErrObservationNotFound = errors.New("observation not found")
|
||||
)
|
||||
|
||||
type observationsService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
func (s *observationsService) Get(id int64) (*Observation, error) {
|
||||
strId := strconv.FormatInt(id, 10)
|
||||
|
||||
url, err := s.client.url(router.Observation, map[string]string{"Id": strId}, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequest("GET", url.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var observation *Observation
|
||||
_, err = s.client.Do(req, &observation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return observation, nil
|
||||
}
|
||||
|
||||
func (s *observationsService) Create(observation *Observation) (bool, error) {
|
||||
url, err := s.client.url(router.CreateObservation, nil, nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequest("POST", url.String(), observation)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, &observation)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return resp.StatusCode == http.StatusCreated, nil
|
||||
}
|
||||
|
||||
type ObservationListOptions struct {
|
||||
ListOptions
|
||||
}
|
||||
|
||||
func (s *observationsService) List(opt *ObservationListOptions) ([]*Observation, error) {
|
||||
url, err := s.client.url(router.Observations, nil, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequest("GET", url.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var observations []*Observation
|
||||
_, err = s.client.Do(req, &observations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return observations, nil
|
||||
}
|
||||
|
||||
func (s *observationsService) Update(id int64, observation *Observation) (bool, error) {
|
||||
strId := strconv.FormatInt(id, 10)
|
||||
|
||||
url, err := s.client.url(router.UpdateObservation, map[string]string{"Id": strId}, nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequest("PUT", url.String(), observation)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := s.client.Do(req, &observation)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return resp.StatusCode == http.StatusOK, nil
|
||||
}
|
||||
|
||||
func (s *observationsService) Delete(id int64) (bool, error) {
|
||||
strId := strconv.FormatInt(id, 10)
|
||||
|
||||
url, err := s.client.url(router.DeleteObservation, map[string]string{"Id": strId}, nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
req, err := s.client.NewRequest("DELETE", url.String(), nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var observation *Observation
|
||||
resp, err := s.client.Do(req, &observation)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return resp.StatusCode == http.StatusOK, nil
|
||||
}
|
||||
|
||||
type MockObservationsService struct {
|
||||
Get_ func(id int64) (*Observation, error)
|
||||
List_ func(opt *ObservationListOptions) ([]*Observation, error)
|
||||
Create_ func(observation *Observation) (bool, error)
|
||||
Update_ func(id int64, observation *Observation) (bool, error)
|
||||
Delete_ func(id int64) (bool, error)
|
||||
}
|
||||
|
||||
var _ ObservationsService = &MockObservationsService{}
|
||||
|
||||
func (s *MockObservationsService) Get(id int64) (*Observation, error) {
|
||||
if s.Get_ == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return s.Get_(id)
|
||||
}
|
||||
|
||||
func (s *MockObservationsService) Create(observation *Observation) (bool, error) {
|
||||
if s.Create_ == nil {
|
||||
return false, nil
|
||||
}
|
||||
return s.Create_(observation)
|
||||
}
|
||||
|
||||
func (s *MockObservationsService) List(opt *ObservationListOptions) ([]*Observation, error) {
|
||||
if s.List_ == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return s.List_(opt)
|
||||
}
|
||||
|
||||
func (s *MockObservationsService) Update(id int64, observation *Observation) (bool, error) {
|
||||
if s.Update_ == nil {
|
||||
return false, nil
|
||||
}
|
||||
return s.Update_(id, observation)
|
||||
}
|
||||
|
||||
func (s *MockObservationsService) Delete(id int64) (bool, error) {
|
||||
if s.Delete_ == nil {
|
||||
return false, nil
|
||||
}
|
||||
return s.Delete_(id)
|
||||
}
|
|
@ -1,174 +0,0 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/thermokarst/bactdb/router"
|
||||
)
|
||||
|
||||
func newObservation() *Observation {
|
||||
observation := NewObservation()
|
||||
observation.Id = 1
|
||||
return observation
|
||||
}
|
||||
|
||||
func TestObservationService_Get(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
want := newObservation()
|
||||
|
||||
var called bool
|
||||
mux.HandleFunc(urlPath(t, router.Observation, map[string]string{"Id": "1"}), func(w http.ResponseWriter, r *http.Request) {
|
||||
called = true
|
||||
testMethod(t, r, "GET")
|
||||
|
||||
writeJSON(w, want)
|
||||
})
|
||||
|
||||
observation, err := client.Observations.Get(want.Id)
|
||||
if err != nil {
|
||||
t.Errorf("Observations.Get returned error: %v", err)
|
||||
}
|
||||
|
||||
if !called {
|
||||
t.Fatal("!called")
|
||||
}
|
||||
|
||||
normalizeTime(&want.CreatedAt, &want.UpdatedAt, &want.DeletedAt)
|
||||
|
||||
if !reflect.DeepEqual(observation, want) {
|
||||
t.Errorf("Observations.Get return %+v, want %+v", observation, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestObservationService_Create(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
want := newObservation()
|
||||
|
||||
var called bool
|
||||
mux.HandleFunc(urlPath(t, router.CreateObservation, nil), func(w http.ResponseWriter, r *http.Request) {
|
||||
called = true
|
||||
testMethod(t, r, "POST")
|
||||
testBody(t, r, `{"id":1,"observationName":"Test Observation","characteristicTypeId":0,"createdAt":"0001-01-01T00:00:00Z","updatedAt":"0001-01-01T00:00:00Z","deletedAt":null}`+"\n")
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
writeJSON(w, want)
|
||||
})
|
||||
|
||||
observation := newObservation()
|
||||
created, err := client.Observations.Create(observation)
|
||||
if err != nil {
|
||||
t.Errorf("Observations.Create returned error: %v", err)
|
||||
}
|
||||
|
||||
if !created {
|
||||
t.Error("!created")
|
||||
}
|
||||
|
||||
if !called {
|
||||
t.Fatal("!called")
|
||||
}
|
||||
|
||||
normalizeTime(&want.CreatedAt, &want.UpdatedAt, &want.DeletedAt)
|
||||
if !reflect.DeepEqual(observation, want) {
|
||||
t.Errorf("Observations.Create returned %+v, want %+v", observation, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestObservationService_List(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
want := []*Observation{newObservation()}
|
||||
|
||||
var called bool
|
||||
mux.HandleFunc(urlPath(t, router.Observations, nil), func(w http.ResponseWriter, r *http.Request) {
|
||||
called = true
|
||||
testMethod(t, r, "GET")
|
||||
testFormValues(t, r, values{})
|
||||
|
||||
writeJSON(w, want)
|
||||
})
|
||||
|
||||
observations, err := client.Observations.List(nil)
|
||||
if err != nil {
|
||||
t.Errorf("Observations.List returned error: %v", err)
|
||||
}
|
||||
|
||||
if !called {
|
||||
t.Fatal("!called")
|
||||
}
|
||||
|
||||
for _, u := range want {
|
||||
normalizeTime(&u.CreatedAt, &u.UpdatedAt, &u.DeletedAt)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(observations, want) {
|
||||
t.Errorf("Observations.List return %+v, want %+v", observations, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestObservationService_Update(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
want := newObservation()
|
||||
|
||||
var called bool
|
||||
mux.HandleFunc(urlPath(t, router.UpdateObservation, map[string]string{"Id": "1"}), func(w http.ResponseWriter, r *http.Request) {
|
||||
called = true
|
||||
testMethod(t, r, "PUT")
|
||||
testBody(t, r, `{"id":1,"observationName":"Test Obs Updated","characteristicTypeId":0,"createdAt":"0001-01-01T00:00:00Z","updatedAt":"0001-01-01T00:00:00Z","deletedAt":null}`+"\n")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
writeJSON(w, want)
|
||||
})
|
||||
|
||||
observation := newObservation()
|
||||
observation.ObservationName = "Test Obs Updated"
|
||||
updated, err := client.Observations.Update(observation.Id, observation)
|
||||
if err != nil {
|
||||
t.Errorf("Observations.Update returned error: %v", err)
|
||||
}
|
||||
|
||||
if !updated {
|
||||
t.Error("!updated")
|
||||
}
|
||||
|
||||
if !called {
|
||||
t.Fatal("!called")
|
||||
}
|
||||
}
|
||||
|
||||
func TestObservationService_Delete(t *testing.T) {
|
||||
setup()
|
||||
defer teardown()
|
||||
|
||||
want := newObservation()
|
||||
|
||||
var called bool
|
||||
mux.HandleFunc(urlPath(t, router.DeleteObservation, map[string]string{"Id": "1"}), func(w http.ResponseWriter, r *http.Request) {
|
||||
called = true
|
||||
testMethod(t, r, "DELETE")
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
writeJSON(w, want)
|
||||
})
|
||||
|
||||
deleted, err := client.Observations.Delete(want.Id)
|
||||
if err != nil {
|
||||
t.Errorf("Observations.Delete returned error: %v", err)
|
||||
}
|
||||
|
||||
if !deleted {
|
||||
t.Error("!deleted")
|
||||
}
|
||||
|
||||
if !called {
|
||||
t.Fatal("!called")
|
||||
}
|
||||
}
|
|
@ -38,12 +38,12 @@ func API() *mux.Router {
|
|||
m.Path("/characteristic_types/{Id:.+}").Methods("PUT").Name(UpdateCharacteristicType)
|
||||
m.Path("/characteristic_types/{Id:.+}").Methods("DELETE").Name(DeleteCharacteristicType)
|
||||
|
||||
// Observations
|
||||
m.Path("/observations").Methods("GET").Name(Observations)
|
||||
m.Path("/observations").Methods("POST").Name(CreateObservation)
|
||||
m.Path("/observations/{Id:.+}").Methods("GET").Name(Observation)
|
||||
m.Path("/observations/{Id:.+}").Methods("PUT").Name(UpdateObservation)
|
||||
m.Path("/observations/{Id:.+}").Methods("DELETE").Name(DeleteObservation)
|
||||
// Characteristics
|
||||
m.Path("/characteristics").Methods("GET").Name(Characteristics)
|
||||
m.Path("/characteristics").Methods("POST").Name(CreateCharacteristic)
|
||||
m.Path("/characteristics/{Id:.+}").Methods("GET").Name(Characteristic)
|
||||
m.Path("/characteristics/{Id:.+}").Methods("PUT").Name(UpdateCharacteristic)
|
||||
m.Path("/characteristics/{Id:.+}").Methods("DELETE").Name(DeleteCharacteristic)
|
||||
|
||||
// TextMeasurementTypes
|
||||
m.Path("/text_measurement_types/").Methods("GET").Name(TextMeasurementTypes)
|
||||
|
|
|
@ -29,11 +29,11 @@ const (
|
|||
UpdateCharacteristicType = "characteristic_type:update"
|
||||
DeleteCharacteristicType = "characteristic_type:delete"
|
||||
|
||||
Observation = "observation:get"
|
||||
CreateObservation = "observation:create"
|
||||
Observations = "observation:list"
|
||||
UpdateObservation = "observation:update"
|
||||
DeleteObservation = "observation:delete"
|
||||
Characteristic = "characteristic:get"
|
||||
CreateCharacteristic = "characteristic:create"
|
||||
Characteristics = "characteristic:list"
|
||||
UpdateCharacteristic = "characteristic:update"
|
||||
DeleteCharacteristic = "characteristic:delete"
|
||||
|
||||
TextMeasurementType = "text_measurement_type:get"
|
||||
CreateTextMeasurementType = "text_measurement_type:create"
|
||||
|
|
Reference in a new issue