diff --git a/datadragon/data_dragon.go b/datadragon/data_dragon.go index 29cb858..64ddccd 100644 --- a/datadragon/data_dragon.go +++ b/datadragon/data_dragon.go @@ -52,7 +52,7 @@ type Client struct { Language languageCode client internal.Doer championsMu sync.RWMutex - championsByName map[string]ChampionDataExtended + championsById map[string]ChampionDataExtended getChampionsToggle uint32 profileIconsMu sync.RWMutex profileIcons []ProfileIcon @@ -69,9 +69,9 @@ type Client struct { // NewClient returns a new client for the Data Dragon service. func NewClient(client internal.Doer, region api.Region, logger log.FieldLogger) *Client { c := &Client{ - client: client, - logger: logger.WithField("client", "data dragon"), - championsByName: map[string]ChampionDataExtended{}, + client: client, + logger: logger.WithField("client", "data dragon"), + championsById: map[string]ChampionDataExtended{}, } if err := c.init(regionToRealmRegion[region]); err != nil { c.Version = fallbackVersion @@ -112,11 +112,11 @@ func (c *Client) GetChampions() ([]ChampionData, error) { } for _, champion := range champions { data := ChampionDataExtended{ChampionData: champion} - c.championsByName[champion.Name] = data + c.championsById[champion.ID] = data } } - res := make([]ChampionData, 0, len(c.championsByName)) - for _, champion := range c.championsByName { + res := make([]ChampionData, 0, len(c.championsById)) + for _, champion := range c.championsById { res = append(res, champion.ChampionData) } return res, nil @@ -124,38 +124,38 @@ func (c *Client) GetChampions() ([]ChampionData, error) { // GetChampionByID returns information about the champion with the given id func (c *Client) GetChampionByID(id string) (ChampionDataExtended, error) { - champions, err := c.GetChampions() - if err != nil { - return ChampionDataExtended{}, err - } - for _, champion := range champions { - if champion.Key == id { - return c.GetChampion(champion.Name) - } - } - return ChampionDataExtended{}, api.ErrNotFound -} - -// GetChampion returns information about the champion with the given name -func (c *Client) GetChampion(name string) (ChampionDataExtended, error) { unlock, toggle := internal.RWLockToggle(&c.championsMu) defer unlock() - champion, ok := c.championsByName[name] + champion, ok := c.championsById[id] if !ok || champion.Lore == "" { toggle() var data map[string]ChampionDataExtended - if err := c.getInto(fmt.Sprintf("/champion/%s.json", name), &data); err != nil { + if err := c.getInto(fmt.Sprintf("/champion/%s.json", id), &data); err != nil { return ChampionDataExtended{}, err } - champion, ok = data[name] + champion, ok = data[id] if !ok { return ChampionDataExtended{}, api.ErrNotFound } - c.championsByName[name] = champion + c.championsById[id] = champion } return champion, nil } +// GetChampion returns information about the champion with the given name +func (c *Client) GetChampion(name string) (ChampionDataExtended, error) { + champions, err := c.GetChampions() + if err != nil { + return ChampionDataExtended{}, err + } + for _, champion := range champions { + if champion.Name == name { + return c.GetChampionByID(champion.ID) + } + } + return ChampionDataExtended{}, api.ErrNotFound +} + // GetProfileIcons returns all existing profile icons func (c *Client) GetProfileIcons() ([]ProfileIcon, error) { unlock, toggle := internal.RWLockToggle(&c.profileIconsMu) @@ -333,7 +333,7 @@ func (c *Client) GetSummonerSpell(id string) (SummonerSpell, error) { // ClearCaches resets all caches of the data dragon client func (c *Client) ClearCaches() { c.championsMu.Lock() - c.championsByName = map[string]ChampionDataExtended{} + c.championsById = map[string]ChampionDataExtended{} atomic.StoreUint32(&c.getChampionsToggle, 0) c.championsMu.Unlock() c.masteriesMu.Lock() diff --git a/datadragon/data_dragon_test.go b/datadragon/data_dragon_test.go index a9fe3ee..d5114f4 100644 --- a/datadragon/data_dragon_test.go +++ b/datadragon/data_dragon_test.go @@ -78,12 +78,42 @@ func TestClient_GetChampion(t *testing.T) { }{ { name: "get response", - doer: dataDragonResponseDoer( - map[string]ChampionDataExtended{ - "champion": {}, + doer: mock.NewPathJSONMockDoer( + []mock.PathJSONResponse{ + { + PathSuffix: "/champion.json", + Object: dataDragonResponse{ + Data: map[string]ChampionData{ + "champion-id": { + ID: "champion-id", + Name: "champion-name", + }, + }, + }, + Code: 200, + }, + { + PathSuffix: "/champion/champion-id.json", + Object: dataDragonResponse{ + Data: map[string]ChampionDataExtended{ + "champion-id": { + ChampionData: ChampionData{ + ID: "champion-id", + Name: "champion-name", + }, + }, + }, + }, + Code: 200, + }, }, ), - want: ChampionDataExtended{}, + want: ChampionDataExtended{ + ChampionData: ChampionData{ + ID: "champion-id", + Name: "champion-name", + }, + }, }, { name: "not found", @@ -108,11 +138,11 @@ func TestClient_GetChampion(t *testing.T) { t.Run( tt.name, func(t *testing.T) { c := NewClient(tt.doer, api.RegionEuropeWest, log.StandardLogger()) - got, err := c.GetChampion("champion") + got, err := c.GetChampion("champion-name") assert.Equal(t, tt.wantErr, err) if tt.wantErr == nil { assert.Equal(t, tt.want, got) - got, err := c.GetChampion("champion") + got, err := c.GetChampion("champion-name") assert.Nil(t, err) assert.Equal(t, tt.want, got) } @@ -380,11 +410,17 @@ func TestClient_GetChampionByID(t *testing.T) { name: "get response", doer: dataDragonResponseDoer( map[string]ChampionData{ - "champion": {Name: "champion", Key: "id"}, + "champion-id": {ID: "champion-id", Name: "champion-name", Key: "champion-id"}, }, ), - id: "id", - want: ChampionDataExtended{ChampionData: ChampionData{Name: "champion", Key: "id"}}, + id: "champion-id", + want: ChampionDataExtended{ + ChampionData: ChampionData{ + ID: "champion-id", + Name: "champion-name", + Key: "champion-id", + }, + }, }, { name: "not found", diff --git a/datadragon/model_test.go b/datadragon/model_test.go index d0cb7d9..5f9b79f 100644 --- a/datadragon/model_test.go +++ b/datadragon/model_test.go @@ -8,6 +8,7 @@ import ( "github.com/KnutZuidema/golio/api" "github.com/KnutZuidema/golio/internal" + "github.com/KnutZuidema/golio/internal/mock" ) func TestChampionData_GetExtended(t *testing.T) { @@ -21,13 +22,38 @@ func TestChampionData_GetExtended(t *testing.T) { tests := []test{ { name: "valid", - doer: dataDragonResponseDoer( - map[string]*ChampionDataExtended{ - "champion": {ChampionData: ChampionData{Name: "champion"}}, + doer: mock.NewPathJSONMockDoer( + []mock.PathJSONResponse{ + { + PathSuffix: "/champion.json", + Object: dataDragonResponse{ + Data: map[string]ChampionData{ + "champion-id": { + ID: "champion-id", + Name: "champion-name", + }, + }, + }, + Code: 200, + }, + { + PathSuffix: "/champion/champion-id.json", + Object: dataDragonResponse{ + Data: map[string]ChampionDataExtended{ + "champion-id": { + ChampionData: ChampionData{ + ID: "champion-id", + Name: "champion-name", + }, + }, + }, + }, + Code: 200, + }, }, ), - data: &ChampionData{Name: "champion"}, - want: ChampionDataExtended{ChampionData: ChampionData{Name: "champion"}}, + data: &ChampionData{ID: "champion-id", Name: "champion-name"}, + want: ChampionDataExtended{ChampionData: ChampionData{ID: "champion-id", Name: "champion-name"}}, }, } for _, test := range tests { diff --git a/internal/mock/mock_doer.go b/internal/mock/mock_doer.go index be55e09..6177ee7 100644 --- a/internal/mock/mock_doer.go +++ b/internal/mock/mock_doer.go @@ -2,8 +2,10 @@ package mock import ( "encoding/json" + "errors" "fmt" "net/http" + "strings" "time" ) @@ -32,6 +34,35 @@ func NewJSONMockDoer(object interface{}, code int) *Doer { } } +type PathJSONResponse struct { + PathSuffix string + Object interface{} + Code int +} + +// NewPathJSONMockDoer constructs a new MockDoer with the json representation of an +// object as body and the given status code for the given path(s) +// CAUTION: silently returns an empty response if object is fails json marshaling +func NewPathJSONMockDoer(pathResponses []PathJSONResponse) *Doer { + return &Doer{ + Custom: func(r *http.Request) (*http.Response, error) { + for _, pathResponse := range pathResponses { + if strings.HasSuffix(r.URL.Path, pathResponse.PathSuffix) { + buffer, _ := json.Marshal(pathResponse.Object) + body := ResponseBody{ + Content: buffer, + } + return &http.Response{ + Body: &body, + StatusCode: pathResponse.Code, + }, nil + } + } + return nil, errors.New("not found") + }, + } +} + // NewStatusMockDoer constructs a new MockDoer with the given status code func NewStatusMockDoer(code int) *Doer { return &Doer{ diff --git a/riot/lol/model_test.go b/riot/lol/model_test.go index 00ef941..6871f4e 100644 --- a/riot/lol/model_test.go +++ b/riot/lol/model_test.go @@ -62,16 +62,16 @@ func TestChampionInfo_GetChampionsForNewPlayers(t *testing.T) { name: "valid", doer: dataDragonResponseDoer( map[string]datadragon.ChampionData{ - "champion1": {Key: "1", Name: "champion1"}, - "champion2": {Key: "2", Name: "champion2"}, + "1": {Key: "1", ID: "1", Name: "champion1"}, + "2": {Key: "2", ID: "2", Name: "champion2"}, }, ), model: ChampionInfo{ FreeChampionIDsForNewPlayers: []int{1, 2}, }, want: []datadragon.ChampionDataExtended{ - {ChampionData: datadragon.ChampionData{Name: "champion1", Key: "1"}}, - {ChampionData: datadragon.ChampionData{Name: "champion2", Key: "2"}}, + {ChampionData: datadragon.ChampionData{ID: "1", Name: "champion1", Key: "1"}}, + {ChampionData: datadragon.ChampionData{ID: "2", Name: "champion2", Key: "2"}}, }, }, { @@ -111,16 +111,16 @@ func TestChampionInfo_GetChampions(t *testing.T) { name: "valid", doer: dataDragonResponseDoer( map[string]datadragon.ChampionData{ - "champion1": {Key: "1", Name: "champion1"}, - "champion2": {Key: "2", Name: "champion2"}, + "1": {Key: "1", ID: "1", Name: "champion1"}, + "2": {Key: "2", ID: "2", Name: "champion2"}, }, ), model: ChampionInfo{ FreeChampionIDs: []int{1, 2}, }, want: []datadragon.ChampionDataExtended{ - {ChampionData: datadragon.ChampionData{Name: "champion1", Key: "1"}}, - {ChampionData: datadragon.ChampionData{Name: "champion2", Key: "2"}}, + {ChampionData: datadragon.ChampionData{ID: "1", Name: "champion1", Key: "1"}}, + {ChampionData: datadragon.ChampionData{ID: "2", Name: "champion2", Key: "2"}}, }, }, { @@ -188,11 +188,13 @@ func TestChampionMastery_GetChampion(t *testing.T) { name: "valid", doer: dataDragonResponseDoer( map[string]datadragon.ChampionData{ - "champion": {Name: "champion", Key: "1"}, + "1": {Key: "1", ID: "1", Name: "champion"}, }, ), model: ChampionMastery{ChampionID: 1}, - want: datadragon.ChampionDataExtended{ChampionData: datadragon.ChampionData{Name: "champion", Key: "1"}}, + want: datadragon.ChampionDataExtended{ + ChampionData: datadragon.ChampionData{ID: "1", Name: "champion", Key: "1"}, + }, }, } for _, test := range tests { @@ -420,11 +422,13 @@ func TestTeamBan_GetChampion(t *testing.T) { name: "valid", doer: dataDragonResponseDoer( map[string]datadragon.ChampionData{ - "champion": {Name: "champion", Key: "1"}, + "1": {Key: "1", ID: "1", Name: "champion"}, }, ), model: TeamBan{ChampionID: 1}, - want: datadragon.ChampionDataExtended{ChampionData: datadragon.ChampionData{Name: "champion", Key: "1"}}, + want: datadragon.ChampionDataExtended{ + ChampionData: datadragon.ChampionData{ID: "1", Name: "champion", Key: "1"}, + }, }, } for _, test := range tests { @@ -452,11 +456,13 @@ func TestParticipant_GetChampion(t *testing.T) { name: "valid", doer: dataDragonResponseDoer( map[string]datadragon.ChampionData{ - "champion": {Name: "champion", Key: "1"}, + "1": {Key: "1", ID: "1", Name: "champion"}, }, ), model: Participant{ChampionID: 1}, - want: datadragon.ChampionDataExtended{ChampionData: datadragon.ChampionData{Name: "champion", Key: "1"}}, + want: datadragon.ChampionDataExtended{ + ChampionData: datadragon.ChampionData{ID: "1", Name: "champion", Key: "1"}, + }, }, } for _, test := range tests { @@ -772,11 +778,13 @@ func TestBannedChampion_GetChampion(t *testing.T) { name: "valid", doer: dataDragonResponseDoer( map[string]datadragon.ChampionData{ - "champion": {Name: "champion", Key: "1"}, + "1": {Key: "1", ID: "1", Name: "champion"}, }, ), model: BannedChampion{ChampionID: 1}, - want: datadragon.ChampionDataExtended{ChampionData: datadragon.ChampionData{Name: "champion", Key: "1"}}, + want: datadragon.ChampionDataExtended{ + ChampionData: datadragon.ChampionData{ID: "1", Name: "champion", Key: "1"}, + }, }, } for _, test := range tests { @@ -804,11 +812,13 @@ func TestCurrentGameParticipant_GetChampion(t *testing.T) { name: "valid", doer: dataDragonResponseDoer( map[string]datadragon.ChampionData{ - "champion": {Name: "champion", Key: "1"}, + "1": {Key: "1", ID: "1", Name: "champion"}, }, ), model: CurrentGameParticipant{ChampionID: 1}, - want: datadragon.ChampionDataExtended{ChampionData: datadragon.ChampionData{Name: "champion", Key: "1"}}, + want: datadragon.ChampionDataExtended{ + ChampionData: datadragon.ChampionData{ID: "1", Name: "champion", Key: "1"}, + }, }, } for _, test := range tests {