From 55aa9db5c7a72af2a57ac953ebbbdbdec3e1efa1 Mon Sep 17 00:00:00 2001 From: David Stotijn Date: Wed, 19 May 2021 22:21:53 +0200 Subject: [PATCH] Add tests for "create page" endpoint --- client_test.go | 283 +++++++++++++++++++++++++++++++++++++++++++++++++ page.go | 4 +- rich_text.go | 2 +- 3 files changed, 285 insertions(+), 4 deletions(-) diff --git a/client_test.go b/client_test.go index e952481..7af3adc 100644 --- a/client_test.go +++ b/client_test.go @@ -769,3 +769,286 @@ func TestFindPageByID(t *testing.T) { }) } } + +func TestCreatePage(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + params notion.CreatePageParams + respBody func(r *http.Request) io.Reader + respStatusCode int + expPostBody map[string]interface{} + expResponse notion.Page + expError error + }{ + { + name: "successful response", + params: notion.CreatePageParams{ + ParentType: notion.ParentTypePage, + ParentID: "b0668f48-8d66-4733-9bdb-2f82215707f7", + Title: []notion.RichText{ + { + Text: ¬ion.Text{ + Content: "Foobar", + }, + }, + }, + Children: []notion.Block{ + { + Object: "block", + Type: notion.BlockTypeParagraph, + Paragraph: ¬ion.RichTextBlock{ + Text: []notion.RichText{ + { + Text: ¬ion.Text{ + Content: "Lorem ipsum dolor sit amet.", + }, + }, + }, + }, + }, + }, + }, + respBody: func(_ *http.Request) io.Reader { + return strings.NewReader( + `{ + "object": "page", + "id": "276ee233-e426-4ed0-9986-6b22af8550df", + "created_time": "2021-05-19T19:34:05.068Z", + "last_edited_time": "2021-05-19T19:34:05.069Z", + "parent": { + "type": "page_id", + "page_id": "b0668f48-8d66-4733-9bdb-2f82215707f7" + }, + "archived": false, + "properties": { + "title": { + "id": "title", + "type": "title", + "title": [ + { + "type": "text", + "text": { + "content": "Foobar", + "link": null + }, + "annotations": { + "bold": false, + "italic": false, + "strikethrough": false, + "underline": false, + "code": false, + "color": "default" + }, + "plain_text": "Foobar", + "href": null + } + ] + } + } + }`, + ) + }, + respStatusCode: http.StatusOK, + expPostBody: map[string]interface{}{ + "parent": map[string]interface{}{ + "page_id": "b0668f48-8d66-4733-9bdb-2f82215707f7", + }, + "properties": map[string]interface{}{ + "title": []interface{}{ + map[string]interface{}{ + "text": map[string]interface{}{ + "content": "Foobar", + }, + }, + }, + }, + "children": []interface{}{ + map[string]interface{}{ + "object": "block", + "type": "paragraph", + "paragraph": map[string]interface{}{ + "text": []interface{}{ + map[string]interface{}{ + "text": map[string]interface{}{ + "content": "Lorem ipsum dolor sit amet.", + }, + }, + }, + }, + }, + }, + }, + expResponse: notion.Page{ + ID: "276ee233-e426-4ed0-9986-6b22af8550df", + CreatedTime: mustParseTime(time.RFC3339Nano, "2021-05-19T19:34:05.068Z"), + LastEditedTime: mustParseTime(time.RFC3339Nano, "2021-05-19T19:34:05.069Z"), + Parent: notion.PageParent{ + Type: notion.ParentTypePage, + PageID: notion.StringPtr("b0668f48-8d66-4733-9bdb-2f82215707f7"), + }, + Properties: notion.PageProperties{ + Title: notion.PageTitle{ + Title: []notion.RichText{ + { + Type: notion.RichTextTypeText, + Text: ¬ion.Text{ + Content: "Foobar", + }, + Annotations: ¬ion.Annotations{ + Color: notion.ColorDefault, + }, + PlainText: "Foobar", + }, + }, + }, + }, + }, + expError: nil, + }, + { + name: "error response", + params: notion.CreatePageParams{ + ParentType: notion.ParentTypePage, + ParentID: "b0668f48-8d66-4733-9bdb-2f82215707f7", + Title: []notion.RichText{ + { + Text: ¬ion.Text{ + Content: "Foobar", + }, + }, + }, + }, + respBody: func(_ *http.Request) io.Reader { + return strings.NewReader( + `{ + "object": "error", + "status": 400, + "code": "validation_error", + "message": "foobar" + }`, + ) + }, + respStatusCode: http.StatusBadRequest, + expPostBody: map[string]interface{}{ + "parent": map[string]interface{}{ + "page_id": "b0668f48-8d66-4733-9bdb-2f82215707f7", + }, + "properties": map[string]interface{}{ + "title": []interface{}{ + map[string]interface{}{ + "text": map[string]interface{}{ + "content": "Foobar", + }, + }, + }, + }, + }, + expResponse: notion.Page{}, + expError: errors.New("notion: failed to create page: foobar (code: validation_error, status: 400)"), + }, + { + name: "parent type required error", + params: notion.CreatePageParams{ + ParentID: "b0668f48-8d66-4733-9bdb-2f82215707f7", + Title: []notion.RichText{ + { + Text: ¬ion.Text{ + Content: "Foobar", + }, + }, + }, + }, + expResponse: notion.Page{}, + expError: errors.New("notion: invalid page params: parent type is required"), + }, + { + name: "parent id required error", + params: notion.CreatePageParams{ + ParentType: notion.ParentTypePage, + Title: []notion.RichText{ + { + Text: ¬ion.Text{ + Content: "Foobar", + }, + }, + }, + }, + expResponse: notion.Page{}, + expError: errors.New("notion: invalid page params: parent ID is required"), + }, + { + name: "page title required error", + params: notion.CreatePageParams{ + ParentType: notion.ParentTypePage, + ParentID: "b0668f48-8d66-4733-9bdb-2f82215707f7", + }, + expResponse: notion.Page{}, + expError: errors.New("notion: invalid page params: title is required when parent type is page"), + }, + { + name: "database properties required error", + params: notion.CreatePageParams{ + ParentType: notion.ParentTypeDatabase, + ParentID: "b0668f48-8d66-4733-9bdb-2f82215707f7", + }, + expResponse: notion.Page{}, + expError: errors.New("notion: invalid page params: database page properties is required when parent type is database"), + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + httpClient := &http.Client{ + Transport: &mockRoundtripper{fn: func(r *http.Request) (*http.Response, error) { + postBody := make(map[string]interface{}) + + err := json.NewDecoder(r.Body).Decode(&postBody) + if err != nil && err != io.EOF { + t.Fatal(err) + } + + if len(tt.expPostBody) == 0 && len(postBody) != 0 { + t.Errorf("unexpected post body: %#v", postBody) + } + + if len(tt.expPostBody) != 0 && len(postBody) == 0 { + t.Errorf("post body not equal (expected %+v, got: nil)", tt.expPostBody) + } + + if len(tt.expPostBody) != 0 && len(postBody) != 0 { + if diff := cmp.Diff(tt.expPostBody, postBody); diff != "" { + t.Errorf("post body not equal (-exp, +got):\n%v", diff) + } + } + + return &http.Response{ + StatusCode: tt.respStatusCode, + Status: http.StatusText(tt.respStatusCode), + Body: ioutil.NopCloser(tt.respBody(r)), + }, nil + }}, + } + client := notion.NewClient("secret-api-key", notion.WithHTTPClient(httpClient)) + page, err := client.CreatePage(context.Background(), tt.params) + + if tt.expError == nil && err != nil { + t.Fatalf("unexpected error: %v", err) + } + if tt.expError != nil && err == nil { + t.Fatalf("error not equal (expected: %v, got: nil)", tt.expError) + } + if tt.expError != nil && err != nil && tt.expError.Error() != err.Error() { + t.Fatalf("error not equal (expected: %v, got: %v)", tt.expError, err) + } + + if diff := cmp.Diff(tt.expResponse, page); diff != "" { + t.Fatalf("response not equal (-exp, +got):\n%v", diff) + } + }) + } +} diff --git a/page.go b/page.go index 0f389cf..529791a 100644 --- a/page.go +++ b/page.go @@ -23,7 +23,7 @@ type Page struct { } type PageParent struct { - Type ParentType `json:"type"` + Type ParentType `json:"type,omitempty"` PageID *string `json:"page_id,omitempty"` DatabaseID *string `json:"database_id,omitempty"` @@ -109,10 +109,8 @@ func (p CreatePageParams) MarshalJSON() ([]byte, error) { var parent PageParent if p.DatabasePageProperties != nil { - parent.Type = "database_id" parent.DatabaseID = StringPtr(p.ParentID) } else if p.Title != nil { - parent.Type = "page_id" parent.PageID = StringPtr(p.ParentID) } diff --git a/rich_text.go b/rich_text.go index b3d4566..0650630 100644 --- a/rich_text.go +++ b/rich_text.go @@ -3,7 +3,7 @@ package notion import "time" type RichText struct { - Type RichTextType `json:"type"` + Type RichTextType `json:"type,omitempty"` Annotations *Annotations `json:"annotations,omitempty"` PlainText string `json:"plain_text,omitempty"`