github.com/line/line-bot-sdk-go/v7@v7.21.0/linebot/oauth_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 "context" 19 "io" 20 "net/http" 21 "net/http/httptest" 22 "reflect" 23 "testing" 24 ) 25 26 func TestIssueAccessToken(t *testing.T) { 27 type want struct { 28 RequestBody []byte 29 Response *AccessTokenResponse 30 Error error 31 } 32 testCases := []struct { 33 ClientID string 34 ClientSecret string 35 Response []byte 36 ResponseCode int 37 Want want 38 }{ 39 { 40 ClientID: "testid", 41 ClientSecret: "testsecret", 42 ResponseCode: 200, 43 Response: []byte(`{}`), 44 Want: want{ 45 RequestBody: []byte("client_id=testid&client_secret=testsecret&grant_type=client_credentials"), 46 Response: &AccessTokenResponse{}, 47 }, 48 }, 49 } 50 51 var currentTestIdx int 52 server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 53 defer r.Body.Close() 54 if r.Method != http.MethodPost { 55 t.Errorf("Method %s; want %s", r.Method, http.MethodPost) 56 } 57 if r.URL.Path != APIEndpointIssueAccessToken { 58 t.Errorf("URLPath %s; want %s", r.URL.Path, APIEndpointIssueAccessToken) 59 } 60 body, err := io.ReadAll(r.Body) 61 if err != nil { 62 t.Fatal(err) 63 } 64 tc := testCases[currentTestIdx] 65 if !reflect.DeepEqual(body, tc.Want.RequestBody) { 66 t.Errorf("RequestBody %s; want %s", body, tc.Want.RequestBody) 67 } 68 w.WriteHeader(tc.ResponseCode) 69 w.Write(tc.Response) 70 })) 71 defer server.Close() 72 73 dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 74 defer r.Body.Close() 75 t.Error("Unexpected data API call") 76 w.WriteHeader(404) 77 w.Write([]byte(`{"message":"Not found"}`)) 78 })) 79 defer dataServer.Close() 80 81 client, err := mockClient(server, dataServer) 82 if err != nil { 83 t.Fatal(err) 84 } 85 for i, tc := range testCases { 86 currentTestIdx = i 87 res, err := client.IssueAccessToken(tc.ClientID, tc.ClientSecret).Do() 88 if tc.Want.Error != nil { 89 if !reflect.DeepEqual(err, tc.Want.Error) { 90 t.Errorf("Error %d %q; want %q", i, err, tc.Want.Error) 91 } 92 } else { 93 if err != nil { 94 t.Error(err) 95 } 96 } 97 if tc.Want.Response != nil { 98 if !reflect.DeepEqual(res, tc.Want.Response) { 99 t.Errorf("Response %d %q; want %q", i, res, tc.Want.Response) 100 } 101 } 102 } 103 } 104 105 func TestIssueAccessTokenCall_WithContext(t *testing.T) { 106 type fields struct { 107 c *Client 108 ctx context.Context 109 channelID string 110 channelSecret string 111 } 112 type args struct { 113 ctx context.Context 114 } 115 116 oldCtx := context.Background() 117 type key string 118 newCtx := context.WithValue(oldCtx, key("foo"), "bar") 119 120 tests := []struct { 121 name string 122 fields fields 123 args args 124 want context.Context 125 }{ 126 { 127 name: "replace context", 128 fields: fields{ 129 ctx: oldCtx, 130 }, 131 args: args{ 132 ctx: newCtx, 133 }, 134 want: newCtx, 135 }, 136 } 137 for _, tt := range tests { 138 t.Run(tt.name, func(t *testing.T) { 139 call := &IssueAccessTokenCall{ 140 c: tt.fields.c, 141 ctx: tt.fields.ctx, 142 channelID: tt.fields.channelID, 143 channelSecret: tt.fields.channelSecret, 144 } 145 call = call.WithContext(tt.args.ctx) 146 got := call.ctx 147 if !reflect.DeepEqual(got, tt.want) { 148 t.Errorf("IssueAccessTokenCall.WithContext() = %v, want %v", got, tt.want) 149 } 150 }) 151 } 152 } 153 154 func TestRevokeAccessToken(t *testing.T) { 155 type want struct { 156 RequestBody []byte 157 Response *BasicResponse 158 Error error 159 } 160 testCases := []struct { 161 AccessToken string 162 Response []byte 163 ResponseCode int 164 Want want 165 }{ 166 { 167 AccessToken: "testtoken", 168 ResponseCode: 200, 169 Response: []byte(`{}`), 170 Want: want{ 171 RequestBody: []byte("access_token=testtoken"), 172 Response: &BasicResponse{}, 173 }, 174 }, 175 } 176 177 var currentTestIdx int 178 server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 179 defer r.Body.Close() 180 if r.Method != http.MethodPost { 181 t.Errorf("Method %s; want %s", r.Method, http.MethodPost) 182 } 183 if r.URL.Path != APIEndpointRevokeAccessToken { 184 t.Errorf("URLPath %s; want %s", r.URL.Path, APIEndpointRevokeAccessToken) 185 } 186 body, err := io.ReadAll(r.Body) 187 if err != nil { 188 t.Fatal(err) 189 } 190 tc := testCases[currentTestIdx] 191 if !reflect.DeepEqual(body, tc.Want.RequestBody) { 192 t.Errorf("RequestBody %s; want %s", body, tc.Want.RequestBody) 193 } 194 w.WriteHeader(tc.ResponseCode) 195 w.Write(tc.Response) 196 })) 197 defer server.Close() 198 199 dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 200 defer r.Body.Close() 201 t.Error("Unexpected data API call") 202 w.WriteHeader(404) 203 w.Write([]byte(`{"message":"Not found"}`)) 204 })) 205 defer dataServer.Close() 206 207 client, err := mockClient(server, dataServer) 208 if err != nil { 209 t.Fatal(err) 210 } 211 for i, tc := range testCases { 212 currentTestIdx = i 213 res, err := client.RevokeAccessToken(tc.AccessToken).Do() 214 if tc.Want.Error != nil { 215 if !reflect.DeepEqual(err, tc.Want.Error) { 216 t.Errorf("Error %d %q; want %q", i, err, tc.Want.Error) 217 } 218 } else { 219 if err != nil { 220 t.Error(err) 221 } 222 } 223 if tc.Want.Response != nil { 224 if !reflect.DeepEqual(res, tc.Want.Response) { 225 t.Errorf("Response %d %q; want %q", i, res, tc.Want.Response) 226 } 227 } 228 } 229 } 230 231 func TestRevokeAccessTokenCall_WithContext(t *testing.T) { 232 type fields struct { 233 c *Client 234 ctx context.Context 235 accessToken string 236 } 237 type args struct { 238 ctx context.Context 239 } 240 241 oldCtx := context.Background() 242 type key string 243 newCtx := context.WithValue(oldCtx, key("foo"), "bar") 244 245 tests := []struct { 246 name string 247 fields fields 248 args args 249 want context.Context 250 }{ 251 { 252 name: "replace context", 253 fields: fields{ 254 ctx: oldCtx, 255 }, 256 args: args{ 257 ctx: newCtx, 258 }, 259 want: newCtx, 260 }, 261 } 262 for _, tt := range tests { 263 t.Run(tt.name, func(t *testing.T) { 264 call := &RevokeAccessTokenCall{ 265 c: tt.fields.c, 266 ctx: tt.fields.ctx, 267 accessToken: tt.fields.accessToken, 268 } 269 call = call.WithContext(tt.args.ctx) 270 got := call.ctx 271 if !reflect.DeepEqual(got, tt.want) { 272 t.Errorf("RevokeAccessTokenCall.WithContext() = %v, want %v", got, tt.want) 273 } 274 }) 275 } 276 } 277 278 func TestVerifyAccessToken(t *testing.T) { 279 type want struct { 280 RequestBody []byte 281 Response *VerifiedAccessTokenResponse 282 Error error 283 } 284 testCases := []struct { 285 AccessToken string 286 Response []byte 287 ResponseCode int 288 Want want 289 }{ 290 { 291 AccessToken: "testtoken", 292 ResponseCode: 200, 293 Response: []byte(`{}`), 294 Want: want{ 295 RequestBody: []byte("access_token=testtoken"), 296 Response: &VerifiedAccessTokenResponse{}, 297 }, 298 }, 299 } 300 301 var currentTestIdx int 302 server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 303 defer r.Body.Close() 304 if r.Method != http.MethodPost { 305 t.Errorf("Method %s; want %s", r.Method, http.MethodPost) 306 } 307 if r.URL.Path != APIEndpointVerifyAccessToken { 308 t.Errorf("URLPath %s; want %s", r.URL.Path, APIEndpointVerifyAccessToken) 309 } 310 body, err := io.ReadAll(r.Body) 311 if err != nil { 312 t.Fatal(err) 313 } 314 tc := testCases[currentTestIdx] 315 if !reflect.DeepEqual(body, tc.Want.RequestBody) { 316 t.Errorf("RequestBody %s; want %s", body, tc.Want.RequestBody) 317 } 318 w.WriteHeader(tc.ResponseCode) 319 w.Write(tc.Response) 320 })) 321 defer server.Close() 322 323 dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 324 defer r.Body.Close() 325 t.Error("Unexpected data API call") 326 w.WriteHeader(404) 327 w.Write([]byte(`{"message":"Not found"}`)) 328 })) 329 defer dataServer.Close() 330 331 client, err := mockClient(server, dataServer) 332 if err != nil { 333 t.Fatal(err) 334 } 335 for i, tc := range testCases { 336 currentTestIdx = i 337 res, err := client.VerifyAccessToken(tc.AccessToken).Do() 338 if tc.Want.Error != nil { 339 if !reflect.DeepEqual(err, tc.Want.Error) { 340 t.Errorf("Error %d %q; want %q", i, err, tc.Want.Error) 341 } 342 } else { 343 if err != nil { 344 t.Error(err) 345 } 346 } 347 if tc.Want.Response != nil { 348 if !reflect.DeepEqual(res, tc.Want.Response) { 349 t.Errorf("Response %d %q; want %q", i, res, tc.Want.Response) 350 } 351 } 352 } 353 } 354 355 func TestVerifyAccessTokenCall_WithContext(t *testing.T) { 356 type fields struct { 357 c *Client 358 ctx context.Context 359 accessToken string 360 } 361 type args struct { 362 ctx context.Context 363 } 364 365 oldCtx := context.Background() 366 type key string 367 newCtx := context.WithValue(oldCtx, key("foo"), "bar") 368 369 tests := []struct { 370 name string 371 fields fields 372 args args 373 want context.Context 374 }{ 375 { 376 name: "replace context", 377 fields: fields{ 378 ctx: oldCtx, 379 }, 380 args: args{ 381 ctx: newCtx, 382 }, 383 want: newCtx, 384 }, 385 } 386 for _, tt := range tests { 387 t.Run(tt.name, func(t *testing.T) { 388 call := &VerifyAccessTokenCall{ 389 c: tt.fields.c, 390 ctx: tt.fields.ctx, 391 accessToken: tt.fields.accessToken, 392 } 393 call = call.WithContext(tt.args.ctx) 394 got := call.ctx 395 if !reflect.DeepEqual(got, tt.want) { 396 t.Errorf("VerifyAccessTokenCall.WithContext() = %v, want %v", got, tt.want) 397 } 398 }) 399 } 400 }