Skip to content

Commit

Permalink
Merge pull request #54 from kintone-labs/v0.5.0
Browse files Browse the repository at this point in the history
V0.5.0
  • Loading branch information
nmanhit committed Feb 22, 2023
2 parents bdfbf2c + f14b3bc commit be577bf
Show file tree
Hide file tree
Showing 5 changed files with 220 additions and 22 deletions.
55 changes: 35 additions & 20 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ func isJSON(contentType string) bool {
func parseResponse(resp *http.Response) ([]byte, error) {
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()

if err != nil {
return nil, err
}
Expand Down Expand Up @@ -377,39 +378,53 @@ func (app *App) GetRecord(id uint64) (*Record, error) {
return rec, nil
}

// GetRecords fetches records matching given conditions.
//
// This method can retrieve up to 100 records at once.
// To retrieve more records, you need to call GetRecords with
// increasing "offset" query parameter until the number of records
// retrieved becomes less than 100.
//
// If fields is nil, all fields are retrieved.
// See API specs how to construct query strings.
func (app *App) GetRecords(fields []string, query string) ([]*Record, error) {
func (app *App) getRecords(fields []string, query string, totalCount bool) ([]*Record, string, error) {
type request_body struct {
App uint64 `json:"app,string"`
Fields []string `json:"fields"`
Query string `json:"query"`
App uint64 `json:"app,string"`
Fields []string `json:"fields"`
Query string `json:"query"`
TotalCount bool `json:"totalCount"`
}
data, _ := json.Marshal(request_body{app.AppId, fields, query})

data, _ := json.Marshal(request_body{app.AppId, fields, query, totalCount})

req, err := app.newRequest("GET", "records", bytes.NewReader(data))
if err != nil {
return nil, err
return nil, "", err
}
resp, err := app.do(req)
if err != nil {
return nil, err
return nil, "", err
}
body, err := parseResponse(resp)
if err != nil {
return nil, err
return nil, "", err
}
recs, err := DecodeRecords(body)
recs, respTotalCount, err := DecodeRecordsWithTotalCount(body)

if err != nil {
return nil, ErrInvalidResponse
return nil, "", ErrInvalidResponse
}
return recs, nil
return recs, respTotalCount, nil
}

// GetRecords fetches records matching given conditions.
//
// This method can retrieve up to 100 records at once.
// To retrieve more records, you need to call GetRecords with
// increasing "offset" query parameter until the number of records
// retrieved becomes less than 100.
//
// If fields is nil, all fields are retrieved.
// See API specs how to construct query strings.
func (app *App) GetRecords(fields []string, query string) ([]*Record, error) {
records, _, err := app.getRecords(fields, query, false)
return records, err
}

// GetRecordsWithTotalCount fetches records matching given conditions and returns totalCount of query result.
func (app *App) GetRecordsWithTotalCount(fields []string, query string) ([]*Record, string, error) {
return app.getRecords(fields, query, true)
}

// GetAllRecords fetches all records.
Expand Down
43 changes: 41 additions & 2 deletions app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package kintone
import (
"crypto/tls"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"io/ioutil"
Expand Down Expand Up @@ -168,8 +169,30 @@ func handleResponseGetRecords(response http.ResponseWriter, request *http.Reques
checkAuth(response, request)
checkContentType(response, request)
if request.Method == "GET" {
testData := GetTestDataGetRecords()
fmt.Fprint(response, testData.output)
type RequestBody struct {
App uint64 `json:"app,string"`
Fields []string `json:"fields"`
Query string `json:"query"`
TotalCount bool `json:"totalCount"`
}

body, err := ioutil.ReadAll(request.Body)
if err != nil {
http.Error(response, "Bad request", http.StatusBadRequest)
return
}
var bodyRequest RequestBody
if err := json.Unmarshal([]byte(body), &bodyRequest); err != nil {
http.Error(response, "Body incorrect", http.StatusBadRequest)
}

if bodyRequest.TotalCount {
testData := GetTestDataGetRecordsWithTotalCount()
fmt.Fprint(response, testData.output)
} else {
testData := GetTestDataGetRecords()
fmt.Fprint(response, testData.output)
}
} else if request.Method == "DELETE" {
testData := GetTestDataDeleteRecords()
fmt.Fprint(response, testData.output)
Expand Down Expand Up @@ -302,6 +325,22 @@ func TestGetRecord(t *testing.T) {
}
}

func TestGetRecordWithTotalCount(t *testing.T) {
testDataRecords := GetTestDataGetRecordsWithTotalCount()
app := newApp()

if recs, totalCount, err := app.GetRecordsWithTotalCount(testDataRecords.input[0].([]string), testDataRecords.input[1].(string)); err != nil {
t.Error(err)
} else {
if len(recs) > 3 {
t.Error("Too many records")
}
if totalCount != "999" {
t.Error("TotalCount incorrect", err)
}
}
}

func TestUpdateRecord(t *testing.T) {
testData := GetTestDataGetRecord()
testDataRecords := GetTestDataGetRecords()
Expand Down
49 changes: 49 additions & 0 deletions app_test_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,55 @@ func GetTestDataGetRecords() *TestData {
}
}

func GetTestDataGetRecordsWithTotalCount() *TestData {
return &TestData{
input: []interface{}{
[]string{},
"limit 3 offset 3",
},
output: `
{
"records":[
{
"Created_datetime":{
"type":"CREATED_TIME",
"value":"2019-03-11T04:50:00Z"
},
"Created_by":{
"type":"CREATOR",
"value":{
"code":"Administrator",
"name":"Administrator"
}
},
"$id":{
"type":"__ID__",
"value":"1"
}
},
{
"Created_datetime":{
"type":"CREATED_TIME",
"value":"2019-03-11T06:42:00Z"
},
"Created_by":{
"type":"CREATOR",
"value":{
"code":"Administrator",
"name":"Administrator"
}
},
"$id":{
"type":"__ID__",
"value":"2"
}
}
],
"totalCount": "999"
}`,
}
}

func GetDataTestUploadFile() *TestData {
return &TestData{
output: `
Expand Down
22 changes: 22 additions & 0 deletions record.go
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,28 @@ func DecodeRecords(b []byte) ([]*Record, error) {
return rec_list, nil
}

func DecodeRecordsWithTotalCount(b []byte) ([]*Record, string, error) {
var t struct {
Records []recordData `json:"records"`
TotalCount string `json:"totalCount"`
}
err := json.Unmarshal(b, &t)
if err != nil {
return nil, "", errors.New("Invalid JSON format")
}

rec_list := make([]*Record, len(t.Records))
for i, rd := range t.Records {
r, err := decodeRecordData(rd)
if err != nil {
return nil, "", err
}
rec_list[i] = r
}

return rec_list, t.TotalCount, nil
}

// DecodeRecord decodes JSON response for single-get API.
func DecodeRecord(b []byte) (*Record, error) {
var t struct {
Expand Down
73 changes: 73 additions & 0 deletions record_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,3 +389,76 @@ func TestDecodeRecords(t *testing.T) {
t.Error("dropdown must be invalid")
}
}

func TestDecodeRecordsWithTotalCount(t *testing.T) {
b := []byte(`
{
"records": [
{
"record_id": {
"type": "RECORD_NUMBER",
"value": "1"
},
"created_time": {
"type": "CREATED_TIME",
"value": "2012-02-03T08:50:00Z"
},
"updated_time": {
"type": "UPDATED_TIME",
"value": "2018-10-24T08:50:00Z"
},
"dropdown": {
"type": "DROP_DOWN",
"value": null
}
},
{
"record_id": {
"type": "RECORD_NUMBER",
"value": "2"
},
"created_time": {
"type": "CREATED_TIME",
"value": "2012-02-03T09:22:00Z"
},
"updated_time": {
"type": "UPDATED_TIME",
"value": "2018-10-24T09:22:00Z"
},
"dropdown": {
"type": "DROP_DOWN",
"value": null
}
}
],
"totalCount": "9999"
}`)

type Record struct {
id uint64
revision int64
Fields map[string]interface{}
}

rec, totalCount, err := DecodeRecordsWithTotalCount(b)

if err != nil {
t.Fatal(err)
}
if totalCount != "9999" {
t.Error("totalCount is incorrect")
}
if len(rec) != 2 {
t.Error("length mismatch")
}
if _, ok := rec[0].Fields["record_id"]; !ok {
t.Error("record_id must exist")
}
dropdown, ok := rec[0].Fields["dropdown"]
if !ok {
t.Error("null dropdown field must exist")
}
if dropdown.(SingleSelectField).Valid {
t.Error("dropdown must be invalid")
}
}

0 comments on commit be577bf

Please sign in to comment.