github.com/line/line-bot-sdk-go/v7@v7.21.0/linebot/richmenu_test.go (about)

     1  // Copyright 2016 LINE Corporation
     2  //
     3  // LINE Corporation licenses this file to you under the Apache License,
     4  // version 2.0 (the "License"); you may not use this file except in compliance
     5  // with the License. You may obtain a copy of the License at:
     6  //
     7  //   http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    11  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    12  // License for the specific language governing permissions and limitations
    13  // under the License.
    14  
    15  package linebot
    16  
    17  import (
    18  	"bytes"
    19  	"fmt"
    20  	"io"
    21  	"net/http"
    22  	"net/http/httptest"
    23  	"os"
    24  	"path/filepath"
    25  	"reflect"
    26  	"strconv"
    27  	"testing"
    28  )
    29  
    30  // TestGetRichMenu tests GetRichMenu, GetUserRichMenu
    31  func TestGetRichMenu(t *testing.T) {
    32  	type want struct {
    33  		URLPath     string
    34  		RequestBody []byte
    35  		Response    *RichMenuResponse
    36  		Error       error
    37  	}
    38  	testCases := []struct {
    39  		Label        string
    40  		UserID       string
    41  		RichMenuID   string
    42  		ResponseCode int
    43  		Response     []byte
    44  		Want         want
    45  	}{
    46  		{
    47  			Label:        "Without UserID",
    48  			RichMenuID:   "123456",
    49  			ResponseCode: 200,
    50  			Response:     []byte(`{"richMenuId":"123456","size":{"width":2500,"height":1686},"selected":false,"areas":[{"bounds":{"x":0,"y":0,"width":2500,"height":1686},"action":{"type":"postback","data":"action=buy&itemid=123"}}]}`),
    51  			Want: want{
    52  				URLPath: fmt.Sprintf(APIEndpointGetRichMenu, "123456"),
    53  				Response: &RichMenuResponse{
    54  					RichMenuID:  "123456",
    55  					Size:        RichMenuSize{Width: 2500, Height: 1686},
    56  					Selected:    false,
    57  					ChatBarText: "",
    58  					Areas: []AreaDetail{
    59  						{
    60  							Bounds: RichMenuBounds{X: 0, Y: 0, Width: 2500, Height: 1686},
    61  							Action: RichMenuAction{Type: RichMenuActionTypePostback, Data: "action=buy&itemid=123"},
    62  						},
    63  					},
    64  				},
    65  			},
    66  		},
    67  		{
    68  			Label:        "With UserID",
    69  			RichMenuID:   "654321",
    70  			UserID:       "user1",
    71  			ResponseCode: 200,
    72  			Response:     []byte(`{"richMenuId":"654321","size":{"width":2500,"height":1686},"selected":false,"areas":[{"bounds":{"x":0,"y":0,"width":2500,"height":1686},"action":{"type":"postback","data":"action=buy&itemid=123"}}]}`),
    73  			Want: want{
    74  				URLPath: fmt.Sprintf(APIEndpointGetUserRichMenu, "user1"),
    75  				Response: &RichMenuResponse{
    76  					RichMenuID:  "654321",
    77  					Size:        RichMenuSize{Width: 2500, Height: 1686},
    78  					Selected:    false,
    79  					ChatBarText: "",
    80  					Areas: []AreaDetail{
    81  						{
    82  							Bounds: RichMenuBounds{X: 0, Y: 0, Width: 2500, Height: 1686},
    83  							Action: RichMenuAction{Type: RichMenuActionTypePostback, Data: "action=buy&itemid=123"},
    84  						},
    85  					},
    86  				},
    87  			},
    88  		},
    89  	}
    90  
    91  	var currentTestIdx int
    92  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    93  		defer r.Body.Close()
    94  		tc := testCases[currentTestIdx]
    95  		if r.Method != http.MethodGet {
    96  			t.Errorf("Method %s; want %s", r.Method, http.MethodGet)
    97  		}
    98  		if r.URL.Path != tc.Want.URLPath {
    99  			t.Errorf("URLPath %s; want %s", r.URL.Path, tc.Want.URLPath)
   100  		}
   101  		_, err := io.ReadAll(r.Body)
   102  		if err != nil {
   103  			t.Fatal(err)
   104  		}
   105  		w.WriteHeader(tc.ResponseCode)
   106  		w.Write(tc.Response)
   107  	}))
   108  	defer server.Close()
   109  
   110  	dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   111  		defer r.Body.Close()
   112  		t.Error("Unexpected data API call")
   113  		w.WriteHeader(404)
   114  		w.Write([]byte(`{"message":"Not found"}`))
   115  	}))
   116  	defer dataServer.Close()
   117  
   118  	client, err := mockClient(server, dataServer)
   119  	if err != nil {
   120  		t.Fatal(err)
   121  	}
   122  
   123  	var res *RichMenuResponse
   124  	for i, tc := range testCases {
   125  		currentTestIdx = i
   126  		t.Run(strconv.Itoa(i)+"/"+tc.Label, func(t *testing.T) {
   127  			if tc.UserID != "" { // test get user
   128  				res, err = client.GetUserRichMenu(tc.UserID).Do()
   129  			} else {
   130  				res, err = client.GetRichMenu(tc.RichMenuID).Do()
   131  			}
   132  			if tc.Want.Error != nil {
   133  				if !reflect.DeepEqual(err, tc.Want.Error) {
   134  					t.Errorf("Error %v; want %v", err, tc.Want.Error)
   135  				}
   136  			} else {
   137  				if err != nil {
   138  					t.Error(err)
   139  				}
   140  			}
   141  			if tc.Want.Response != nil {
   142  				if !reflect.DeepEqual(res, tc.Want.Response) {
   143  					t.Errorf("Response %v; want %v", res, tc.Want.Response)
   144  				}
   145  			}
   146  		})
   147  	}
   148  }
   149  
   150  func TestCreateRichMenu(t *testing.T) {
   151  	type want struct {
   152  		RequestBody []byte
   153  		Response    *RichMenuIDResponse
   154  		Error       error
   155  	}
   156  	testCases := []struct {
   157  		Request      RichMenu
   158  		Response     []byte
   159  		ResponseCode int
   160  		Want         want
   161  	}{
   162  		{
   163  			Request: RichMenu{
   164  				Size:        RichMenuSize{Width: 2500, Height: 1686},
   165  				Selected:    false,
   166  				Name:        "Menu1",
   167  				ChatBarText: "ChatText",
   168  				Areas: []AreaDetail{
   169  					{
   170  						Bounds: RichMenuBounds{X: 0, Y: 0, Width: 2500, Height: 1686},
   171  						Action: RichMenuAction{Type: RichMenuActionTypePostback, Data: "action=buy&itemid=123", DisplayText: "Buy", Label: "Buy"},
   172  					},
   173  				},
   174  			},
   175  			ResponseCode: 200,
   176  			Response:     []byte(`{"richMenuId":"abcefg"}`),
   177  			Want: want{
   178  				RequestBody: []byte(`{"size":{"width":2500,"height":1686},"selected":false,"name":"Menu1","chatBarText":"ChatText","areas":[{"bounds":{"x":0,"y":0,"width":2500,"height":1686},"action":{"type":"postback","displayText":"Buy","label":"Buy","data":"action=buy\u0026itemid=123"}}]}` + "\n"),
   179  				Response:    &RichMenuIDResponse{RichMenuID: "abcefg"},
   180  			},
   181  		},
   182  	}
   183  
   184  	var currentTestIdx int
   185  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   186  		defer r.Body.Close()
   187  		tc := testCases[currentTestIdx]
   188  		if r.Method != http.MethodPost {
   189  			t.Errorf("Method %s; want %s", r.Method, http.MethodPost)
   190  		}
   191  		if r.URL.Path != APIEndpointCreateRichMenu {
   192  			t.Errorf("URLPath %s; want %s", r.URL.Path, APIEndpointCreateRichMenu)
   193  		}
   194  		body, err := io.ReadAll(r.Body)
   195  		if err != nil {
   196  			t.Fatal(err)
   197  		}
   198  		if !reflect.DeepEqual(body, tc.Want.RequestBody) {
   199  			t.Errorf("RequestBody\n %s; want\n %s", body, tc.Want.RequestBody)
   200  		}
   201  		w.WriteHeader(tc.ResponseCode)
   202  		w.Write(tc.Response)
   203  	}))
   204  	defer server.Close()
   205  
   206  	dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   207  		defer r.Body.Close()
   208  		t.Error("Unexpected data API call")
   209  		w.WriteHeader(404)
   210  		w.Write([]byte(`{"message":"Not found"}`))
   211  	}))
   212  	defer dataServer.Close()
   213  
   214  	client, err := mockClient(server, dataServer)
   215  	if err != nil {
   216  		t.Fatal(err)
   217  	}
   218  	for i, tc := range testCases {
   219  		currentTestIdx = i
   220  		t.Run(strconv.Itoa(i), func(t *testing.T) {
   221  			res, err := client.CreateRichMenu(tc.Request).Do()
   222  			if tc.Want.Error != nil {
   223  				if !reflect.DeepEqual(err, tc.Want.Error) {
   224  					t.Errorf("Error %v; want %v", err, tc.Want.Error)
   225  				}
   226  			} else {
   227  				if err != nil {
   228  					t.Error(err)
   229  				}
   230  			}
   231  			if tc.Want.Response != nil {
   232  				if !reflect.DeepEqual(res, tc.Want.Response) {
   233  					t.Errorf("Response %v; want %v", res, tc.Want.Response)
   234  				}
   235  			}
   236  		})
   237  	}
   238  }
   239  
   240  // TestLinkRichMenu tests LinkUserRichMenu
   241  func TestLinkRichMenu(t *testing.T) {
   242  	type want struct {
   243  		URLPath     string
   244  		RequestBody []byte
   245  		Response    *BasicResponse
   246  		Error       error
   247  	}
   248  	testCases := []struct {
   249  		RichMenuID   string
   250  		UserID       string
   251  		ResponseCode int
   252  		Response     []byte
   253  		Want         want
   254  	}{
   255  		{
   256  			RichMenuID:   "654321",
   257  			UserID:       "userId1",
   258  			ResponseCode: 200,
   259  			Response:     []byte(`{}`),
   260  			Want: want{
   261  				URLPath:  fmt.Sprintf(APIEndpointLinkUserRichMenu, "userId1", "654321"),
   262  				Response: &BasicResponse{},
   263  			},
   264  		},
   265  	}
   266  
   267  	var currentTestIdx int
   268  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   269  		defer r.Body.Close()
   270  		tc := testCases[currentTestIdx]
   271  		if r.Method != http.MethodPost {
   272  			t.Errorf("Method %s; want %s", r.Method, http.MethodGet)
   273  		}
   274  		if r.URL.Path != tc.Want.URLPath {
   275  			t.Errorf("URLPath %s; want %s", r.URL.Path, tc.Want.URLPath)
   276  		}
   277  		_, err := io.ReadAll(r.Body)
   278  		if err != nil {
   279  			t.Fatal(err)
   280  		}
   281  		w.WriteHeader(tc.ResponseCode)
   282  		w.Write(tc.Response)
   283  	}))
   284  	defer server.Close()
   285  
   286  	dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   287  		defer r.Body.Close()
   288  		t.Error("Unexpected data API call")
   289  		w.WriteHeader(404)
   290  		w.Write([]byte(`{"message":"Not found"}`))
   291  	}))
   292  	defer dataServer.Close()
   293  
   294  	client, err := mockClient(server, dataServer)
   295  	if err != nil {
   296  		t.Fatal(err)
   297  	}
   298  	var res *BasicResponse
   299  	for i, tc := range testCases {
   300  		currentTestIdx = i
   301  		t.Run(strconv.Itoa(i), func(t *testing.T) {
   302  			res, err = client.LinkUserRichMenu(tc.UserID, tc.RichMenuID).Do()
   303  			if tc.Want.Error != nil {
   304  				if !reflect.DeepEqual(err, tc.Want.Error) {
   305  					t.Errorf("Error %v; want %v", err, tc.Want.Error)
   306  				}
   307  			} else {
   308  				if err != nil {
   309  					t.Error(err)
   310  				}
   311  			}
   312  			if tc.Want.Response != nil {
   313  				if !reflect.DeepEqual(res, tc.Want.Response) {
   314  					t.Errorf("Response %v; want %v", res, tc.Want.Response)
   315  				}
   316  			}
   317  		})
   318  	}
   319  }
   320  
   321  // Test method for GetDefaultRichMenu
   322  func (call *GetDefaultRichMenuCall) Test() {
   323  }
   324  
   325  // Test method for CancelDefaultRichMenu
   326  func (call *CancelDefaultRichMenuCall) Test() {
   327  }
   328  
   329  // Test method for SetDefaultRichMenu
   330  func (call *SetDefaultRichMenuCall) Test() {
   331  }
   332  
   333  // TestDefaultRichMenu tests SetDefaultRichMenu, CancelDefaultRichMenu, GetDefaultRichMenu
   334  func TestDefaultRichMenu(t *testing.T) {
   335  	type testMethod interface {
   336  		Test()
   337  	}
   338  	type want struct {
   339  		URLPath     string
   340  		HTTPMethod  string
   341  		RequestBody []byte
   342  		Response    interface{}
   343  		Error       error
   344  	}
   345  	testCases := []struct {
   346  		TestMethod   testMethod
   347  		RichMenuID   string
   348  		ResponseCode int
   349  		Response     []byte
   350  		Want         want
   351  	}{
   352  		{
   353  			RichMenuID:   "654321",
   354  			TestMethod:   new(SetDefaultRichMenuCall),
   355  			ResponseCode: 200,
   356  			Response:     []byte(`{}`),
   357  			Want: want{
   358  				HTTPMethod: http.MethodPost,
   359  				URLPath:    fmt.Sprintf(APIEndpointSetDefaultRichMenu, "654321"),
   360  				Response:   &BasicResponse{},
   361  			},
   362  		},
   363  		{
   364  			RichMenuID:   "N/A",
   365  			TestMethod:   new(GetDefaultRichMenuCall),
   366  			ResponseCode: 200,
   367  			Response:     []byte(`{"richMenuId": "654321"}`),
   368  			Want: want{
   369  				HTTPMethod: http.MethodGet,
   370  				URLPath:    APIEndpointDefaultRichMenu,
   371  				Response:   &RichMenuIDResponse{RichMenuID: "654321"},
   372  			},
   373  		},
   374  		{
   375  			RichMenuID:   "N/A",
   376  			TestMethod:   new(CancelDefaultRichMenuCall),
   377  			ResponseCode: 200,
   378  			Response:     []byte(`{}`),
   379  			Want: want{
   380  				HTTPMethod: http.MethodDelete,
   381  				URLPath:    APIEndpointDefaultRichMenu,
   382  				Response:   &BasicResponse{},
   383  			},
   384  		},
   385  	}
   386  
   387  	var currentTestIdx int
   388  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   389  		defer r.Body.Close()
   390  		tc := testCases[currentTestIdx]
   391  		if r.Method != tc.Want.HTTPMethod {
   392  			t.Errorf("Method %s; want %s", r.Method, tc.Want.HTTPMethod)
   393  		}
   394  		if r.URL.Path != tc.Want.URLPath {
   395  			t.Errorf("URLPath %s; want %s", r.URL.Path, tc.Want.URLPath)
   396  		}
   397  		_, err := io.ReadAll(r.Body)
   398  		if err != nil {
   399  			t.Fatal(err)
   400  		}
   401  		w.WriteHeader(tc.ResponseCode)
   402  		w.Write(tc.Response)
   403  	}))
   404  	defer server.Close()
   405  
   406  	dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   407  		defer r.Body.Close()
   408  		t.Error("Unexpected data API call")
   409  		w.WriteHeader(404)
   410  		w.Write([]byte(`{"message":"Not found"}`))
   411  	}))
   412  	defer dataServer.Close()
   413  
   414  	client, err := mockClient(server, dataServer)
   415  	if err != nil {
   416  		t.Fatal(err)
   417  	}
   418  	var res interface{}
   419  	for i, tc := range testCases {
   420  		currentTestIdx = i
   421  		t.Run(strconv.Itoa(i)+"/"+tc.RichMenuID+"."+string(tc.Response), func(t *testing.T) {
   422  			switch tc.TestMethod.(type) {
   423  			case *SetDefaultRichMenuCall:
   424  				res, err = client.SetDefaultRichMenu(tc.RichMenuID).Do()
   425  			case *CancelDefaultRichMenuCall:
   426  				res, err = client.CancelDefaultRichMenu().Do()
   427  			case *GetDefaultRichMenuCall:
   428  				res, err = client.GetDefaultRichMenu().Do()
   429  			}
   430  			if tc.Want.Error != nil {
   431  				if !reflect.DeepEqual(err, tc.Want.Error) {
   432  					t.Errorf("Error %v; want %v", err, tc.Want.Error)
   433  				}
   434  			} else {
   435  				if err != nil {
   436  					t.Error(err)
   437  				}
   438  			}
   439  			if tc.Want.Response != nil {
   440  				if !reflect.DeepEqual(res, tc.Want.Response) {
   441  					t.Errorf("Response %v; want %v", res, tc.Want.Response)
   442  				}
   443  			}
   444  		})
   445  	}
   446  }
   447  
   448  // TestListRichMenu
   449  func TestListRichMenu(t *testing.T) {
   450  	type want struct {
   451  		URLPath     string
   452  		RequestBody []byte
   453  		Response    []*RichMenuResponse
   454  		Error       error
   455  	}
   456  	testCases := []struct {
   457  		ResponseCode int
   458  		Response     []byte
   459  		Want         want
   460  	}{
   461  		{
   462  			ResponseCode: 200,
   463  			Response: []byte(`{"richmenus":[` +
   464  				`{"richMenuId":"123","size":{"width":2500,"height":1686},"selected":false,"areas":[{"bounds":{"x":0,"y":0,"width":2500,"height":1686},"action":{"type":"postback","data":"action=buy&itemid=123"}}]},` +
   465  				`{"richMenuId":"456","size":{"width":2500,"height":1686},"selected":false,"chatBarText":"hello","areas":[{"bounds":{"x":0,"y":0,"width":2500,"height":1686},"action":{"type":"message","text":"text"}}]},` +
   466  				`{"richMenuId":"789","size":{"width":2500,"height":1686},"selected":false,"chatBarText":"line.me","areas":[{"bounds":{"x":0,"y":0,"width":2500,"height":1686},"action":{"type":"uri","uri":"https://line.me/"}}]}` +
   467  				`]}`),
   468  			Want: want{
   469  				URLPath: APIEndpointListRichMenu,
   470  				Response: []*RichMenuResponse{
   471  					{
   472  						RichMenuID:  "123",
   473  						Size:        RichMenuSize{Width: 2500, Height: 1686},
   474  						Selected:    false,
   475  						ChatBarText: "",
   476  						Areas: []AreaDetail{
   477  							{
   478  								Bounds: RichMenuBounds{X: 0, Y: 0, Width: 2500, Height: 1686},
   479  								Action: RichMenuAction{Type: RichMenuActionTypePostback, Data: "action=buy&itemid=123"},
   480  							},
   481  						},
   482  					},
   483  					{
   484  						RichMenuID:  "456",
   485  						Size:        RichMenuSize{Width: 2500, Height: 1686},
   486  						Selected:    false,
   487  						ChatBarText: "hello",
   488  						Areas: []AreaDetail{
   489  							{
   490  								Bounds: RichMenuBounds{X: 0, Y: 0, Width: 2500, Height: 1686},
   491  								Action: RichMenuAction{Type: RichMenuActionTypeMessage, Text: "text"},
   492  							},
   493  						},
   494  					},
   495  					{
   496  						RichMenuID:  "789",
   497  						Size:        RichMenuSize{Width: 2500, Height: 1686},
   498  						Selected:    false,
   499  						ChatBarText: "line.me",
   500  						Areas: []AreaDetail{
   501  							{
   502  								Bounds: RichMenuBounds{X: 0, Y: 0, Width: 2500, Height: 1686},
   503  								Action: RichMenuAction{Type: RichMenuActionTypeURI, URI: "https://line.me/"},
   504  							},
   505  						},
   506  					},
   507  				},
   508  			},
   509  		},
   510  	}
   511  
   512  	var currentTestIdx int
   513  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   514  		defer r.Body.Close()
   515  		tc := testCases[currentTestIdx]
   516  		if r.Method != http.MethodGet {
   517  			t.Errorf("Method %s; want %s", r.Method, http.MethodGet)
   518  		}
   519  		if r.URL.Path != tc.Want.URLPath {
   520  			t.Errorf("URLPath %s; want %s", r.URL.Path, tc.Want.URLPath)
   521  		}
   522  		_, err := io.ReadAll(r.Body)
   523  		if err != nil {
   524  			t.Fatal(err)
   525  		}
   526  		w.WriteHeader(tc.ResponseCode)
   527  		w.Write(tc.Response)
   528  	}))
   529  	defer server.Close()
   530  
   531  	dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   532  		defer r.Body.Close()
   533  		t.Error("Unexpected data API call")
   534  		w.WriteHeader(404)
   535  		w.Write([]byte(`{"message":"Not found"}`))
   536  	}))
   537  	defer dataServer.Close()
   538  
   539  	client, err := mockClient(server, dataServer)
   540  	if err != nil {
   541  		t.Fatal(err)
   542  	}
   543  	for i, tc := range testCases {
   544  		currentTestIdx = i
   545  		t.Run(strconv.Itoa(i), func(t *testing.T) {
   546  			res, err := client.GetRichMenuList().Do()
   547  			if tc.Want.Error != nil {
   548  				if !reflect.DeepEqual(err, tc.Want.Error) {
   549  					t.Errorf("Error %v; want %v", err, tc.Want.Error)
   550  				}
   551  			} else {
   552  				if err != nil {
   553  					t.Error(err)
   554  				}
   555  			}
   556  			if tc.Want.Response != nil {
   557  				if !reflect.DeepEqual(res, tc.Want.Response) {
   558  					t.Errorf("Response\n %v; want\n %v", res, tc.Want.Response)
   559  				}
   560  			}
   561  		})
   562  	}
   563  }
   564  
   565  // TestBulkRichMenu tests BulkLinkRichMenu, BulkUnlinkRichMenu
   566  func TestBulkRichMenu(t *testing.T) {
   567  	type want struct {
   568  		URLPath     string
   569  		RequestBody []byte
   570  		Response    *BasicResponse
   571  		Error       error
   572  	}
   573  	testCases := []struct {
   574  		UserIDs      []string
   575  		RichMenuID   string
   576  		ResponseCode int
   577  		Response     []byte
   578  		Want         want
   579  	}{
   580  		{
   581  			ResponseCode: 202,
   582  			Response:     []byte(`{}`),
   583  			UserIDs:      []string{"userId1", "userId2"},
   584  			RichMenuID:   "richMenuId",
   585  			Want: want{
   586  				RequestBody: []byte(`{"richMenuId":"richMenuId","userIds":["userId1","userId2"]}` + "\n"),
   587  				URLPath:     APIEndpointBulkLinkRichMenu,
   588  				Response:    &BasicResponse{},
   589  			},
   590  		},
   591  		{
   592  			ResponseCode: 202,
   593  			Response:     []byte(`{}`),
   594  			UserIDs:      []string{"userId1", "userId2"},
   595  			RichMenuID:   "", // bulk unlink has no richmenuid
   596  			Want: want{
   597  				RequestBody: []byte(`{"userIds":["userId1","userId2"]}` + "\n"),
   598  				URLPath:     APIEndpointBulkUnlinkRichMenu,
   599  				Response:    &BasicResponse{},
   600  			},
   601  		},
   602  	}
   603  
   604  	var currentTestIdx int
   605  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   606  		defer r.Body.Close()
   607  		tc := testCases[currentTestIdx]
   608  		if r.Method != http.MethodPost {
   609  			t.Errorf("Method %s; want %s", r.Method, http.MethodPost)
   610  		}
   611  		if r.URL.Path != tc.Want.URLPath {
   612  			t.Errorf("URLPath %s; want %s", r.URL.Path, tc.Want.URLPath)
   613  		}
   614  		body, err := io.ReadAll(r.Body)
   615  		if err != nil {
   616  			t.Fatal(err)
   617  		}
   618  		if !reflect.DeepEqual(body, tc.Want.RequestBody) {
   619  			t.Errorf("RequestBody\n %s; want\n %s", body, tc.Want.RequestBody)
   620  		}
   621  		w.WriteHeader(tc.ResponseCode)
   622  		w.Write(tc.Response)
   623  	}))
   624  	defer server.Close()
   625  
   626  	dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   627  		defer r.Body.Close()
   628  		t.Error("Unexpected data API call")
   629  		w.WriteHeader(404)
   630  		w.Write([]byte(`{"message":"Not found"}`))
   631  	}))
   632  	defer dataServer.Close()
   633  
   634  	client, err := mockClient(server, dataServer)
   635  	if err != nil {
   636  		t.Fatal(err)
   637  	}
   638  
   639  	var res interface{}
   640  	for i, tc := range testCases {
   641  		currentTestIdx = i
   642  		t.Run(strconv.Itoa(i), func(t *testing.T) {
   643  			if tc.RichMenuID == "" { // unlink
   644  				res, err = client.BulkUnlinkRichMenu(tc.UserIDs...).Do()
   645  			} else { // bulk link
   646  				res, err = client.BulkLinkRichMenu(tc.RichMenuID, tc.UserIDs...).Do()
   647  			}
   648  			if tc.Want.Error != nil {
   649  				if !reflect.DeepEqual(err, tc.Want.Error) {
   650  					t.Errorf("Error %v; want %v", err, tc.Want.Error)
   651  				}
   652  			} else {
   653  				if err != nil {
   654  					t.Error(err)
   655  				}
   656  			}
   657  			if tc.Want.Response != nil {
   658  				if !reflect.DeepEqual(res, tc.Want.Response) {
   659  					t.Errorf("Response\n %v; want\n %v", res, tc.Want.Response)
   660  				}
   661  			}
   662  		})
   663  	}
   664  }
   665  
   666  func TestUploadRichMenuImage(t *testing.T) {
   667  	type want struct {
   668  		URLPath     string
   669  		RequestBody []byte
   670  		Response    *BasicResponse
   671  		Error       error
   672  	}
   673  	testCases := []struct {
   674  		RichMenuID   string
   675  		ImagePath    string
   676  		ResponseCode int
   677  		Response     []byte
   678  		Want         want
   679  	}{
   680  		{
   681  			RichMenuID:   "123456",
   682  			ImagePath:    filepath.Join("..", "testdata", "img", "richmenu.png"),
   683  			ResponseCode: 200,
   684  			Response:     []byte(`{}`),
   685  			Want: want{
   686  				URLPath:  fmt.Sprintf(APIEndpointUploadRichMenuImage, "123456"),
   687  				Response: &BasicResponse{},
   688  			},
   689  		},
   690  	}
   691  
   692  	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   693  		defer r.Body.Close()
   694  		t.Error("Unexpected API call")
   695  		w.WriteHeader(404)
   696  		w.Write([]byte(`{"message":"Not found"}`))
   697  	}))
   698  	defer server.Close()
   699  
   700  	var currentTestIdx int
   701  	dataServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   702  		defer r.Body.Close()
   703  		tc := testCases[currentTestIdx]
   704  		if r.Method != http.MethodPost {
   705  			t.Errorf("Method %s; want %s", r.Method, http.MethodPost)
   706  		}
   707  		if r.URL.Path != tc.Want.URLPath {
   708  			t.Errorf("URLPath %s; want %s", r.URL.Path, tc.Want.URLPath)
   709  		}
   710  		body, err := io.ReadAll(r.Body)
   711  		if err != nil {
   712  			t.Fatal(err)
   713  		}
   714  		imgBody, err := os.ReadFile(tc.ImagePath)
   715  		if err != nil {
   716  			t.Fatal(err)
   717  		}
   718  		wantImgSize := len(imgBody)
   719  		if len(body) != wantImgSize {
   720  			t.Errorf("ContentLength %d; want %d", len(body), wantImgSize)
   721  		}
   722  		if r.ContentLength != int64(wantImgSize) {
   723  			t.Errorf("ContentLength %d; want %d", r.ContentLength, wantImgSize)
   724  		}
   725  		w.WriteHeader(tc.ResponseCode)
   726  		w.Write(tc.Response)
   727  	}))
   728  	defer dataServer.Close()
   729  	client, err := mockClient(server, dataServer)
   730  	if err != nil {
   731  		t.Fatal(err)
   732  	}
   733  
   734  	for i, tc := range testCases {
   735  		currentTestIdx = i
   736  		t.Run(strconv.Itoa(i), func(t *testing.T) {
   737  			res, err := client.UploadRichMenuImage(tc.RichMenuID, tc.ImagePath).Do()
   738  			if tc.Want.Error != nil {
   739  				if !reflect.DeepEqual(err, tc.Want.Error) {
   740  					t.Errorf("Error %v; want %v", err, tc.Want.Error)
   741  				}
   742  			} else {
   743  				if err != nil {
   744  					t.Error(err)
   745  				}
   746  			}
   747  			if tc.Want.Response != nil {
   748  				if !reflect.DeepEqual(res, tc.Want.Response) {
   749  					t.Errorf("Response\n %v; want\n %v", res, tc.Want.Response)
   750  				}
   751  			}
   752  		})
   753  	}
   754  }
   755  
   756  func TestDownloadRichMenuImage(t *testing.T) {
   757  	filePath := filepath.Join("..", "testdata", "img", "richmenu.png")
   758  	file, err := os.ReadFile(filePath)
   759  	if err != nil {
   760  		t.Fatal(err)
   761  	}
   762  
   763  	type want struct {
   764  		URLPath  string
   765  		Response *MessageContentResponse
   766  		Error    error
   767  	}
   768  	testCases := []struct {
   769  		RichMenuID     string
   770  		ImagePath      string
   771  		Response       []byte
   772  		ResponseCode   int
   773  		ResponseHeader map[string]string
   774  		Want           want
   775  	}{
   776  		{
   777  			RichMenuID:   "123456",
   778  			Response:     file,
   779  			ResponseCode: 200,
   780  			ResponseHeader: map[string]string{
   781  				"Content-Type":   "image/png",
   782  				"Content-Length": strconv.Itoa(len(file)),
   783  			},
   784  			Want: want{
   785  				URLPath: fmt.Sprintf(APIEndpointUploadRichMenuImage, "123456"),
   786  				Response: &MessageContentResponse{
   787  					ContentType:   "image/png",
   788  					ContentLength: int64(len(file)),
   789  					Content:       io.NopCloser(bytes.NewReader(file)),
   790  				},
   791  			},
   792  		},
   793  	}
   794  
   795  	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   796  		defer r.Body.Close()
   797  		t.Error("Unexpected API call")
   798  		w.WriteHeader(404)
   799  		w.Write([]byte(`{"message":"Not found"}`))
   800  	}))
   801  	defer server.Close()
   802  
   803  	var currentTestIdx int
   804  	dataServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   805  		defer r.Body.Close()
   806  		tc := testCases[currentTestIdx]
   807  		if r.Method != http.MethodGet {
   808  			t.Errorf("Method %s; want %s", r.Method, http.MethodGet)
   809  		}
   810  		if r.URL.Path != tc.Want.URLPath {
   811  			t.Errorf("URLPath %s; want %s", r.URL.Path, tc.Want.URLPath)
   812  		}
   813  		if err != nil {
   814  			t.Fatal(err)
   815  		}
   816  		for k, v := range tc.ResponseHeader {
   817  			w.Header().Add(k, v)
   818  		}
   819  		w.WriteHeader(tc.ResponseCode)
   820  		w.Write(tc.Response)
   821  	}))
   822  	defer dataServer.Close()
   823  
   824  	client, err := mockClient(server, dataServer)
   825  	if err != nil {
   826  		t.Fatal(err)
   827  	}
   828  
   829  	for i, tc := range testCases {
   830  		currentTestIdx = i
   831  		t.Run(strconv.Itoa(i), func(t *testing.T) {
   832  			res, err := client.DownloadRichMenuImage(tc.RichMenuID).Do()
   833  			if tc.Want.Error != nil {
   834  				if !reflect.DeepEqual(err, tc.Want.Error) {
   835  					t.Errorf("Error %v; want %v", err, tc.Want.Error)
   836  				}
   837  			} else {
   838  				if err != nil {
   839  					t.Error(err)
   840  				}
   841  			}
   842  			if tc.Want.Response != nil {
   843  				body := res.Content
   844  				defer body.Close()
   845  				resImage, err := io.ReadAll(body)
   846  				if err != nil {
   847  					t.Fatal(err)
   848  				}
   849  				if !bytes.Equal(resImage, tc.Response) {
   850  					t.Error("Expected image content is not returned")
   851  				}
   852  				res.Content = nil
   853  				tc.Want.Response.Content = nil
   854  				if !reflect.DeepEqual(res, tc.Want.Response) {
   855  					t.Errorf("Response\n %+v; want\n %+v", res, tc.Want.Response)
   856  				}
   857  			}
   858  		})
   859  	}
   860  }
   861  
   862  // Test method for CreateRichMenuAlias
   863  func (call *CreateRichMenuAliasCall) Test() {
   864  }
   865  
   866  // Test method for GetRichMenuAlias
   867  func (call *GetRichMenuAliasCall) Test() {
   868  }
   869  
   870  // Test method for UpdateRichMenuAlias
   871  func (call *UpdateRichMenuAliasCall) Test() {
   872  }
   873  
   874  // Test method for DeleteRichMenuAlias
   875  func (call *DeleteRichMenuAliasCall) Test() {
   876  }
   877  
   878  // TestCRUDRichMenuAlias tests CreateRichMenuAlias, GetRichMenuAlias, UpdateRichMenuAlias, DeleteRichMenuAlias
   879  func TestCRUDRichMenuAlias(t *testing.T) {
   880  	type testMethod interface {
   881  		Test()
   882  	}
   883  	type want struct {
   884  		URLPath    string
   885  		HTTPMethod string
   886  		Response   interface{}
   887  		Error      error
   888  	}
   889  	testCases := []struct {
   890  		TestMethod      testMethod
   891  		RichMenuID      string
   892  		RichMenuAliasID string
   893  		ResponseCode    int
   894  		Response        []byte
   895  		Want            want
   896  	}{
   897  		{
   898  			RichMenuID:      "654321",
   899  			RichMenuAliasID: "richmenu-alias-create",
   900  			TestMethod:      new(CreateRichMenuAliasCall),
   901  			ResponseCode:    200,
   902  			Response:        []byte(`{}`),
   903  			Want: want{
   904  				HTTPMethod: http.MethodPost,
   905  				URLPath:    APIEndpointCreateRichMenuAlias,
   906  				Response:   &BasicResponse{},
   907  			},
   908  		},
   909  		{
   910  			RichMenuID:      "N/A",
   911  			RichMenuAliasID: "richmenu-alias-get",
   912  			TestMethod:      new(GetRichMenuAliasCall),
   913  			ResponseCode:    200,
   914  			Response:        []byte(`{"richMenuAliasId":"richmenu-alias-get","richMenuId":"richmenu-88c05ef6921ae53f8b58a25f3a65faf7"}`),
   915  			Want: want{
   916  				HTTPMethod: http.MethodGet,
   917  				URLPath:    fmt.Sprintf(APIEndpointGetRichMenuAlias, "richmenu-alias-get"),
   918  				Response:   &RichMenuAliasResponse{RichMenuAliasID: "richmenu-alias-get", RichMenuID: "richmenu-88c05ef6921ae53f8b58a25f3a65faf7"},
   919  			},
   920  		},
   921  		{
   922  			RichMenuID:      "123456",
   923  			RichMenuAliasID: "richmenu-alias-update",
   924  			TestMethod:      new(UpdateRichMenuAliasCall),
   925  			ResponseCode:    200,
   926  			Response:        []byte(`{}`),
   927  			Want: want{
   928  				HTTPMethod: http.MethodPost,
   929  				URLPath:    fmt.Sprintf(APIEndpointGetRichMenuAlias, "richmenu-alias-update"),
   930  				Response:   &BasicResponse{},
   931  			},
   932  		},
   933  		{
   934  			RichMenuID:      "N/A",
   935  			RichMenuAliasID: "richmenu-alias-delete",
   936  			TestMethod:      new(DeleteRichMenuAliasCall),
   937  			ResponseCode:    200,
   938  			Response:        []byte(`{}`),
   939  			Want: want{
   940  				HTTPMethod: http.MethodDelete,
   941  				URLPath:    fmt.Sprintf(APIEndpointDeleteRichMenuAlias, "richmenu-alias-delete"),
   942  				Response:   &BasicResponse{},
   943  			},
   944  		},
   945  	}
   946  
   947  	var currentTestIdx int
   948  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   949  		defer r.Body.Close()
   950  		tc := testCases[currentTestIdx]
   951  		if r.Method != tc.Want.HTTPMethod {
   952  			t.Errorf("Method %s; want %s", r.Method, tc.Want.HTTPMethod)
   953  		}
   954  		if r.URL.Path != tc.Want.URLPath {
   955  			t.Errorf("URLPath %s; want %s", r.URL.Path, tc.Want.URLPath)
   956  		}
   957  		_, err := io.ReadAll(r.Body)
   958  		if err != nil {
   959  			t.Fatal(err)
   960  		}
   961  		w.WriteHeader(tc.ResponseCode)
   962  		w.Write(tc.Response)
   963  	}))
   964  	defer server.Close()
   965  
   966  	dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   967  		defer r.Body.Close()
   968  		t.Error("Unexpected data API call")
   969  		w.WriteHeader(404)
   970  		w.Write([]byte(`{"message":"Not found"}`))
   971  	}))
   972  	defer dataServer.Close()
   973  
   974  	client, err := mockClient(server, dataServer)
   975  	if err != nil {
   976  		t.Fatal(err)
   977  	}
   978  	var res interface{}
   979  	for i, tc := range testCases {
   980  		currentTestIdx = i
   981  		t.Run(strconv.Itoa(i)+"/"+tc.RichMenuAliasID+"."+string(tc.Response), func(t *testing.T) {
   982  			switch tc.TestMethod.(type) {
   983  			case *CreateRichMenuAliasCall:
   984  				res, err = client.CreateRichMenuAlias(tc.RichMenuAliasID, tc.RichMenuID).Do()
   985  			case *GetRichMenuAliasCall:
   986  				res, err = client.GetRichMenuAlias(tc.RichMenuAliasID).Do()
   987  			case *UpdateRichMenuAliasCall:
   988  				res, err = client.UpdateRichMenuAlias(tc.RichMenuAliasID, tc.RichMenuID).Do()
   989  			case *DeleteRichMenuAliasCall:
   990  				res, err = client.DeleteRichMenuAlias(tc.RichMenuAliasID).Do()
   991  			}
   992  			if tc.Want.Error != nil {
   993  				if !reflect.DeepEqual(err, tc.Want.Error) {
   994  					t.Errorf("Error %v; want %v", err, tc.Want.Error)
   995  				}
   996  			} else {
   997  				if err != nil {
   998  					t.Error(err)
   999  				}
  1000  			}
  1001  			if tc.Want.Response != nil {
  1002  				if !reflect.DeepEqual(res, tc.Want.Response) {
  1003  					t.Errorf("Response %v; want %v", res, tc.Want.Response)
  1004  				}
  1005  			}
  1006  		})
  1007  	}
  1008  }
  1009  
  1010  // TestListRichMenuAlias
  1011  func TestListRichMenuAlias(t *testing.T) {
  1012  	type want struct {
  1013  		URLPath  string
  1014  		Response []*RichMenuAliasResponse
  1015  		Error    error
  1016  	}
  1017  	testCases := []struct {
  1018  		ResponseCode int
  1019  		Response     []byte
  1020  		Want         want
  1021  	}{
  1022  		{
  1023  			ResponseCode: 200,
  1024  			Response: []byte(`{"aliases":[` +
  1025  				`{"richMenuAliasId":"richmenu-alias-a","richMenuId": "richmenu-862e6ad6c267d2ddf3f42bc78554f6a4"},` +
  1026  				`{"richMenuAliasId": "richmenu-alias-b","richMenuId": "richmenu-88c05ef6921ae53f8b58a25f3a65faf7"}` +
  1027  				`]}`),
  1028  			Want: want{
  1029  				URLPath: APIEndpointListRichMenuAlias,
  1030  				Response: []*RichMenuAliasResponse{
  1031  					{
  1032  						RichMenuAliasID: "richmenu-alias-a",
  1033  						RichMenuID:      "richmenu-862e6ad6c267d2ddf3f42bc78554f6a4",
  1034  					},
  1035  					{
  1036  						RichMenuAliasID: "richmenu-alias-b",
  1037  						RichMenuID:      "richmenu-88c05ef6921ae53f8b58a25f3a65faf7",
  1038  					},
  1039  				},
  1040  			},
  1041  		},
  1042  		{
  1043  			ResponseCode: 200,
  1044  			Response: []byte(`{"aliases":[` +
  1045  				`]}`),
  1046  			Want: want{
  1047  				URLPath:  APIEndpointListRichMenuAlias,
  1048  				Response: []*RichMenuAliasResponse{},
  1049  			},
  1050  		},
  1051  	}
  1052  
  1053  	var currentTestIdx int
  1054  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1055  		defer r.Body.Close()
  1056  		tc := testCases[currentTestIdx]
  1057  		if r.Method != http.MethodGet {
  1058  			t.Errorf("Method %s; want %s", r.Method, http.MethodGet)
  1059  		}
  1060  		if r.URL.Path != tc.Want.URLPath {
  1061  			t.Errorf("URLPath %s; want %s", r.URL.Path, tc.Want.URLPath)
  1062  		}
  1063  		_, err := io.ReadAll(r.Body)
  1064  		if err != nil {
  1065  			t.Fatal(err)
  1066  		}
  1067  		w.WriteHeader(tc.ResponseCode)
  1068  		w.Write(tc.Response)
  1069  	}))
  1070  	defer server.Close()
  1071  
  1072  	dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1073  		defer r.Body.Close()
  1074  		t.Error("Unexpected data API call")
  1075  		w.WriteHeader(404)
  1076  		w.Write([]byte(`{"message":"Not found"}`))
  1077  	}))
  1078  	defer dataServer.Close()
  1079  
  1080  	client, err := mockClient(server, dataServer)
  1081  	if err != nil {
  1082  		t.Fatal(err)
  1083  	}
  1084  	for i, tc := range testCases {
  1085  		currentTestIdx = i
  1086  		t.Run(strconv.Itoa(i), func(t *testing.T) {
  1087  			res, err := client.GetRichMenuAliasList().Do()
  1088  			if tc.Want.Error != nil {
  1089  				if !reflect.DeepEqual(err, tc.Want.Error) {
  1090  					t.Errorf("Error %v; want %v", err, tc.Want.Error)
  1091  				}
  1092  			} else {
  1093  				if err != nil {
  1094  					t.Error(err)
  1095  				}
  1096  			}
  1097  			if tc.Want.Response != nil {
  1098  				if !reflect.DeepEqual(res, tc.Want.Response) {
  1099  					t.Errorf("Response\n %v; want\n %v", res, tc.Want.Response)
  1100  				}
  1101  			}
  1102  		})
  1103  	}
  1104  }
  1105  
  1106  func TestValidateRichMenuObject(t *testing.T) {
  1107  	type want struct {
  1108  		RequestBody []byte
  1109  		Response    *BasicResponse
  1110  		Error       error
  1111  	}
  1112  	testCases := []struct {
  1113  		Request      RichMenu
  1114  		Response     []byte
  1115  		ResponseCode int
  1116  		Want         want
  1117  	}{
  1118  		{
  1119  			Request: RichMenu{
  1120  				Size:        RichMenuSize{Width: 2500, Height: 1686},
  1121  				Selected:    false,
  1122  				Name:        "Menu1",
  1123  				ChatBarText: "ChatText",
  1124  				Areas: []AreaDetail{
  1125  					{
  1126  						Bounds: RichMenuBounds{X: 0, Y: 0, Width: 2500, Height: 1686},
  1127  						Action: RichMenuAction{Type: RichMenuActionTypePostback, Data: "action=buy&itemid=123", DisplayText: "Buy", Label: "Buy"},
  1128  					},
  1129  				},
  1130  			},
  1131  			ResponseCode: 200,
  1132  			Response:     []byte(`{}`),
  1133  			Want: want{
  1134  				RequestBody: []byte(`{"size":{"width":2500,"height":1686},"selected":false,"name":"Menu1","chatBarText":"ChatText","areas":[{"bounds":{"x":0,"y":0,"width":2500,"height":1686},"action":{"type":"postback","displayText":"Buy","label":"Buy","data":"action=buy\u0026itemid=123"}}]}` + "\n"),
  1135  				Response:    &BasicResponse{},
  1136  			},
  1137  		},
  1138  	}
  1139  
  1140  	var currentTestIdx int
  1141  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1142  		defer r.Body.Close()
  1143  		tc := testCases[currentTestIdx]
  1144  		if r.Method != http.MethodPost {
  1145  			t.Errorf("Method %s; want %s", r.Method, http.MethodPost)
  1146  		}
  1147  		if r.URL.Path != APIEndpointValidateRichMenuObject {
  1148  			t.Errorf("URLPath %s; want %s", r.URL.Path, APIEndpointValidateRichMenuObject)
  1149  		}
  1150  		body, err := io.ReadAll(r.Body)
  1151  		if err != nil {
  1152  			t.Fatal(err)
  1153  		}
  1154  		if !reflect.DeepEqual(body, tc.Want.RequestBody) {
  1155  			t.Errorf("RequestBody\n %s; want\n %s", body, tc.Want.RequestBody)
  1156  		}
  1157  		w.WriteHeader(tc.ResponseCode)
  1158  		w.Write(tc.Response)
  1159  	}))
  1160  	defer server.Close()
  1161  
  1162  	dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1163  		defer r.Body.Close()
  1164  		t.Error("Unexpected data API call")
  1165  		w.WriteHeader(404)
  1166  		w.Write([]byte(`{"message":"Not found"}`))
  1167  	}))
  1168  	defer dataServer.Close()
  1169  
  1170  	client, err := mockClient(server, dataServer)
  1171  	if err != nil {
  1172  		t.Fatal(err)
  1173  	}
  1174  	for i, tc := range testCases {
  1175  		currentTestIdx = i
  1176  		t.Run(strconv.Itoa(i), func(t *testing.T) {
  1177  			res, err := client.ValidateRichMenuObject(tc.Request).Do()
  1178  			if tc.Want.Error != nil {
  1179  				if !reflect.DeepEqual(err, tc.Want.Error) {
  1180  					t.Errorf("Error %v; want %v", err, tc.Want.Error)
  1181  				}
  1182  			} else {
  1183  				if err != nil {
  1184  					t.Error(err)
  1185  				}
  1186  			}
  1187  			if tc.Want.Response != nil {
  1188  				if !reflect.DeepEqual(res, tc.Want.Response) {
  1189  					t.Errorf("Response %v; want %v", res, tc.Want.Response)
  1190  				}
  1191  			}
  1192  		})
  1193  	}
  1194  }