Skip to content
This repository was archived by the owner on Sep 11, 2018. It is now read-only.

Commit cd13040

Browse files
MarinXdlebech
authored andcommitted
Add support for Blog API (#95)
* Implement blog service (CRUD) * Added test for blog service * Register blog service on client * Remove GetTags func so coverage can be 100%
1 parent 65a6d21 commit cd13040

File tree

4 files changed

+266
-0
lines changed

4 files changed

+266
-0
lines changed

blog.go

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package goshopify
2+
3+
import (
4+
"fmt"
5+
"time"
6+
)
7+
8+
const blogsBasePath = "admin/blogs"
9+
10+
// BlogService is an interface for interfacing with the blogs endpoints
11+
// of the Shopify API.
12+
// See: https://help.shopify.com/api/reference/online_store/blog
13+
type BlogService interface {
14+
List(interface{}) ([]Blog, error)
15+
Count(interface{}) (int, error)
16+
Get(int, interface{}) (*Blog, error)
17+
Create(Blog) (*Blog, error)
18+
Update(Blog) (*Blog, error)
19+
Delete(int) error
20+
}
21+
22+
// BlogServiceOp handles communication with the blog related methods of
23+
// the Shopify API.
24+
type BlogServiceOp struct {
25+
client *Client
26+
}
27+
28+
// Blog represents a Shopify blog
29+
type Blog struct {
30+
ID int `json:"id"`
31+
Title string `json:"title"`
32+
Commentable string `json:"commentable"`
33+
Feedburner string `json:"feedburner"`
34+
FeedburnerLocation string `json:"feedburner_location"`
35+
Handle string `json:"handle"`
36+
Metafield Metafield `json:"metafield"`
37+
Tags string `json:"tags"`
38+
TemplateSuffix string `json:"template_suffix"`
39+
CreatedAt *time.Time `json:"created_at"`
40+
UpdatedAt *time.Time `json:"updated_at"`
41+
}
42+
43+
// BlogsResource is the result from the blogs.json endpoint
44+
type BlogsResource struct {
45+
Blogs []Blog `json:"blogs"`
46+
}
47+
48+
// Represents the result from the blogs/X.json endpoint
49+
type BlogResource struct {
50+
Blog *Blog `json:"blog"`
51+
}
52+
53+
// List all blogs
54+
func (s *BlogServiceOp) List(options interface{}) ([]Blog, error) {
55+
path := fmt.Sprintf("%s.json", blogsBasePath)
56+
resource := new(BlogsResource)
57+
err := s.client.Get(path, resource, options)
58+
return resource.Blogs, err
59+
}
60+
61+
// Count blogs
62+
func (s *BlogServiceOp) Count(options interface{}) (int, error) {
63+
path := fmt.Sprintf("%s/count.json", blogsBasePath)
64+
return s.client.Count(path, options)
65+
}
66+
67+
// Get single blog
68+
func (s *BlogServiceOp) Get(blogId int, options interface{}) (*Blog, error) {
69+
path := fmt.Sprintf("%s/%d.json", blogsBasePath, blogId)
70+
resource := new(BlogResource)
71+
err := s.client.Get(path, resource, options)
72+
return resource.Blog, err
73+
}
74+
75+
// Create a new blog
76+
func (s *BlogServiceOp) Create(blog Blog) (*Blog, error) {
77+
path := fmt.Sprintf("%s.json", blogsBasePath)
78+
wrappedData := BlogResource{Blog: &blog}
79+
resource := new(BlogResource)
80+
err := s.client.Post(path, wrappedData, resource)
81+
return resource.Blog, err
82+
}
83+
84+
// Update an existing blog
85+
func (s *BlogServiceOp) Update(blog Blog) (*Blog, error) {
86+
path := fmt.Sprintf("%s/%d.json", blogsBasePath, blog.ID)
87+
wrappedData := BlogResource{Blog: &blog}
88+
resource := new(BlogResource)
89+
err := s.client.Put(path, wrappedData, resource)
90+
return resource.Blog, err
91+
}
92+
93+
// Delete an blog
94+
func (s *BlogServiceOp) Delete(blogId int) error {
95+
return s.client.Delete(fmt.Sprintf("%s/%d.json", blogsBasePath, blogId))
96+
}

blog_test.go

+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
package goshopify
2+
3+
import (
4+
"reflect"
5+
"testing"
6+
7+
"gopkg.in/jarcoal/httpmock.v1"
8+
)
9+
10+
func TestBlogList(t *testing.T) {
11+
setup()
12+
defer teardown()
13+
14+
httpmock.RegisterResponder(
15+
"GET",
16+
"https://fooshop.myshopify.com/admin/blogs.json",
17+
httpmock.NewStringResponder(
18+
200,
19+
`{"blogs": [{"id":1},{"id":2}]}`,
20+
),
21+
)
22+
23+
blogs, err := client.Blog.List(nil)
24+
if err != nil {
25+
t.Errorf("Blog.List returned error: %v", err)
26+
}
27+
28+
expected := []Blog{{ID: 1}, {ID: 2}}
29+
if !reflect.DeepEqual(blogs, expected) {
30+
t.Errorf("Blog.List returned %+v, expected %+v", blogs, expected)
31+
}
32+
33+
}
34+
35+
func TestBlogCount(t *testing.T) {
36+
setup()
37+
defer teardown()
38+
39+
httpmock.RegisterResponder(
40+
"GET",
41+
"https://fooshop.myshopify.com/admin/blogs/count.json",
42+
httpmock.NewStringResponder(
43+
200,
44+
`{"count": 5}`,
45+
),
46+
)
47+
48+
cnt, err := client.Blog.Count(nil)
49+
if err != nil {
50+
t.Errorf("Blog.Count returned error: %v", err)
51+
}
52+
53+
expected := 5
54+
if cnt != expected {
55+
t.Errorf("Blog.Count returned %d, expected %d", cnt, expected)
56+
}
57+
58+
}
59+
60+
func TestBlogGet(t *testing.T) {
61+
setup()
62+
defer teardown()
63+
64+
httpmock.RegisterResponder(
65+
"GET",
66+
"https://fooshop.myshopify.com/admin/blogs/1.json",
67+
httpmock.NewStringResponder(
68+
200,
69+
`{"blog": {"id":1}}`,
70+
),
71+
)
72+
73+
blog, err := client.Blog.Get(1, nil)
74+
if err != nil {
75+
t.Errorf("Blog.Get returned error: %v", err)
76+
}
77+
78+
expected := &Blog{ID: 1}
79+
if !reflect.DeepEqual(blog, expected) {
80+
t.Errorf("Blog.Get returned %+v, expected %+v", blog, expected)
81+
}
82+
83+
}
84+
85+
func TestBlogCreate(t *testing.T) {
86+
setup()
87+
defer teardown()
88+
89+
httpmock.RegisterResponder(
90+
"POST",
91+
"https://fooshop.myshopify.com/admin/blogs.json",
92+
httpmock.NewBytesResponder(
93+
200,
94+
loadFixture("blog.json"),
95+
),
96+
)
97+
98+
blog := Blog{
99+
Title: "Mah Blog",
100+
}
101+
102+
returnedBlog, err := client.Blog.Create(blog)
103+
if err != nil {
104+
t.Errorf("Blog.Create returned error: %v", err)
105+
}
106+
107+
expectedInt := 241253187
108+
if returnedBlog.ID != expectedInt {
109+
t.Errorf("Blog.ID returned %+v, expected %+v", returnedBlog.ID, expectedInt)
110+
}
111+
112+
}
113+
114+
func TestBlogUpdate(t *testing.T) {
115+
setup()
116+
defer teardown()
117+
118+
httpmock.RegisterResponder(
119+
"PUT",
120+
"https://fooshop.myshopify.com/admin/blogs/1.json",
121+
httpmock.NewBytesResponder(
122+
200,
123+
loadFixture("blog.json"),
124+
),
125+
)
126+
127+
blog := Blog{
128+
ID: 1,
129+
Title: "Mah Blog",
130+
}
131+
132+
returnedBlog, err := client.Blog.Update(blog)
133+
if err != nil {
134+
t.Errorf("Blog.Update returned error: %v", err)
135+
}
136+
137+
expectedInt := 241253187
138+
if returnedBlog.ID != expectedInt {
139+
t.Errorf("Blog.ID returned %+v, expected %+v", returnedBlog.ID, expectedInt)
140+
}
141+
}
142+
143+
func TestBlogDelete(t *testing.T) {
144+
setup()
145+
defer teardown()
146+
147+
httpmock.RegisterResponder("DELETE", "https://fooshop.myshopify.com/admin/blogs/1.json",
148+
httpmock.NewStringResponder(200, "{}"))
149+
150+
err := client.Blog.Delete(1)
151+
if err != nil {
152+
t.Errorf("Blog.Delete returned error: %v", err)
153+
}
154+
}

fixtures/blog.json

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"blog": {
3+
"id": 241253187,
4+
"handle": "apple-blog",
5+
"title": "Mah Blog",
6+
"updated_at": "2006-02-01T19:00:00-05:00",
7+
"commentable": "no",
8+
"feedburner": null,
9+
"feedburner_location": null,
10+
"created_at": "2018-05-07T15:33:38-04:00",
11+
"template_suffix": null,
12+
"tags": "Announcing, Mystery"
13+
}
14+
}

goshopify.go

+2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ type Client struct {
6363
ScriptTag ScriptTagService
6464
RecurringApplicationCharge RecurringApplicationChargeService
6565
Metafield MetafieldService
66+
Blog BlogService
6667
}
6768

6869
// A general response error that follows a similar layout to Shopify's response
@@ -184,6 +185,7 @@ func NewClient(app App, shopName, token string) *Client {
184185
c.ScriptTag = &ScriptTagServiceOp{client: c}
185186
c.RecurringApplicationCharge = &RecurringApplicationChargeServiceOp{client: c}
186187
c.Metafield = &MetafieldServiceOp{client: c}
188+
c.Blog = &BlogServiceOp{client: c}
187189

188190
return c
189191
}

0 commit comments

Comments
 (0)