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