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  }