Create a new observation
This commit is contained in:
		
							parent
							
								
									a018d2bd7a
								
							
						
					
					
						commit
						f867e5c424
					
				
					 9 changed files with 154 additions and 3 deletions
				
			
		|  | @ -48,6 +48,7 @@ func Handler() *mux.Router { | |||
| 	m.Get(router.DeleteObservationType).Handler(handler(serveDeleteObservationType)) | ||||
| 
 | ||||
| 	m.Get(router.Observation).Handler(handler(serveObservation)) | ||||
| 	m.Get(router.CreateObservation).Handler(handler(serveCreateObservation)) | ||||
| 
 | ||||
| 	return m | ||||
| } | ||||
|  |  | |||
|  | @ -1,10 +1,12 @@ | |||
| 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 { | ||||
|  | @ -20,3 +22,21 @@ func serveObservation(w http.ResponseWriter, r *http.Request) error { | |||
| 
 | ||||
| 	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) | ||||
| } | ||||
|  |  | |||
|  | @ -38,3 +38,30 @@ func TestObservation_Get(t *testing.T) { | |||
| 		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") | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -1,6 +1,10 @@ | |||
| package datastore | ||||
| 
 | ||||
| import "github.com/thermokarst/bactdb/models" | ||||
| import ( | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/thermokarst/bactdb/models" | ||||
| ) | ||||
| 
 | ||||
| func init() { | ||||
| 	DB.AddTableWithName(models.Observation{}, "observations").SetKeys(true, "Id") | ||||
|  | @ -20,3 +24,13 @@ func (s *observationsStore) Get(id int64) (*models.Observation, error) { | |||
| 	} | ||||
| 	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 | ||||
| } | ||||
|  |  | |||
|  | @ -45,3 +45,23 @@ func TestObservationsStore_Get_db(t *testing.T) { | |||
| 		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") | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ package models | |||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"net/http" | ||||
| 	"strconv" | ||||
| 	"time" | ||||
| 
 | ||||
|  | @ -28,6 +29,9 @@ func NewObservation() *Observation { | |||
| type ObservationsService interface { | ||||
| 	// Get an observation | ||||
| 	Get(id int64) (*Observation, error) | ||||
| 
 | ||||
| 	// Create an observation | ||||
| 	Create(observation *Observation) (bool, error) | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
|  | @ -60,8 +64,28 @@ func (s *observationsService) Get(id int64) (*Observation, error) { | |||
| 	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 MockObservationsService struct { | ||||
| 	Get_ func(id int64) (*Observation, error) | ||||
| 	Get_    func(id int64) (*Observation, error) | ||||
| 	Create_ func(observation *Observation) (bool, error) | ||||
| } | ||||
| 
 | ||||
| var _ObservationsService = &MockObservationsService{} | ||||
|  | @ -72,3 +96,10 @@ func (s *MockObservationsService) Get(id int64) (*Observation, error) { | |||
| 	} | ||||
| 	return s.Get_(id) | ||||
| } | ||||
| 
 | ||||
| func (s *MockObservationsService) Create(observation *Observation) (bool, error) { | ||||
| 	if s.Create_ == nil { | ||||
| 		return false, nil | ||||
| 	} | ||||
| 	return s.Create_(observation) | ||||
| } | ||||
|  |  | |||
|  | @ -43,3 +43,39 @@ func TestObservationService_Get(t *testing.T) { | |||
| 		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,"observation_name":"Test Observation","observation_type_id":0,"created_at":"0001-01-01T00:00:00Z","updated_at":"0001-01-01T00:00:00Z","deleted_at":{"Time":"0001-01-01T00:00:00Z","Valid":false}}`+"\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) | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -39,6 +39,7 @@ func API() *mux.Router { | |||
| 	m.Path("/observation_types/{Id:.+}").Methods("DELETE").Name(DeleteObservationType) | ||||
| 
 | ||||
| 	// Observations | ||||
| 	m.Path("/observations").Methods("POST").Name(CreateObservation) | ||||
| 	m.Path("/observations/{Id:.+}").Methods("GET").Name(Observation) | ||||
| 
 | ||||
| 	return m | ||||
|  |  | |||
|  | @ -29,5 +29,6 @@ const ( | |||
| 	UpdateObservationType = "observation_type:update" | ||||
| 	DeleteObservationType = "observation_type:delete" | ||||
| 
 | ||||
| 	Observation = "observation:get" | ||||
| 	Observation       = "observation:get" | ||||
| 	CreateObservation = "observation:create" | ||||
| ) | ||||
|  |  | |||
		Reference in a new issue
	
	 Matthew Dillon
						Matthew Dillon