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  }