-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Henry-Sarabia
committed
Mar 1, 2019
1 parent
fabe4df
commit 73fd22d
Showing
5 changed files
with
359 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package igdb | ||
|
||
import ( | ||
"github.com/Henry-Sarabia/sliceconv" | ||
"github.com/pkg/errors" | ||
"strconv" | ||
) | ||
|
||
//go:generate gomodifytags -file $GOFILE -struct PulseURL -add-tags json -w | ||
|
||
// PulseURL represents a URL linking to an article. | ||
// For more information visit: https://api-docs.igdb.com/#pulse-url | ||
type PulseURL struct { | ||
ID int `json:"id"` | ||
Trusted bool `json:"trusted"` | ||
URL string `json:"url"` | ||
} | ||
|
||
// PulseURLService handles all the API | ||
// calls for the IGDB PulseURL endpoint. | ||
type PulseURLService service | ||
|
||
// Get returns a single PulseURL identified by the provided IGDB ID. Provide | ||
// the SetFields functional option if you need to specify which fields to | ||
// retrieve. If the ID does not match any PulseURLs, an error is returned. | ||
func (ps *PulseURLService) Get(id int, opts ...Option) (*PulseURL, error) { | ||
if id < 0 { | ||
return nil, ErrNegativeID | ||
} | ||
|
||
var URL []*PulseURL | ||
|
||
opts = append(opts, SetFilter("id", OpEquals, strconv.Itoa(id))) | ||
err := ps.client.get(ps.end, &URL, opts...) | ||
if err != nil { | ||
return nil, errors.Wrapf(err, "cannot get PulseURL with ID %v", id) | ||
} | ||
|
||
return URL[0], nil | ||
} | ||
|
||
// List returns a list of PulseURLs identified by the provided list of IGDB IDs. | ||
// Provide functional options to sort, filter, and paginate the results. | ||
// Any ID that does not match a PulseURL is ignored. If none of the IDs | ||
// match a PulseURL, an error is returned. | ||
func (ps *PulseURLService) List(ids []int, opts ...Option) ([]*PulseURL, error) { | ||
for len(ids) < 1 { | ||
return nil, ErrEmptyIDs | ||
} | ||
|
||
for _, id := range ids { | ||
if id < 0 { | ||
return nil, ErrNegativeID | ||
} | ||
} | ||
|
||
var URL []*PulseURL | ||
|
||
opts = append(opts, SetFilter("id", OpContainsAtLeast, sliceconv.Itoa(ids)...)) | ||
err := ps.client.get(ps.end, &URL, opts...) | ||
if err != nil { | ||
return nil, errors.Wrapf(err, "cannot get PulseURLs with IDs %v", ids) | ||
} | ||
|
||
return URL, nil | ||
} | ||
|
||
// Index returns an index of PulseURLs based solely on the provided functional | ||
// options used to sort, filter, and paginate the results. If no PulseURLs can | ||
// be found using the provided options, an error is returned. | ||
func (ps *PulseURLService) Index(opts ...Option) ([]*PulseURL, error) { | ||
var URL []*PulseURL | ||
|
||
err := ps.client.get(ps.end, &URL, opts...) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "cannot get index of PulseURLs") | ||
} | ||
|
||
return URL, nil | ||
} | ||
|
||
// Search returns a list of PulseURLs found by searching the IGDB using the provided | ||
// query. Provide functional options to sort, filter, and paginate the results. If | ||
// no PulseURLs are found using the provided query, an error is returned. | ||
func (ps *PulseURLService) Search(qry string, opts ...Option) ([]*PulseURL, error) { | ||
var URL []*PulseURL | ||
|
||
opts = append(opts, setSearch(qry)) | ||
err := ps.client.get(ps.end, &URL, opts...) | ||
if err != nil { | ||
return nil, errors.Wrapf(err, "cannot get PulseURL with query %s", qry) | ||
} | ||
|
||
return URL, nil | ||
} | ||
|
||
// Count returns the number of PulseURLs available in the IGDB. | ||
// Provide the SetFilter functional option if you need to filter | ||
// which PulseURLs to count. | ||
func (ps *PulseURLService) Count(opts ...Option) (int, error) { | ||
ct, err := ps.client.getCount(ps.end, opts...) | ||
if err != nil { | ||
return 0, errors.Wrap(err, "cannot count PulseURLs") | ||
} | ||
|
||
return ct, nil | ||
} | ||
|
||
// Fields returns the up-to-date list of fields in an | ||
// IGDB PulseURL object. | ||
func (ps *PulseURLService) Fields() ([]string, error) { | ||
f, err := ps.client.getFields(ps.end) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "cannot get PulseURL fields") | ||
} | ||
|
||
return f, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
package igdb | ||
|
||
import ( | ||
"encoding/json" | ||
"github.com/pkg/errors" | ||
"io/ioutil" | ||
"net/http" | ||
"reflect" | ||
"testing" | ||
) | ||
|
||
const ( | ||
testPulseURLGet string = "test_data/pulseurl_get.json" | ||
testPulseURLList string = "test_data/pulseurl_list.json" | ||
) | ||
|
||
func TestPulseURLService_Get(t *testing.T) { | ||
f, err := ioutil.ReadFile(testPulseURLGet) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
init := make([]*PulseURL, 1) | ||
json.Unmarshal(f, &init) | ||
|
||
var tests = []struct { | ||
name string | ||
file string | ||
id int | ||
opts []Option | ||
wantPulseURL *PulseURL | ||
wantErr error | ||
}{ | ||
{"Valid response", testPulseURLGet, 105759, []Option{SetFields("name")}, init[0], nil}, | ||
{"Invalid ID", testFileEmpty, -1, nil, nil, ErrNegativeID}, | ||
{"Empty response", testFileEmpty, 105759, nil, nil, errInvalidJSON}, | ||
{"Invalid option", testFileEmpty, 105759, []Option{SetOffset(-99999)}, nil, ErrOutOfRange}, | ||
{"No results", testFileEmptyArray, 0, nil, nil, ErrNoResults}, | ||
} | ||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
ts, c, err := testServerFile(http.StatusOK, test.file) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
defer ts.Close() | ||
|
||
URL, err := c.PulseURLs.Get(test.id, test.opts...) | ||
if errors.Cause(err) != test.wantErr { | ||
t.Errorf("got: <%v>, want: <%v>", errors.Cause(err), test.wantErr) | ||
} | ||
|
||
if !reflect.DeepEqual(URL, test.wantPulseURL) { | ||
t.Errorf("got: <%v>, \nwant: <%v>", URL, test.wantPulseURL) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestPulseURLService_List(t *testing.T) { | ||
f, err := ioutil.ReadFile(testPulseURLList) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
init := make([]*PulseURL, 0) | ||
json.Unmarshal(f, &init) | ||
|
||
var tests = []struct { | ||
name string | ||
file string | ||
ids []int | ||
opts []Option | ||
wantPulseURLs []*PulseURL | ||
wantErr error | ||
}{ | ||
{"Valid response", testPulseURLList, []int{105784, 105904, 105984, 92066, 70576}, []Option{SetLimit(5)}, init, nil}, | ||
{"Zero IDs", testFileEmpty, nil, nil, nil, ErrEmptyIDs}, | ||
{"Invalid ID", testFileEmpty, []int{-500}, nil, nil, ErrNegativeID}, | ||
{"Empty response", testFileEmpty, []int{105784, 105904, 105984, 92066, 70576}, nil, nil, errInvalidJSON}, | ||
{"Invalid option", testFileEmpty, []int{105784, 105904, 105984, 92066, 70576}, []Option{SetOffset(-99999)}, nil, ErrOutOfRange}, | ||
{"No results", testFileEmptyArray, []int{0, 9999999}, nil, nil, ErrNoResults}, | ||
} | ||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
ts, c, err := testServerFile(http.StatusOK, test.file) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
defer ts.Close() | ||
|
||
URL, err := c.PulseURLs.List(test.ids, test.opts...) | ||
if errors.Cause(err) != test.wantErr { | ||
t.Errorf("got: <%v>, want: <%v>", errors.Cause(err), test.wantErr) | ||
} | ||
|
||
if !reflect.DeepEqual(URL, test.wantPulseURLs) { | ||
t.Errorf("got: <%v>, \nwant: <%v>", URL, test.wantPulseURLs) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestPulseURLService_Index(t *testing.T) { | ||
f, err := ioutil.ReadFile(testPulseURLList) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
init := make([]*PulseURL, 0) | ||
json.Unmarshal(f, &init) | ||
|
||
tests := []struct { | ||
name string | ||
file string | ||
opts []Option | ||
wantPulseURLs []*PulseURL | ||
wantErr error | ||
}{ | ||
{"Valid response", testPulseURLList, []Option{SetLimit(5)}, init, nil}, | ||
{"Empty response", testFileEmpty, nil, nil, errInvalidJSON}, | ||
{"Invalid option", testFileEmpty, []Option{SetOffset(-99999)}, nil, ErrOutOfRange}, | ||
{"No results", testFileEmptyArray, nil, nil, ErrNoResults}, | ||
} | ||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
ts, c, err := testServerFile(http.StatusOK, test.file) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
defer ts.Close() | ||
|
||
URL, err := c.PulseURLs.Index(test.opts...) | ||
if errors.Cause(err) != test.wantErr { | ||
t.Errorf("got: <%v>, want: <%v>", errors.Cause(err), test.wantErr) | ||
} | ||
|
||
if !reflect.DeepEqual(URL, test.wantPulseURLs) { | ||
t.Errorf("got: <%v>, \nwant: <%v>", URL, test.wantPulseURLs) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestPulseURLService_Count(t *testing.T) { | ||
var tests = []struct { | ||
name string | ||
resp string | ||
opts []Option | ||
wantCount int | ||
wantErr error | ||
}{ | ||
{"Happy path", `{"count": 100}`, []Option{SetFilter("popularity", OpGreaterThan, "75")}, 100, nil}, | ||
{"Empty response", "", nil, 0, errInvalidJSON}, | ||
{"Invalid option", "", []Option{SetLimit(-100)}, 0, ErrOutOfRange}, | ||
{"No results", "[]", nil, 0, ErrNoResults}, | ||
} | ||
|
||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
ts, c := testServerString(http.StatusOK, test.resp) | ||
defer ts.Close() | ||
|
||
count, err := c.PulseURLs.Count(test.opts...) | ||
if errors.Cause(err) != test.wantErr { | ||
t.Errorf("got: <%v>, want: <%v>", errors.Cause(err), test.wantErr) | ||
} | ||
|
||
if count != test.wantCount { | ||
t.Fatalf("got: <%v>, want: <%v>", count, test.wantCount) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestPulseURLService_Fields(t *testing.T) { | ||
var tests = []struct { | ||
name string | ||
resp string | ||
wantFields []string | ||
wantErr error | ||
}{ | ||
{"Happy path", `["name", "slug", "url"]`, []string{"url", "slug", "name"}, nil}, | ||
{"Dot operator", `["logo.url", "background.id"]`, []string{"background.id", "logo.url"}, nil}, | ||
{"Asterisk", `["*"]`, []string{"*"}, nil}, | ||
{"Empty response", "", nil, errInvalidJSON}, | ||
{"No results", "[]", nil, nil}, | ||
} | ||
|
||
for _, test := range tests { | ||
t.Run(test.name, func(t *testing.T) { | ||
ts, c := testServerString(http.StatusOK, test.resp) | ||
defer ts.Close() | ||
|
||
fields, err := c.PulseURLs.Fields() | ||
if errors.Cause(err) != test.wantErr { | ||
t.Errorf("got: <%v>, want: <%v>", errors.Cause(err), test.wantErr) | ||
} | ||
|
||
if !equalSlice(fields, test.wantFields) { | ||
t.Fatalf("Expected fields '%v', got '%v'", test.wantFields, fields) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[ | ||
{ | ||
"id": 105759, | ||
"trusted": false, | ||
"url": "http://shoryuken.com/2017/10/30/the-latest-beta-version-of-fightcade-goes-live-for-accounts-from-2015-and-older/" | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
[ | ||
{ | ||
"id": 105784, | ||
"trusted": false, | ||
"url": "http://www.criticalhit.net/gaming/you-can-play-the-whole-of-far-cry-5-in-co-op/" | ||
}, | ||
{ | ||
"id": 105904, | ||
"trusted": false, | ||
"url": "http://www.pcgamer.com/the-elder-scrolls-legends-is-getting-a-clockwork-city-expansion" | ||
}, | ||
{ | ||
"id": 105984, | ||
"trusted": false, | ||
"url": "http://shoryuken.com/2017/10/31/dante-shows-some-bold-moves-in-this-new-marvel-vs-capcom-infinite-combo-video/" | ||
}, | ||
{ | ||
"id": 92066, | ||
"trusted": false, | ||
"url": "http://gamingbolt.com/saints-row-the-third-is-now-playable-on-xbox-one-via-backward-compatibility" | ||
}, | ||
{ | ||
"id": 70576, | ||
"trusted": false, | ||
"url": "http://www.gamepur.com/news/27082-zelda-master-trials.html" | ||
} | ||
] |