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

     1  // Copyright 2019 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  	"fmt"
    20  	"io"
    21  	"net/http"
    22  	"net/http/httptest"
    23  	"reflect"
    24  	"strconv"
    25  	"testing"
    26  	"time"
    27  )
    28  
    29  // TestInsights tests GetNumberMessagesDelivery, GetNumberFollowers
    30  // and GetFriendDemographics func
    31  
    32  func TestGetNumberMessagesDelivery(t *testing.T) {
    33  	type want struct {
    34  		URLPath     string
    35  		RequestBody []byte
    36  		Response    *MessagesNumberDeliveryResponse
    37  		Error       error
    38  	}
    39  	testCases := []struct {
    40  		Label        string
    41  		Date         string
    42  		ResponseCode int
    43  		Response     []byte
    44  		Want         want
    45  	}{
    46  		{
    47  			Label:        "Success",
    48  			Date:         "20190418",
    49  			ResponseCode: 200,
    50  			Response: []byte(`{
    51  				"status": "ready",
    52  				"broadcast": 5385,
    53  				"targeting": 522
    54  			}`),
    55  			Want: want{
    56  				URLPath:     fmt.Sprintf(APIEndpointInsight, InsightTypeMessageDelivery),
    57  				RequestBody: []byte(""),
    58  				Response: &MessagesNumberDeliveryResponse{
    59  					Status:    "ready",
    60  					Broadcast: 5385,
    61  					Targeting: 522,
    62  				},
    63  			},
    64  		},
    65  		{
    66  			Label:        "Internal server error",
    67  			Date:         "20190418",
    68  			ResponseCode: 500,
    69  			Response:     []byte("500 Internal server error"),
    70  			Want: want{
    71  				URLPath:     fmt.Sprintf(APIEndpointInsight, InsightTypeMessageDelivery),
    72  				RequestBody: []byte(""),
    73  				Error: &APIError{
    74  					Code: 500,
    75  				},
    76  			},
    77  		},
    78  	}
    79  
    80  	var currentTestIdx int
    81  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    82  		defer r.Body.Close()
    83  		tc := testCases[currentTestIdx]
    84  		if r.Method != http.MethodGet {
    85  			t.Errorf("Method %s; want %s", r.Method, http.MethodGet)
    86  		}
    87  		if r.URL.Path != tc.Want.URLPath {
    88  			t.Errorf("URLPath %s; want %s", r.URL.Path, tc.Want.URLPath)
    89  		}
    90  		body, err := io.ReadAll(r.Body)
    91  		if err != nil {
    92  			t.Fatal(err)
    93  		}
    94  		if !reflect.DeepEqual(body, tc.Want.RequestBody) {
    95  			t.Errorf("RequestBody %s; want %s", body, tc.Want.RequestBody)
    96  		}
    97  		w.WriteHeader(tc.ResponseCode)
    98  		w.Write(tc.Response)
    99  	}))
   100  	defer server.Close()
   101  
   102  	dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   103  		defer r.Body.Close()
   104  		t.Error("Unexpected Data API call")
   105  		w.WriteHeader(404)
   106  		w.Write([]byte(`{"message":"Not found"}`))
   107  	}))
   108  	defer dataServer.Close()
   109  
   110  	client, err := mockClient(server, dataServer)
   111  	if err != nil {
   112  		t.Fatal(err)
   113  	}
   114  	for i, tc := range testCases {
   115  		currentTestIdx = i
   116  		t.Run(strconv.Itoa(i)+"/"+tc.Label, func(t *testing.T) {
   117  			res, err := client.GetNumberMessagesDelivery(tc.Date).Do()
   118  			if tc.Want.Error != nil {
   119  				if !reflect.DeepEqual(err, tc.Want.Error) {
   120  					t.Errorf("Error %v; want %v", err, tc.Want.Error)
   121  				}
   122  			} else {
   123  				if err != nil {
   124  					t.Error(err)
   125  				}
   126  			}
   127  			if !reflect.DeepEqual(res, tc.Want.Response) {
   128  				t.Errorf("Response %v; want %v", res, tc.Want.Response)
   129  			}
   130  		})
   131  	}
   132  }
   133  
   134  func TestGetNumberMessagesDeliveryContext(t *testing.T) {
   135  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   136  		defer r.Body.Close()
   137  		time.Sleep(10 * time.Millisecond)
   138  		w.Write([]byte("{}"))
   139  	}))
   140  	defer server.Close()
   141  
   142  	dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   143  		defer r.Body.Close()
   144  		t.Error("Unexpected Data API call")
   145  		w.WriteHeader(404)
   146  		w.Write([]byte(`{"message":"Not found"}`))
   147  	}))
   148  	defer dataServer.Close()
   149  
   150  	client, err := mockClient(server, dataServer)
   151  	if err != nil {
   152  		t.Fatal(err)
   153  	}
   154  	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond)
   155  	defer cancel()
   156  	_, err = client.GetNumberMessagesDelivery("20190418").WithContext(ctx).Do()
   157  	expectCtxDeadlineExceed(ctx, err, t)
   158  }
   159  
   160  func BenchmarkGetNumberMessagesDelivery(b *testing.B) {
   161  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   162  		defer r.Body.Close()
   163  		w.Write([]byte(`{
   164  			"status": "ready",
   165  			"broadcast": 5385,
   166  			"targeting": 522
   167  		}`))
   168  	}))
   169  	defer server.Close()
   170  
   171  	dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   172  		defer r.Body.Close()
   173  		b.Error("Unexpected Data API call")
   174  		w.WriteHeader(404)
   175  		w.Write([]byte(`{"message":"Not found"}`))
   176  	}))
   177  	defer dataServer.Close()
   178  
   179  	client, err := mockClient(server, dataServer)
   180  	if err != nil {
   181  		b.Fatal(err)
   182  	}
   183  	b.ResetTimer()
   184  	for i := 0; i < b.N; i++ {
   185  		client.GetNumberMessagesDelivery("20190418").Do()
   186  	}
   187  }
   188  
   189  func TestGetNumberFollowers(t *testing.T) {
   190  	type want struct {
   191  		URLPath     string
   192  		RequestBody []byte
   193  		Response    *MessagesNumberFollowersResponse
   194  		Error       error
   195  	}
   196  	testCases := []struct {
   197  		Label        string
   198  		Date         string
   199  		ResponseCode int
   200  		Response     []byte
   201  		Want         want
   202  	}{
   203  		{
   204  			Label:        "Success",
   205  			Date:         "20190418",
   206  			ResponseCode: 200,
   207  			Response: []byte(`{
   208  				"status": "ready",
   209  				"followers": 7620,
   210  				"targetedReaches": 5848,
   211  				"blocks": 237
   212  			}`),
   213  			Want: want{
   214  				URLPath:     fmt.Sprintf(APIEndpointInsight, InsightTypeFollowers),
   215  				RequestBody: []byte(""),
   216  				Response: &MessagesNumberFollowersResponse{
   217  					Status:          "ready",
   218  					Followers:       7620,
   219  					TargetedReaches: 5848,
   220  					Blocks:          237,
   221  				},
   222  			},
   223  		},
   224  		{
   225  			Label:        "Internal server error",
   226  			Date:         "20190418",
   227  			ResponseCode: 500,
   228  			Response:     []byte("500 Internal server error"),
   229  			Want: want{
   230  				URLPath:     fmt.Sprintf(APIEndpointInsight, InsightTypeFollowers),
   231  				RequestBody: []byte(""),
   232  				Error: &APIError{
   233  					Code: 500,
   234  				},
   235  			},
   236  		},
   237  	}
   238  
   239  	var currentTestIdx int
   240  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   241  		defer r.Body.Close()
   242  		tc := testCases[currentTestIdx]
   243  		if r.Method != http.MethodGet {
   244  			t.Errorf("Method %s; want %s", r.Method, http.MethodGet)
   245  		}
   246  		if r.URL.Path != tc.Want.URLPath {
   247  			t.Errorf("URLPath %s; want %s", r.URL.Path, tc.Want.URLPath)
   248  		}
   249  		body, err := io.ReadAll(r.Body)
   250  		if err != nil {
   251  			t.Fatal(err)
   252  		}
   253  		if !reflect.DeepEqual(body, tc.Want.RequestBody) {
   254  			t.Errorf("RequestBody %s; want %s", body, tc.Want.RequestBody)
   255  		}
   256  		w.WriteHeader(tc.ResponseCode)
   257  		w.Write(tc.Response)
   258  	}))
   259  	defer server.Close()
   260  
   261  	dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   262  		defer r.Body.Close()
   263  		t.Error("Unexpected Data API call")
   264  		w.WriteHeader(404)
   265  		w.Write([]byte(`{"message":"Not found"}`))
   266  	}))
   267  	defer dataServer.Close()
   268  
   269  	client, err := mockClient(server, dataServer)
   270  	if err != nil {
   271  		t.Fatal(err)
   272  	}
   273  	for i, tc := range testCases {
   274  		currentTestIdx = i
   275  		t.Run(strconv.Itoa(i)+"/"+tc.Label, func(t *testing.T) {
   276  			res, err := client.GetNumberFollowers(tc.Date).Do()
   277  			if tc.Want.Error != nil {
   278  				if !reflect.DeepEqual(err, tc.Want.Error) {
   279  					t.Errorf("Error %v; want %v", err, tc.Want.Error)
   280  				}
   281  			} else {
   282  				if err != nil {
   283  					t.Error(err)
   284  				}
   285  			}
   286  			if !reflect.DeepEqual(res, tc.Want.Response) {
   287  				t.Errorf("Response %v; want %v", res, tc.Want.Response)
   288  			}
   289  		})
   290  	}
   291  }
   292  
   293  func TestGetNumberFollowersContext(t *testing.T) {
   294  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   295  		defer r.Body.Close()
   296  		time.Sleep(10 * time.Millisecond)
   297  		w.Write([]byte("{}"))
   298  	}))
   299  	defer server.Close()
   300  
   301  	dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   302  		defer r.Body.Close()
   303  		t.Error("Unexpected Data API call")
   304  		w.WriteHeader(404)
   305  		w.Write([]byte(`{"message":"Not found"}`))
   306  	}))
   307  	defer dataServer.Close()
   308  
   309  	client, err := mockClient(server, dataServer)
   310  	if err != nil {
   311  		t.Fatal(err)
   312  	}
   313  	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond)
   314  	defer cancel()
   315  	_, err = client.GetNumberFollowers("20190418").WithContext(ctx).Do()
   316  	expectCtxDeadlineExceed(ctx, err, t)
   317  }
   318  
   319  func BenchmarkGetNumberFollowers(b *testing.B) {
   320  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   321  		defer r.Body.Close()
   322  		w.Write([]byte(`{
   323  			"status": "ready",
   324  			"followers": 7620,
   325  			"targetedReaches": 5848,
   326  			"blocks": 237
   327  		}`))
   328  	}))
   329  	defer server.Close()
   330  
   331  	dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   332  		defer r.Body.Close()
   333  		b.Error("Unexpected Data API call")
   334  		w.WriteHeader(404)
   335  		w.Write([]byte(`{"message":"Not found"}`))
   336  	}))
   337  	defer dataServer.Close()
   338  
   339  	client, err := mockClient(server, dataServer)
   340  	if err != nil {
   341  		b.Fatal(err)
   342  	}
   343  	b.ResetTimer()
   344  	for i := 0; i < b.N; i++ {
   345  		client.GetNumberFollowers("20190418").Do()
   346  	}
   347  }
   348  
   349  func TestGetFriendDemographics(t *testing.T) {
   350  	type want struct {
   351  		URLPath     string
   352  		RequestBody []byte
   353  		Response    *MessagesFriendDemographicsResponse
   354  		Error       error
   355  	}
   356  	testCases := []struct {
   357  		Label        string
   358  		ResponseCode int
   359  		Response     []byte
   360  		Want         want
   361  	}{
   362  		{
   363  			Label:        "Success",
   364  			ResponseCode: 200,
   365  			Response: []byte(`{
   366  				"available": true,
   367  				"genders": [
   368  					{
   369  						"gender": "unknown",
   370  						"percentage": 37.6
   371  					}
   372  				],
   373  				"ages": [
   374  					{
   375  						"age": "unknown",
   376  						"percentage": 37.6
   377  					}
   378  				],
   379  				"areas": [
   380  					{
   381  						"area": "unknown",
   382  						"percentage": 42.9
   383  					}
   384  				],
   385  				"appTypes": [
   386  					{
   387  						"appType": "ios",
   388  						"percentage": 62.4
   389  					}
   390  				],
   391  				"subscriptionPeriods": [
   392  					{
   393  						"subscriptionPeriod": "over365days",
   394  						"percentage": 96.4
   395  					}
   396  				]
   397  			}`),
   398  			Want: want{
   399  				URLPath:     fmt.Sprintf(APIEndpointInsight, InsightTypeDemographic),
   400  				RequestBody: []byte(""),
   401  				Response: &MessagesFriendDemographicsResponse{
   402  					Available: true,
   403  					Genders: []GenderDetail{
   404  						{Gender: "unknown", Percentage: 37.6},
   405  					},
   406  					Ages: []AgeDetail{
   407  						{Age: "unknown", Percentage: 37.6},
   408  					},
   409  					Areas: []AreasDetail{
   410  						{Area: "unknown", Percentage: 42.9},
   411  					},
   412  					AppTypes: []AppTypeDetail{
   413  						{AppType: "ios", Percentage: 62.4},
   414  					},
   415  					SubscriptionPeriods: []SubscriptionPeriodDetail{
   416  						{SubscriptionPeriod: "over365days", Percentage: 96.4},
   417  					},
   418  				},
   419  			},
   420  		},
   421  		{
   422  			Label:        "Internal server error",
   423  			ResponseCode: 500,
   424  			Response:     []byte("500 Internal server error"),
   425  			Want: want{
   426  				URLPath:     fmt.Sprintf(APIEndpointInsight, InsightTypeDemographic),
   427  				RequestBody: []byte(""),
   428  				Error: &APIError{
   429  					Code: 500,
   430  				},
   431  			},
   432  		},
   433  	}
   434  
   435  	var currentTestIdx int
   436  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   437  		defer r.Body.Close()
   438  		tc := testCases[currentTestIdx]
   439  		if r.Method != http.MethodGet {
   440  			t.Errorf("Method %s; want %s", r.Method, http.MethodGet)
   441  		}
   442  		if r.URL.Path != tc.Want.URLPath {
   443  			t.Errorf("URLPath %s; want %s", r.URL.Path, tc.Want.URLPath)
   444  		}
   445  		body, err := io.ReadAll(r.Body)
   446  		if err != nil {
   447  			t.Fatal(err)
   448  		}
   449  		if !reflect.DeepEqual(body, tc.Want.RequestBody) {
   450  			t.Errorf("RequestBody %s; want %s", body, tc.Want.RequestBody)
   451  		}
   452  		w.WriteHeader(tc.ResponseCode)
   453  		w.Write(tc.Response)
   454  	}))
   455  	defer server.Close()
   456  
   457  	dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   458  		defer r.Body.Close()
   459  		t.Error("Unexpected Data API call")
   460  		w.WriteHeader(404)
   461  		w.Write([]byte(`{"message":"Not found"}`))
   462  	}))
   463  	defer dataServer.Close()
   464  
   465  	client, err := mockClient(server, dataServer)
   466  	if err != nil {
   467  		t.Fatal(err)
   468  	}
   469  	for i, tc := range testCases {
   470  		currentTestIdx = i
   471  		t.Run(strconv.Itoa(i)+"/"+tc.Label, func(t *testing.T) {
   472  			res, err := client.GetFriendDemographics().Do()
   473  			if tc.Want.Error != nil {
   474  				if !reflect.DeepEqual(err, tc.Want.Error) {
   475  					t.Errorf("Error %v; want %v", err, tc.Want.Error)
   476  				}
   477  			} else {
   478  				if err != nil {
   479  					t.Error(err)
   480  				}
   481  			}
   482  			if !reflect.DeepEqual(res, tc.Want.Response) {
   483  				t.Errorf("Response %v; want %v", res, tc.Want.Response)
   484  			}
   485  		})
   486  	}
   487  }
   488  
   489  func TestGetFriendDemographicsContext(t *testing.T) {
   490  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   491  		defer r.Body.Close()
   492  		time.Sleep(10 * time.Millisecond)
   493  		w.Write([]byte("{}"))
   494  	}))
   495  	defer server.Close()
   496  
   497  	dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   498  		defer r.Body.Close()
   499  		t.Error("Unexpected Data API call")
   500  		w.WriteHeader(404)
   501  		w.Write([]byte(`{"message":"Not found"}`))
   502  	}))
   503  	defer dataServer.Close()
   504  
   505  	client, err := mockClient(server, dataServer)
   506  	if err != nil {
   507  		t.Fatal(err)
   508  	}
   509  	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond)
   510  	defer cancel()
   511  	_, err = client.GetFriendDemographics().WithContext(ctx).Do()
   512  	expectCtxDeadlineExceed(ctx, err, t)
   513  }
   514  
   515  func BenchmarkGetFriendDemographics(b *testing.B) {
   516  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   517  		defer r.Body.Close()
   518  		w.Write([]byte(`{
   519  			"available": true,
   520  			"genders": [
   521  				{
   522  					"gender": "unknown",
   523  					"percentage": 37.6
   524  				}
   525  			],
   526  			"ages": [
   527  				{
   528  					"age": "unknown",
   529  					"percentage": 37.6
   530  				}
   531  			],
   532  			"areas": [
   533  				{
   534  					"area": "unknown",
   535  					"percentage": 42.9
   536  				}
   537  			],
   538  			"appTypes": [
   539  				{
   540  					"appType": "ios",
   541  					"percentage": 62.4
   542  				}
   543  			],
   544  			"subscriptionPeriods": [
   545  				{
   546  					"subscriptionPeriod": "over365days",
   547  					"percentage": 96.4
   548  				}
   549  			]
   550  		}`))
   551  	}))
   552  	defer server.Close()
   553  
   554  	dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   555  		defer r.Body.Close()
   556  		b.Error("Unexpected Data API call")
   557  		w.WriteHeader(404)
   558  		w.Write([]byte(`{"message":"Not found"}`))
   559  	}))
   560  	defer dataServer.Close()
   561  
   562  	client, err := mockClient(server, dataServer)
   563  	if err != nil {
   564  		b.Fatal(err)
   565  	}
   566  	b.ResetTimer()
   567  	for i := 0; i < b.N; i++ {
   568  		client.GetFriendDemographics().Do()
   569  	}
   570  }
   571  
   572  func TestGetUserInteractionStats(t *testing.T) {
   573  	type want struct {
   574  		URLPath     string
   575  		RequestBody []byte
   576  		Response    *MessagesUserInteractionStatsResponse
   577  		Error       error
   578  	}
   579  	testCases := []struct {
   580  		Label        string
   581  		RequestID    string
   582  		ResponseCode int
   583  		Response     []byte
   584  		Want         want
   585  	}{
   586  		{
   587  			Label:        "Success",
   588  			RequestID:    "f70dd685-499a-4231-a441-f24b8d4fba21",
   589  			ResponseCode: 200,
   590  			Response: []byte(`{
   591  				"overview": {
   592  					"requestId": "f70dd685-499a-4231-a441-f24b8d4fba21",
   593  					"timestamp": 1568214000,
   594  					"delivered": 32,
   595  					"uniqueImpression": 4,
   596  					"uniqueClick": null,
   597  					"uniqueMediaPlayed": 2,
   598  					"uniqueMediaPlayed100Percent": -1
   599  				},
   600  				"messages": [
   601  					{
   602  						"seq": 1,
   603  						"impression": 18,
   604  						"mediaPlayed": 11,
   605  						"mediaPlayed25Percent": -1,
   606  						"mediaPlayed50Percent": -1,
   607  						"mediaPlayed75Percent": -1,
   608  						"mediaPlayed100Percent": -1,
   609  						"uniqueMediaPlayed": 2,
   610  						"uniqueMediaPlayed25Percent": -1,
   611  						"uniqueMediaPlayed50Percent": -1,
   612  						"uniqueMediaPlayed75Percent": -1,
   613  						"uniqueMediaPlayed100Percent": -1
   614  					}
   615  				],
   616  				"clicks": [
   617  					{
   618  						"seq": 1,
   619  						"url": "https://www.yahoo.co.jp/",
   620  						"click": -1,
   621  						"uniqueClick": -1,
   622  						"uniqueClickOfRequest": -1
   623  					},
   624  					{
   625  						"seq": 1,
   626  						"url": "https://www.google.com/?hl=ja",
   627  						"click": -1,
   628  						"uniqueClick": -1,
   629  						"uniqueClickOfRequest": -1
   630  					}
   631  				]
   632  			}`),
   633  			Want: want{
   634  				URLPath:     fmt.Sprintf(APIEndpointInsight, InsightTypeUserInteractionStats),
   635  				RequestBody: []byte(""),
   636  				Response: &MessagesUserInteractionStatsResponse{
   637  					Overview: OverviewDetail{
   638  						RequestID:                   "f70dd685-499a-4231-a441-f24b8d4fba21",
   639  						Timestamp:                   1568214000,
   640  						Delivered:                   32,
   641  						UniqueImpression:            4,
   642  						UniqueClick:                 0,
   643  						UniqueMediaPlayed:           2,
   644  						UniqueMediaPlayed100Percent: -1,
   645  					},
   646  					Messages: []MessageDetail{
   647  						{
   648  							Seq:                         1,
   649  							Impression:                  18,
   650  							MediaPlayed:                 11,
   651  							MediaPlayed25Percent:        -1,
   652  							MediaPlayed50Percent:        -1,
   653  							MediaPlayed75Percent:        -1,
   654  							MediaPlayed100Percent:       -1,
   655  							UniqueMediaPlayed:           2,
   656  							UniqueMediaPlayed25Percent:  -1,
   657  							UniqueMediaPlayed50Percent:  -1,
   658  							UniqueMediaPlayed75Percent:  -1,
   659  							UniqueMediaPlayed100Percent: -1,
   660  						},
   661  					},
   662  					Clicks: []ClickDetail{
   663  						{
   664  							Seq:                  1,
   665  							URL:                  "https://www.yahoo.co.jp/",
   666  							Click:                -1,
   667  							UniqueClick:          -1,
   668  							UniqueClickOfRequest: -1,
   669  						},
   670  						{
   671  							Seq:                  1,
   672  							URL:                  "https://www.google.com/?hl=ja",
   673  							Click:                -1,
   674  							UniqueClick:          -1,
   675  							UniqueClickOfRequest: -1,
   676  						},
   677  					},
   678  				},
   679  			},
   680  		},
   681  		{
   682  			Label:        "Internal server error",
   683  			ResponseCode: 500,
   684  			Response:     []byte("500 Internal server error"),
   685  			Want: want{
   686  				URLPath:     fmt.Sprintf(APIEndpointInsight, InsightTypeUserInteractionStats),
   687  				RequestBody: []byte(""),
   688  				Error: &APIError{
   689  					Code: 500,
   690  				},
   691  			},
   692  		},
   693  	}
   694  
   695  	var currentTestIdx int
   696  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   697  		defer r.Body.Close()
   698  		tc := testCases[currentTestIdx]
   699  		if r.Method != http.MethodGet {
   700  			t.Errorf("Method %s; want %s", r.Method, http.MethodGet)
   701  		}
   702  		if r.URL.Path != tc.Want.URLPath {
   703  			t.Errorf("URLPath %s; want %s", r.URL.Path, tc.Want.URLPath)
   704  		}
   705  		body, err := io.ReadAll(r.Body)
   706  		if err != nil {
   707  			t.Fatal(err)
   708  		}
   709  		if !reflect.DeepEqual(body, tc.Want.RequestBody) {
   710  			t.Errorf("RequestBody %s; want %s", body, tc.Want.RequestBody)
   711  		}
   712  		w.WriteHeader(tc.ResponseCode)
   713  		w.Write(tc.Response)
   714  	}))
   715  	defer server.Close()
   716  
   717  	dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   718  		defer r.Body.Close()
   719  		t.Error("Unexpected Data API call")
   720  		w.WriteHeader(404)
   721  		w.Write([]byte(`{"message":"Not found"}`))
   722  	}))
   723  	defer dataServer.Close()
   724  
   725  	client, err := mockClient(server, dataServer)
   726  	if err != nil {
   727  		t.Fatal(err)
   728  	}
   729  	for i, tc := range testCases {
   730  		currentTestIdx = i
   731  		t.Run(strconv.Itoa(i)+"/"+tc.Label, func(t *testing.T) {
   732  			res, err := client.GetUserInteractionStats(tc.RequestID).Do()
   733  			if tc.Want.Error != nil {
   734  				if !reflect.DeepEqual(err, tc.Want.Error) {
   735  					t.Errorf("Error %v; want %v", err, tc.Want.Error)
   736  				}
   737  			} else {
   738  				if err != nil {
   739  					t.Error(err)
   740  				}
   741  			}
   742  			if !reflect.DeepEqual(res, tc.Want.Response) {
   743  				t.Errorf("Response %v; want %v", res, tc.Want.Response)
   744  			}
   745  		})
   746  	}
   747  }
   748  
   749  func TestGetUserInteractionStatsContext(t *testing.T) {
   750  	server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   751  		defer r.Body.Close()
   752  		time.Sleep(10 * time.Millisecond)
   753  		w.Write([]byte("{}"))
   754  	}))
   755  	defer server.Close()
   756  
   757  	dataServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   758  		defer r.Body.Close()
   759  		t.Error("Unexpected Data API call")
   760  		w.WriteHeader(404)
   761  		w.Write([]byte(`{"message":"Not found"}`))
   762  	}))
   763  	defer dataServer.Close()
   764  
   765  	client, err := mockClient(server, dataServer)
   766  	if err != nil {
   767  		t.Fatal(err)
   768  	}
   769  	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond)
   770  	defer cancel()
   771  	_, err = client.GetUserInteractionStats("f70dd685-499a-4231-a441-f24b8d4fba21").WithContext(ctx).Do()
   772  	expectCtxDeadlineExceed(ctx, err, t)
   773  }