Repository: Yoctol/bottender
Pull request #768 (2020-05-11 09:06:42)

refactor(Line): avoid custom access token in context
Create a new client in LineConnector if `mapDestinationToAccessToken` is provided.


Patch:
diff --git a/packages/bottender/src/line/LineConnector.ts b/packages/bottender/src/line/LineConnector.ts
index 5ef09f8c..0b0566a4 100644
--- a/packages/bottender/src/line/LineConnector.ts
+++ b/packages/bottender/src/line/LineConnector.ts
@@ -44,6 +44,8 @@ export default class LineConnector
 
   _channelSecret: string;
 
+  _origin: string | undefined = undefined;
+
   _skipLegacyProfile: boolean;
 
   _mapDestinationToAccessToken:
@@ -84,6 +86,7 @@ export default class LineConnector
       });
 
       this._channelSecret = channelSecret;
+      this._origin = origin;
     }
 
     this._mapDestinationToAccessToken = mapDestinationToAccessToken || null;
@@ -292,23 +295,28 @@ export default class LineConnector
     requestContext?: RequestContext;
     emitter?: EventEmitter | null;
   }): Promise<LineContext> {
-    let customAccessToken;
+    let client = this._client;
     if (this._mapDestinationToAccessToken) {
       const { destination } = params.event;
 
       if (!destination) {
         warning(false, 'Could not find destination from request body.');
       } else {
-        customAccessToken = await this._mapDestinationToAccessToken(
+        const customAccessToken = await this._mapDestinationToAccessToken(
           destination
         );
+
+        client = LineClient.connect({
+          accessToken: customAccessToken,
+          channelSecret: this._channelSecret,
+          origin: this._origin,
+        });
       }
     }
 
     return new LineContext({
       ...params,
-      client: this._client,
-      customAccessToken,
+      client,
       shouldBatch: this._shouldBatch,
       sendMethod: this._sendMethod,
     });
diff --git a/packages/bottender/src/line/LineContext.ts b/packages/bottender/src/line/LineContext.ts
index 20c1cc4a..87acce57 100644
--- a/packages/bottender/src/line/LineContext.ts
+++ b/packages/bottender/src/line/LineContext.ts
@@ -25,8 +25,6 @@ type Options = {
 };
 
 class LineContext extends Context<LineClient, LineEvent> {
-  _customAccessToken: string | null;
-
   _isReplied = false;
 
   _shouldBatch: boolean;
@@ -49,9 +47,13 @@ class LineContext extends Context<LineClient, LineEvent> {
     emitter,
   }: Options) {
     super({ client, event, session, initialState, requestContext, emitter });
-    this._customAccessToken = customAccessToken || null;
     this._shouldBatch = shouldBatch || false;
     this._sendMethod = sendMethod || 'reply';
+
+    // TODO: remove this in v2
+    if (customAccessToken) {
+      this.useAccessToken(customAccessToken);
+    }
   }
 
   /**
@@ -67,7 +69,7 @@ class LineContext extends Context<LineClient, LineEvent> {
    *
    */
   get accessToken(): string {
-    return this._customAccessToken || this._client.accessToken;
+    return this._client.accessToken;
   }
 
   /**
@@ -75,7 +77,8 @@ class LineContext extends Context<LineClient, LineEvent> {
    *
    */
   useAccessToken(accessToken: string) {
-    this._customAccessToken = accessToken;
+    warning(false, '`useAccessToken` is deprecated.');
+    this._client._accessToken = accessToken;
   }
 
   /**
@@ -101,11 +104,7 @@ class LineContext extends Context<LineClient, LineEvent> {
           'one replyToken can only be used to reply 5 messages'
         );
         if (this._event.replyToken) {
-          await this._client.reply(this._event.replyToken, messageChunks[0], {
-            ...(this._customAccessToken
-              ? { accessToken: this._customAccessToken }
-              : undefined),
-          });
+          await this._client.reply(this._event.replyToken, messageChunks[0]);
         }
       }
 
@@ -119,11 +118,7 @@ class LineContext extends Context<LineClient, LineEvent> {
             const messages = messageChunks[i];
 
             // eslint-disable-next-line no-await-in-loop
-            await this._client.push(sessionTypeId, messages, {
-              ...(this._customAccessToken
-                ? { accessToken: this._customAccessToken }
-                : undefined),
-            });
+            await this._client.push(sessionTypeId, messages);
           }
         } else {
           warning(
@@ -160,11 +155,7 @@ class LineContext extends Context<LineClient, LineEvent> {
 
     const messageId = (this._event.message as any).id;
 
-    return this._client.getMessageContent(messageId, {
-      ...(this._customAccessToken
-        ? { accessToken: this._customAccessToken }
-        : undefined),
-    });
+    return this._client.getMessageContent(messageId);
   }
 
   /**
@@ -179,17 +170,9 @@ class LineContext extends Context<LineClient, LineEvent> {
 
     switch (this._session.type) {
       case 'room':
-        return this._client.leaveRoom(this._session.room.id, {
-          ...(this._customAccessToken
-            ? { accessToken: this._customAccessToken }
-            : undefined),
-        } as any);
+        return this._client.leaveRoom(this._session.room.id);
       case 'group':
-        return this._client.leaveGroup(this._session.group.id, {
-          ...(this._customAccessToken
-            ? { accessToken: this._customAccessToken }
-            : undefined),
-        } as any);
+        return this._client.leaveGroup(this._session.group.id);
       default:
         warning(
           false,
@@ -223,30 +206,16 @@ class LineContext extends Context<LineClient, LineEvent> {
       case 'room':
         return this._client.getRoomMemberProfile(
           this._session.room.id,
-          this._session.user.id,
-          {
-            ...(this._customAccessToken
-              ? { accessToken: this._customAccessToken }
-              : undefined),
-          } as any
+          this._session.user.id
         );
       case 'group':
         return this._client.getGroupMemberProfile(
           this._session.group.id,
-          this._session.user.id,
-          {
-            ...(this._customAccessToken
-              ? { accessToken: this._customAccessToken }
-              : undefined),
-          } as any
+          this._session.user.id
         );
       case 'user':
       default:
-        return this._client.getUserProfile(this._session.user.id, {
-          ...(this._customAccessToken
-            ? { accessToken: this._customAccessToken }
-            : undefined),
-        } as any);
+        return this._client.getUserProfile(this._session.user.id);
     }
   }
 
@@ -266,24 +235,11 @@ class LineContext extends Context<LineClient, LineEvent> {
 
     switch (this._session.type) {
       case 'room':
-        return this._client.getRoomMemberProfile(
-          this._session.room.id,
-          userId,
-          {
-            ...(this._customAccessToken
-              ? { accessToken: this._customAccessToken }
-              : undefined),
-          } as any
-        );
+        return this._client.getRoomMemberProfile(this._session.room.id, userId);
       case 'group':
         return this._client.getGroupMemberProfile(
           this._session.group.id,
-          userId,
-          {
-            ...(this._customAccessToken
-              ? { accessToken: this._customAccessToken }
-              : undefined),
-          } as any
+          userId
         );
       default:
         warning(
@@ -312,17 +268,9 @@ class LineContext extends Context<LineClient, LineEvent> {
 
     switch (this._session.type) {
       case 'room':
-        return this._client.getRoomMemberIds(this._session.room.id, start, {
-          ...(this._customAccessToken
-            ? { accessToken: this._customAccessToken }
-            : undefined),
-        } as any);
+        return this._client.getRoomMemberIds(this._session.room.id, start);
       case 'group':
-        return this._client.getGroupMemberIds(this._session.group.id, start, {
-          ...(this._customAccessToken
-            ? { accessToken: this._customAccessToken }
-            : undefined),
-        } as any);
+        return this._client.getGroupMemberIds(this._session.group.id, start);
       default:
         warning(
           false,
@@ -349,17 +297,9 @@ class LineContext extends Context<LineClient, LineEvent> {
 
     switch (this._session.type) {
       case 'room':
-        return this._client.getAllRoomMemberIds(this._session.room.id, {
-          ...(this._customAccessToken
-            ? { accessToken: this._customAccessToken }
-            : undefined),
-        });
+        return this._client.getAllRoomMemberIds(this._session.room.id);
       case 'group':
-        return this._client.getAllGroupMemberIds(this._session.group.id, {
-          ...(this._customAccessToken
-            ? { accessToken: this._customAccessToken }
-            : undefined),
-        });
+        return this._client.getAllGroupMemberIds(this._session.group.id);
       default:
         warning(
           false,
@@ -375,11 +315,7 @@ class LineContext extends Context<LineClient, LineEvent> {
    */
   async getLinkedRichMenu(): Promise<any> {
     if (this._session && this._session.user) {
-      return this._client.getLinkedRichMenu(this._session.user.id, {
-        ...(this._customAccessToken
-          ? { accessToken: this._customAccessToken }
-          : undefined),
-      } as any);
+      return this._client.getLinkedRichMenu(this._session.user.id);
     }
     warning(
       false,
@@ -393,11 +329,7 @@ class LineContext extends Context<LineClient, LineEvent> {
    */
   async linkRichMenu(richMenuId: string): Promise<any> {
     if (this._session && this._session.user) {
-      return this._client.linkRichMenu(this._session.user.id, richMenuId, {
-        ...(this._customAccessToken
-          ? { accessToken: this._customAccessToken }
-          : undefined),
-      } as any);
+      return this._client.linkRichMenu(this._session.user.id, richMenuId);
     }
     warning(
       false,
@@ -411,11 +343,7 @@ class LineContext extends Context<LineClient, LineEvent> {
    */
   async unlinkRichMenu(): Promise<any> {
     if (this._session && this._session.user) {
-      return this._client.unlinkRichMenu(this._session.user.id, {
-        ...(this._customAccessToken
-          ? { accessToken: this._customAccessToken }
-          : undefined),
-      } as any);
+      return this._client.unlinkRichMenu(this._session.user.id);
     }
     warning(
       false,
@@ -429,11 +357,7 @@ class LineContext extends Context<LineClient, LineEvent> {
    */
   async issueLinkToken(): Promise<any> {
     if (this._session && this._session.user) {
-      return this._client.issueLinkToken(this._session.user.id, {
-        ...(this._customAccessToken
-          ? { accessToken: this._customAccessToken }
-          : undefined),
-      } as any);
+      return this._client.issueLinkToken(this._session.user.id);
     }
     warning(
       false,
@@ -441,7 +365,7 @@ class LineContext extends Context<LineClient, LineEvent> {
     );
   }
 
-  reply(messages: LineTypes.Message[], options: LineTypes.MessageOptions = {}) {
+  reply(messages: LineTypes.Message[]) {
     invariant(!this._isReplied, 'Can not reply event multiple times');
 
     if (this._shouldBatch) {
@@ -453,19 +377,14 @@ class LineContext extends Context<LineClient, LineEvent> {
     this._isReplied = true;
 
     // FIXME: throw or warn for no replyToken
-    return this._client.reply(this._event.replyToken as string, messages, {
-      ...(this._customAccessToken
-        ? { accessToken: this._customAccessToken }
-        : undefined),
-      ...options,
-    });
+    return this._client.reply(this._event.replyToken as string, messages);
   }
 
   replyText(
     text: string,
     options?: LineTypes.MessageOptions & { emojis?: LineTypes.Emoji[] }
   ) {
-    return this.reply([Line.createText(text, options)], options);
+    return this.reply([Line.createText(text, options)]);
   }
 
   replyImage(
@@ -475,7 +394,7 @@ class LineContext extends Context<LineClient, LineEvent> {
     },
     options?: LineTypes.MessageOptions
   ) {
-    return this.reply([Line.createImage(image, options)], options);
+    return this.reply([Line.createImage(image, options)]);
   }
 
   replyVideo(
@@ -485,7 +404,7 @@ class LineContext extends Context<LineClient, LineEvent> {
     },
     options?: LineTypes.MessageOptions
   ) {
-    return this.reply([Line.createVideo(video, options)], options);
+    return this.reply([Line.createVideo(video, options)]);
   }
 
   replyAudio(
@@ -495,21 +414,21 @@ class LineContext extends Context<LineClient, LineEvent> {
     },
     options?: LineTypes.MessageOptions
   ) {
-    return this.reply([Line.createAudio(audio, options)], options);
+    return this.reply([Line.createAudio(audio, options)]);
   }
 
   replyLocation(
     location: LineTypes.Location,
     options?: LineTypes.MessageOptions
   ) {
-    return this.reply([Line.createLocation(location, options)], options);
+    return this.reply([Line.createLocation(location, options)]);
   }
 
   replySticker(
     sticker: Omit<LineTypes.StickerMessage, 'type'>,
     options?: LineTypes.MessageOptions
   ) {
-    return this.reply([Line.createSticker(sticker, options)], options);
+    return this.reply([Line.createSticker(sticker, options)]);
   }
 
   replyImagemap(
@@ -517,10 +436,7 @@ class LineContext extends Context<LineClient, LineEvent> {
     imagemap: Omit<LineTypes.ImagemapMessage, 'type' | 'altText'>,
     options?: LineTypes.MessageOptions
   ) {
-    return this.reply(
-      [Line.createImagemap(altText, imagemap, options)],
-      options
-    );
+    return this.reply([Line.createImagemap(altText, imagemap, options)]);
   }
 
   replyFlex(
@@ -528,7 +444,7 @@ class LineContext extends Context<LineClient, LineEvent> {
     flex: LineTypes.FlexContainer,
     options?: LineTypes.MessageOptions
   ) {
-    return this.reply([Line.createFlex(altText, flex, options)], options);
+    return this.reply([Line.createFlex(altText, flex, options)]);
   }
 
   replyTemplate(
@@ -536,10 +452,7 @@ class LineContext extends Context<LineClient, LineEvent> {
     template: LineTypes.Template,
     options?: LineTypes.MessageOptions
   ) {
-    return this.reply(
-      [Line.createTemplate(altText, template, options)],
-      options
-    );
+    return this.reply([Line.createTemplate(altText, template, options)]);
   }
 
   replyButtonTemplate(
@@ -547,10 +460,9 @@ class LineContext extends Context<LineClient, LineEvent> {
     buttonTemplate: Omit<LineTypes.ButtonsTemplate, 'type'>,
     options?: LineTypes.MessageOptions
   ) {
-    return this.reply(
-      [Line.createButtonTemplate(altText, buttonTemplate, options)],
-      options
-    );
+    return this.reply([
+      Line.createButtonTemplate(altText, buttonTemplate, options),
+    ]);
   }
 
   replyButtonsTemplate(
@@ -566,34 +478,20 @@ class LineContext extends Context<LineClient, LineEvent> {
     confirmTemplate: Omit<LineTypes.ConfirmTemplate, 'type'>,
     options: LineTypes.MessageOptions
   ) {
-    return this.reply(
-      [Line.createConfirmTemplate(altText, confirmTemplate, options)],
-      options
-    );
+    return this.reply([
+      Line.createConfirmTemplate(altText, confirmTemplate, options),
+    ]);
   }
 
   replyCarouselTemplate(
     altText: string,
     columns: LineTypes.ColumnObject[],
-    {
-      imageAspectRatio,
-      imageSize,
-      ...options
-    }: {
+    options: {
       imageAspectRatio?: 'rectangle' | 'square';
       imageSize?: 'cover' | 'contain';
-    } & LineTypes.MessageOptions = {}
-  ) {
-    return this.reply(
-      [
-        Line.createCarouselTemplate(altText, columns, {
-          imageAspectRatio,
-          imageSize,
-          ...options,
-        }),
-      ],
-      options
-    );
+    } & LineTypes.MessageOptions
+  ) {
+    return this.reply([Line.createCarouselTemplate(altText, columns, options)]);
   }
 
   replyImageCarouselTemplate(
@@ -601,13 +499,12 @@ class LineContext extends Context<LineClient, LineEvent> {
     columns: LineTypes.ImageCarouselColumnObject[],
     options: LineTypes.MessageOptions
   ) {
-    return this.reply(
-      [Line.createImageCarouselTemplate(altText, columns, options)],
-      options
-    );
+    return this.reply([
+      Line.createImageCarouselTemplate(altText, columns, options),
+    ]);
   }
 
-  push(messages: LineTypes.Message[], options: LineTypes.MessageOptions = {}) {
+  push(messages: LineTypes.Message[]) {
     if (!this._session) {
       warning(false, `push: should not be called in context without session`);
       return;
@@ -619,19 +516,14 @@ class LineContext extends Context<LineClient, LineEvent> {
     }
 
     const sessionType = this._session.type;
-    return this._client.push(this._session[sessionType].id, messages, {
-      ...(this._customAccessToken
-        ? { accessToken: this._customAccessToken }
-        : undefined),
-      ...options,
-    });
+    return this._client.push(this._session[sessionType].id, messages);
   }
 
   pushText(
     text: string,
     options?: LineTypes.MessageOptions & { emojis?: LineTypes.Emoji[] }
   ) {
-    return this.push([Line.createText(text, options)], options);
+    return this.push([Line.createText(text, options)]);
   }
 
   pushImage(
@@ -641,7 +533,7 @@ class LineContext extends Context<LineClient, LineEvent> {
     },
     options?: LineTypes.MessageOptions
   ) {
-    return this.push([Line.createImage(image, options)], options);
+    return this.push([Line.createImage(image, options)]);
   }
 
   pushVideo(
@@ -651,7 +543,7 @@ class LineContext extends Context<LineClient, LineEvent> {
     },
     options?: LineTypes.MessageOptions
   ) {
-    return this.push([Line.createVideo(video, options)], options);
+    return this.push([Line.createVideo(video, options)]);
   }
 
   pushAudio(
@@ -661,21 +553,21 @@ class LineContext extends Context<LineClient, LineEvent> {
     },
     options?: LineTypes.MessageOptions
   ) {
-    return this.push([Line.createAudio(audio, options)], options);
+    return this.push([Line.createAudio(audio, options)]);
   }
 
   pushLocation(
     location: LineTypes.Location,
     options?: LineTypes.MessageOptions
   ) {
-    return this.push([Line.createLocation(location, options)], options);
+    return this.push([Line.createLocation(location, options)]);
   }
 
   pushSticker(
     sticker: Omit<LineTypes.StickerMessage, 'type'>,
     options?: LineTypes.MessageOptions
   ) {
-    return this.push([Line.createSticker(sticker, options)], options);
+    return this.push([Line.createSticker(sticker, options)]);
   }
 
   pushImagemap(
@@ -683,10 +575,7 @@ class LineContext extends Context<LineClient, LineEvent> {
     imagemap: Omit<LineTypes.ImagemapMessage, 'type' | 'altText'>,
     options?: LineTypes.MessageOptions
   ) {
-    return this.push(
-      [Line.createImagemap(altText, imagemap, options)],
-      options
-    );
+    return this.push([Line.createImagemap(altText, imagemap, options)]);
   }
 
   pushFlex(
@@ -694,7 +583,7 @@ class LineContext extends Context<LineClient, LineEvent> {
     flex: LineTypes.FlexContainer,
     options?: LineTypes.MessageOptions
   ) {
-    return this.push([Line.createFlex(altText, flex, options)], options);
+    return this.push([Line.createFlex(altText, flex, options)]);
   }
 
   pushTemplate(
@@ -702,10 +591,7 @@ class LineContext extends Context<LineClient, LineEvent> {
     template: LineTypes.Template,
     options?: LineTypes.MessageOptions
   ) {
-    return this.push(
-      [Line.createTemplate(altText, template, options)],
-      options
-    );
+    return this.push([Line.createTemplate(altText, template, options)]);
   }
 
   pushButtonTemplate(
@@ -713,10 +599,9 @@ class LineContext extends Context<LineClient, LineEvent> {
     buttonTemplate: Omit<LineTypes.ButtonsTemplate, 'type'>,
     options?: LineTypes.MessageOptions
   ) {
-    return this.push(
-      [Line.createButtonTemplate(altText, buttonTemplate, options)],
-      options
-    );
+    return this.push([
+      Line.createButtonTemplate(altText, buttonTemplate, options),
+    ]);
   }
 
   pushButtonsTemplate(
@@ -732,34 +617,20 @@ class LineContext extends Context<LineClient, LineEvent> {
     confirmTemplate: Omit<LineTypes.ConfirmTemplate, 'type'>,
     options: LineTypes.MessageOptions
   ) {
-    return this.push(
-      [Line.createConfirmTemplate(altText, confirmTemplate, options)],
-      options
-    );
+    return this.push([
+      Line.createConfirmTemplate(altText, confirmTemplate, options),
+    ]);
   }
 
   pushCarouselTemplate(
     altText: string,
     columns: LineTypes.ColumnObject[],
-    {
-      imageAspectRatio,
-      imageSize,
-      ...options
-    }: {
+    options: {
       imageAspectRatio?: 'rectangle' | 'square';
       imageSize?: 'cover' | 'contain';
-    } & LineTypes.MessageOptions = {}
-  ) {
-    return this.push(
-      [
-        Line.createCarouselTemplate(altText, columns, {
-          imageAspectRatio,
-          imageSize,
-          ...options,
-        }),
-      ],
-      options
-    );
+    } & LineTypes.MessageOptions
+  ) {
+    return this.push([Line.createCarouselTemplate(altText, columns, options)]);
   }
 
   pushImageCarouselTemplate(
@@ -767,24 +638,23 @@ class LineContext extends Context<LineClient, LineEvent> {
     columns: LineTypes.ImageCarouselColumnObject[],
     options: LineTypes.MessageOptions
   ) {
-    return this.push(
-      [Line.createImageCarouselTemplate(altText, columns, options)],
-      options
-    );
+    return this.push([
+      Line.createImageCarouselTemplate(altText, columns, options),
+    ]);
   }
 
-  send(messages: LineTypes.Message[], options: LineTypes.MessageOptions = {}) {
+  send(messages: LineTypes.Message[]) {
     if (this._sendMethod === 'push') {
-      return this.push(messages, options);
+      return this.push(messages);
     }
-    return this.reply(messages, options);
+    return this.reply(messages);
   }
 
   sendText(
     text: string,
     options?: LineTypes.MessageOptions & { emojis?: LineTypes.Emoji[] }
   ) {
-    return this.send([Line.createText(text, options)], options);
+    return this.send([Line.createText(text, options)]);
   }
 
   sendImage(
@@ -794,7 +664,7 @@ class LineContext extends Context<LineClient, LineEvent> {
     },
     options?: LineTypes.MessageOptions
   ) {
-    return this.send([Line.createImage(image, options)], options);
+    return this.send([Line.createImage(image, options)]);
   }
 
   sendVideo(
@@ -804,7 +674,7 @@ class LineContext extends Context<LineClient, LineEvent> {
     },
     options?: LineTypes.MessageOptions
   ) {
-    return this.send([Line.createVideo(video, options)], options);
+    return this.send([Line.createVideo(video, options)]);
   }
 
   sendAudio(
@@ -814,21 +684,21 @@ class LineContext extends Context<LineClient, LineEvent> {
     },
     options?: LineTypes.MessageOptions
   ) {
-    return this.send([Line.createAudio(audio, options)], options);
+    return this.send([Line.createAudio(audio, options)]);
   }
 
   sendLocation(
     location: LineTypes.Location,
     options?: LineTypes.MessageOptions
   ) {
-    return this.send([Line.createLocation(location, options)], options);
+    return this.send([Line.createLocation(location, options)]);
   }
 
   sendSticker(
     sticker: Omit<LineTypes.StickerMessage, 'type'>,
     options?: LineTypes.MessageOptions
   ) {
-    return this.send([Line.createSticker(sticker, options)], options);
+    return this.send([Line.createSticker(sticker, options)]);
   }
 
   sendImagemap(
@@ -836,10 +706,7 @@ class LineContext extends Context<LineClient, LineEvent> {
     imagemap: Omit<LineTypes.ImagemapMessage, 'type' | 'altText'>,
     options?: LineTypes.MessageOptions
   ) {
-    return this.send(
-      [Line.createImagemap(altText, imagemap, options)],
-      options
-    );
+    return this.send([Line.createImagemap(altText, imagemap, options)]);
   }
 
   sendFlex(
@@ -847,7 +714,7 @@ class LineContext extends Context<LineClient, LineEvent> {
     flex: LineTypes.FlexContainer,
     options?: LineTypes.MessageOptions
   ) {
-    return this.send([Line.createFlex(altText, flex, options)], options);
+    return this.send([Line.createFlex(altText, flex, options)]);
   }
 
   sendTemplate(
@@ -855,10 +722,7 @@ class LineContext extends Context<LineClient, LineEvent> {
     template: LineTypes.Template,
     options?: LineTypes.MessageOptions
   ) {
-    return this.send(
-      [Line.createTemplate(altText, template, options)],
-      options
-    );
+    return this.send([Line.createTemplate(altText, template, options)]);
   }
 
   sendButtonTemplate(
@@ -866,10 +730,9 @@ class LineContext extends Context<LineClient, LineEvent> {
     buttonTemplate: Omit<LineTypes.ButtonsTemplate, 'type'>,
     options?: LineTypes.MessageOptions
   ) {
-    return this.send(
-      [Line.createButtonTemplate(altText, buttonTemplate, options)],
-      options
-    );
+    return this.send([
+      Line.createButtonTemplate(altText, buttonTemplate, options),
+    ]);
   }
 
   sendButtonsTemplate(
@@ -885,34 +748,20 @@ class LineContext extends Context<LineClient, LineEvent> {
     confirmTemplate: Omit<LineTypes.ConfirmTemplate, 'type'>,
     options: LineTypes.MessageOptions
   ) {
-    return this.send(
-      [Line.createConfirmTemplate(altText, confirmTemplate, options)],
-      options
-    );
+    return this.send([
+      Line.createConfirmTemplate(altText, confirmTemplate, options),
+    ]);
   }
 
   sendCarouselTemplate(
     altText: string,
     columns: LineTypes.ColumnObject[],
-    {
-      imageAspectRatio,
-      imageSize,
-      ...options
-    }: {
+    options: {
       imageAspectRatio?: 'rectangle' | 'square';
       imageSize?: 'cover' | 'contain';
-    } & LineTypes.MessageOptions = {}
-  ) {
-    return this.send(
-      [
-        Line.createCarouselTemplate(altText, columns, {
-          imageAspectRatio,
-          imageSize,
-          ...options,
-        }),
-      ],
-      options
-    );
+    } & LineTypes.MessageOptions
+  ) {
+    return this.send([Line.createCarouselTemplate(altText, columns, options)]);
   }
 
   sendImageCarouselTemplate(
@@ -920,10 +769,9 @@ class LineContext extends Context<LineClient, LineEvent> {
     columns: LineTypes.ImageCarouselColumnObject[],
     options: LineTypes.MessageOptions
   ) {
-    return this.send(
-      [Line.createImageCarouselTemplate(altText, columns, options)],
-      options
-    );
+    return this.send([
+      Line.createImageCarouselTemplate(altText, columns, options),
+    ]);
   }
 }
 


Test patch:
diff --git a/packages/bottender/src/line/__tests__/LineContext.spec.ts b/packages/bottender/src/line/__tests__/LineContext.spec.ts
index 71129ec4..c7e87d42 100644
--- a/packages/bottender/src/line/__tests__/LineContext.spec.ts
+++ b/packages/bottender/src/line/__tests__/LineContext.spec.ts
@@ -165,7 +165,7 @@ describe('#getMessageContent', () => {
 
     const res = await context.getMessageContent();
 
-    expect(client.getMessageContent).toBeCalledWith('325708', {});
+    expect(client.getMessageContent).toBeCalledWith('325708');
     expect(res).toEqual(buf);
   });
 
@@ -196,7 +196,7 @@ describe('#leave', () => {
 
     await context.leave();
 
-    expect(client.leaveGroup).toBeCalledWith('fakeGroupId', {});
+    expect(client.leaveGroup).toBeCalledWith('fakeGroupId');
   });
 
   it('leave room', async () => {
@@ -204,7 +204,7 @@ describe('#leave', () => {
 
     await context.leave();
 
-    expect(client.leaveRoom).toBeCalledWith('fakeRoomId', {});
+    expect(client.leaveRoom).toBeCalledWith('fakeRoomId');
   });
 
   it('not leave user', async () => {
@@ -219,7 +219,7 @@ describe('#leave', () => {
 });
 
 describe('#reply', () => {
-  it('#reply to call client.reply', async () => {
+  it('to call client.reply', async () => {
     const { context, client } = setup();
 
     await context.reply([
@@ -229,16 +229,12 @@ describe('#reply', () => {
       },
     ]);
 
-    expect(client.reply).toBeCalledWith(
-      REPLY_TOKEN,
-      [
-        {
-          type: 'text',
-          text: 'hello',
-        },
-      ],
-      { accessToken: undefined }
-    );
+    expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+      {
+        type: 'text',
+        text: 'hello',
+      },
+    ]);
   });
 
   it('should work with quickReply', async () => {
@@ -252,17 +248,13 @@ describe('#reply', () => {
       },
     ]);
 
-    expect(client.reply).toBeCalledWith(
-      REPLY_TOKEN,
-      [
-        {
-          type: 'text',
-          text: 'hello',
-          quickReply,
-        },
-      ],
-      {}
-    );
+    expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+      {
+        type: 'text',
+        text: 'hello',
+        quickReply,
+      },
+    ]);
   });
 });
 
@@ -272,11 +264,9 @@ describe('#replyText', () => {
 
     await context.replyText('hello');
 
-    expect(client.reply).toBeCalledWith(
-      REPLY_TOKEN,
-      [{ text: 'hello', type: 'text' }],
-      {}
-    );
+    expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+      { text: 'hello', type: 'text' },
+    ]);
   });
 
   it('should work with quickReply', async () => {
@@ -286,19 +276,13 @@ describe('#replyText', () => {
       quickReply,
     });
 
-    expect(client.reply).toBeCalledWith(
-      REPLY_TOKEN,
-      [
-        {
-          type: 'text',
-          text: 'hello',
-          quickReply,
-        },
-      ],
+    expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
       {
+        type: 'text',
+        text: 'hello',
         quickReply,
-      }
-    );
+      },
+    ]);
   });
 
   it('should throw when reply multiple times', async () => {
@@ -316,22 +300,6 @@ describe('#replyText', () => {
     expect(error).toBeDefined();
     expect(error.message).toEqual('Can not reply event multiple times');
   });
-
-  it('should support custom token', async () => {
-    const { context, client } = setup({
-      customAccessToken: 'anyToken',
-    });
-
-    await context.replyText('hello');
-
-    expect(client.reply).toBeCalledWith(
-      REPLY_TOKEN,
-      [{ text: 'hello', type: 'text' }],
-      {
-        accessToken: 'anyToken',
-      }
-    );
-  });
 });
 
 describe('#push', () => {
@@ -345,16 +313,12 @@ describe('#push', () => {
       },
     ]);
 
-    expect(client.push).toBeCalledWith(
-      session.user.id,
-      [
-        {
-          type: 'text',
-          text: 'hello',
-        },
-      ],
-      { accessToken: undefined }
-    );
+    expect(client.push).toBeCalledWith(session.user.id, [
+      {
+        type: 'text',
+        text: 'hello',
+      },
+    ]);
   });
 
   it('should work with quickReply', async () => {
@@ -368,17 +332,13 @@ describe('#push', () => {
       },
     ]);
 
-    expect(client.push).toBeCalledWith(
-      session.user.id,
-      [
-        {
-          type: 'text',
-          text: 'hello',
-          quickReply,
-        },
-      ],
-      {}
-    );
+    expect(client.push).toBeCalledWith(session.user.id, [
+      {
+        type: 'text',
+        text: 'hello',
+        quickReply,
+      },
+    ]);
   });
 });
 
@@ -388,11 +348,9 @@ describe('#pushText', () => {
 
     await context.pushText('hello');
 
-    expect(client.push).toBeCalledWith(
-      session.user.id,
-      [{ text: 'hello', type: 'text' }],
-      {}
-    );
+    expect(client.push).toBeCalledWith(session.user.id, [
+      { text: 'hello', type: 'text' },
+    ]);
   });
 
   it('should work with quickReply', async () => {
@@ -402,19 +360,13 @@ describe('#pushText', () => {
       quickReply,
     });
 
-    expect(client.push).toBeCalledWith(
-      session.user.id,
-      [
-        {
-          text: 'hello',
-          type: 'text',
-          quickReply,
-        },
-      ],
+    expect(client.push).toBeCalledWith(session.user.id, [
       {
+        text: 'hello',
+        type: 'text',
         quickReply,
-      }
-    );
+      },
+    ]);
   });
 
   it('should work with room session', async () => {
@@ -424,11 +376,9 @@ describe('#pushText', () => {
 
     await context.pushText('hello');
 
-    expect(client.push).toBeCalledWith(
-      session.room.id,
-      [{ text: 'hello', type: 'text' }],
-      {}
-    );
+    expect(client.push).toBeCalledWith(session.room.id, [
+      { text: 'hello', type: 'text' },
+    ]);
   });
 
   it('should work with group session', async () => {
@@ -438,11 +388,9 @@ describe('#pushText', () => {
 
     await context.pushText('hello');
 
-    expect(client.push).toBeCalledWith(
-      session.group.id,
-      [{ text: 'hello', type: 'text' }],
-      {}
-    );
+    expect(client.push).toBeCalledWith(session.group.id, [
+      { text: 'hello', type: 'text' },
+    ]);
   });
 
   it('should call warning and not to send if dont have session', async () => {
@@ -453,22 +401,6 @@ describe('#pushText', () => {
     expect(warning).toBeCalled();
     expect(client.push).not.toBeCalled();
   });
-
-  it('should support custom token', async () => {
-    const { context, client, session } = setup({
-      customAccessToken: 'anyToken',
-    });
-
-    await context.pushText('hello');
-
-    expect(client.push).toBeCalledWith(
-      session.user.id,
-      [{ text: 'hello', type: 'text' }],
-      {
-        accessToken: 'anyToken',
-      }
-    );
-  });
 });
 
 describe('send APIs', () => {
@@ -478,20 +410,16 @@ describe('send APIs', () => {
 
       await context.send([Line.createText('2'), Line.createText('3')]);
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'text',
-            text: '2',
-          },
-          {
-            type: 'text',
-            text: '3',
-          },
-        ],
-        {}
-      );
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+        {
+          type: 'text',
+          text: '2',
+        },
+        {
+          type: 'text',
+          text: '3',
+        },
+      ]);
     });
   });
 
@@ -501,16 +429,12 @@ describe('send APIs', () => {
 
       await context.sendText('hello');
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'text',
-            text: 'hello',
-          },
-        ],
-        {}
-      );
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+        {
+          type: 'text',
+          text: 'hello',
+        },
+      ]);
     });
 
     it('should work with quickReply', async () => {
@@ -520,19 +444,13 @@ describe('send APIs', () => {
         quickReply,
       });
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'text',
-            text: 'hello',
-            quickReply,
-          },
-        ],
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
         {
+          type: 'text',
+          text: 'hello',
           quickReply,
-        }
-      );
+        },
+      ]);
     });
   });
 
@@ -545,17 +463,13 @@ describe('send APIs', () => {
         previewImageUrl: 'yyy.jpg',
       });
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'image',
-            originalContentUrl: 'xxx.jpg',
-            previewImageUrl: 'yyy.jpg',
-          },
-        ],
-        { accessToken: undefined }
-      );
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+        {
+          type: 'image',
+          originalContentUrl: 'xxx.jpg',
+          previewImageUrl: 'yyy.jpg',
+        },
+      ]);
     });
 
     it('should work with quickReply', async () => {
@@ -571,20 +485,14 @@ describe('send APIs', () => {
         }
       );
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'image',
-            originalContentUrl: 'xxx.jpg',
-            previewImageUrl: 'yyy.jpg',
-            quickReply,
-          },
-        ],
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
         {
+          type: 'image',
+          originalContentUrl: 'xxx.jpg',
+          previewImageUrl: 'yyy.jpg',
           quickReply,
-        }
-      );
+        },
+      ]);
     });
   });
 
@@ -597,17 +505,13 @@ describe('send APIs', () => {
         duration: 240000,
       });
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'audio',
-            originalContentUrl: 'xxx.m4a',
-            duration: 240000,
-          },
-        ],
-        { accessToken: undefined }
-      );
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+        {
+          type: 'audio',
+          originalContentUrl: 'xxx.m4a',
+          duration: 240000,
+        },
+      ]);
     });
 
     it('should work with quickReply', async () => {
@@ -623,20 +527,14 @@ describe('send APIs', () => {
         }
       );
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'audio',
-            originalContentUrl: 'xxx.m4a',
-            duration: 240000,
-            quickReply,
-          },
-        ],
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
         {
+          type: 'audio',
+          originalContentUrl: 'xxx.m4a',
+          duration: 240000,
           quickReply,
-        }
-      );
+        },
+      ]);
     });
   });
 
@@ -649,17 +547,13 @@ describe('send APIs', () => {
         previewImageUrl: 'yyy.jpg',
       });
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'video',
-            originalContentUrl: 'xxx.mp4',
-            previewImageUrl: 'yyy.jpg',
-          },
-        ],
-        { accessToken: undefined }
-      );
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+        {
+          type: 'video',
+          originalContentUrl: 'xxx.mp4',
+          previewImageUrl: 'yyy.jpg',
+        },
+      ]);
     });
 
     it('should work with quickReply', async () => {
@@ -675,20 +569,14 @@ describe('send APIs', () => {
         }
       );
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'video',
-            originalContentUrl: 'xxx.mp4',
-            previewImageUrl: 'yyy.jpg',
-            quickReply,
-          },
-        ],
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
         {
+          type: 'video',
+          originalContentUrl: 'xxx.mp4',
+          previewImageUrl: 'yyy.jpg',
           quickReply,
-        }
-      );
+        },
+      ]);
     });
   });
 
@@ -703,19 +591,15 @@ describe('send APIs', () => {
         longitude: 139.70372892916203,
       });
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'location',
-            title: 'my location',
-            address: '〒150-0002 東京都渋谷区渋谷２丁目２１−１',
-            latitude: 35.65910807942215,
-            longitude: 139.70372892916203,
-          },
-        ],
-        { accessToken: undefined }
-      );
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+        {
+          type: 'location',
+          title: 'my location',
+          address: '〒150-0002 東京都渋谷区渋谷２丁目２１−１',
+          latitude: 35.65910807942215,
+          longitude: 139.70372892916203,
+        },
+      ]);
     });
 
     it('should work with quickReply', async () => {
@@ -733,22 +617,16 @@ describe('send APIs', () => {
         }
       );
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'location',
-            title: 'my location',
-            address: '〒150-0002 東京都渋谷区渋谷２丁目２１−１',
-            latitude: 35.65910807942215,
-            longitude: 139.70372892916203,
-            quickReply,
-          },
-        ],
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
         {
+          type: 'location',
+          title: 'my location',
+          address: '〒150-0002 東京都渋谷区渋谷２丁目２１−１',
+          latitude: 35.65910807942215,
+          longitude: 139.70372892916203,
           quickReply,
-        }
-      );
+        },
+      ]);
     });
   });
 
@@ -761,17 +639,13 @@ describe('send APIs', () => {
         stickerId: '1',
       });
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'sticker',
-            packageId: '1',
-            stickerId: '1',
-          },
-        ],
-        { accessToken: undefined }
-      );
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+        {
+          type: 'sticker',
+          packageId: '1',
+          stickerId: '1',
+        },
+      ]);
     });
 
     it('should work with quickReply', async () => {
@@ -787,20 +661,14 @@ describe('send APIs', () => {
         }
       );
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'sticker',
-            packageId: '1',
-            stickerId: '1',
-            quickReply,
-          },
-        ],
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
         {
+          type: 'sticker',
+          packageId: '1',
+          stickerId: '1',
           quickReply,
-        }
-      );
+        },
+      ]);
     });
   });
 
@@ -840,17 +708,13 @@ describe('send APIs', () => {
 
       await context.sendImagemap('this is an imagemap', template);
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'imagemap',
-            altText: 'this is an imagemap',
-            ...template,
-          },
-        ],
-        {}
-      );
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+        {
+          type: 'imagemap',
+          altText: 'this is an imagemap',
+          ...template,
+        },
+      ]);
     });
 
     it('should work with quickReply', async () => {
@@ -860,20 +724,14 @@ describe('send APIs', () => {
         quickReply,
       });
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'imagemap',
-            altText: 'this is an imagemap',
-            ...template,
-            quickReply,
-          },
-        ],
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
         {
+          type: 'imagemap',
+          altText: 'this is an imagemap',
+          ...template,
           quickReply,
-        }
-      );
+        },
+      ]);
     });
   });
 
@@ -924,17 +782,13 @@ describe('send APIs', () => {
 
       await context.sendFlex('this is a flex', contents);
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'flex',
-            altText: 'this is a flex',
-            contents,
-          },
-        ],
-        {}
-      );
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+        {
+          type: 'flex',
+          altText: 'this is a flex',
+          contents,
+        },
+      ]);
     });
 
     it('should work with quickReply', async () => {
@@ -944,20 +798,14 @@ describe('send APIs', () => {
         quickReply,
       });
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'flex',
-            altText: 'this is a flex',
-            contents,
-            quickReply,
-          },
-        ],
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
         {
+          type: 'flex',
+          altText: 'this is a flex',
+          contents,
           quickReply,
-        }
-      );
+        },
+      ]);
     });
   });
 
@@ -991,17 +839,13 @@ describe('send APIs', () => {
 
       await context.sendTemplate('this is a template', template);
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'template',
-            altText: 'this is a template',
-            template,
-          },
-        ],
-        {}
-      );
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+        {
+          type: 'template',
+          altText: 'this is a template',
+          template,
+        },
+      ]);
     });
 
     it('should work with quickReply', async () => {
@@ -1011,20 +855,14 @@ describe('send APIs', () => {
         quickReply,
       });
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'template',
-            altText: 'this is a template',
-            template,
-            quickReply,
-          },
-        ],
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
         {
+          type: 'template',
+          altText: 'this is a template',
+          template,
           quickReply,
-        }
-      );
+        },
+      ]);
     });
   });
 
@@ -1057,20 +895,16 @@ describe('send APIs', () => {
 
       await context.sendButtonTemplate('this is a button template', template);
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'template',
-            altText: 'this is a button template',
-            template: {
-              type: 'buttons',
-              ...template,
-            },
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+        {
+          type: 'template',
+          altText: 'this is a button template',
+          template: {
+            type: 'buttons',
+            ...template,
           },
-        ],
-        { accessToken: undefined }
-      );
+        },
+      ]);
     });
 
     it('should work with quickReply', async () => {
@@ -1080,23 +914,17 @@ describe('send APIs', () => {
         quickReply,
       });
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'template',
-            altText: 'this is a button template',
-            template: {
-              type: 'buttons',
-              ...template,
-            },
-            quickReply,
-          },
-        ],
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
         {
+          type: 'template',
+          altText: 'this is a button template',
+          template: {
+            type: 'buttons',
+            ...template,
+          },
           quickReply,
-        }
-      );
+        },
+      ]);
     });
 
     it('should support sendButtonsTemplate alias', async () => {
@@ -1104,20 +932,16 @@ describe('send APIs', () => {
 
       await context.sendButtonsTemplate('this is a button template', template);
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'template',
-            altText: 'this is a button template',
-            template: {
-              type: 'buttons',
-              ...template,
-            },
-          },
-        ],
-        {}
-      );
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+        {
+          type: 'template',
+          altText: 'this is a button template',
+          template: {
+            type: 'buttons',
+            ...template,
+          },
+        },
+      ]);
     });
   });
 
@@ -1143,20 +967,16 @@ describe('send APIs', () => {
 
       await context.sendConfirmTemplate('this is a confirm template', template);
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'template',
-            altText: 'this is a confirm template',
-            template: {
-              type: 'confirm',
-              ...template,
-            },
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+        {
+          type: 'template',
+          altText: 'this is a confirm template',
+          template: {
+            type: 'confirm',
+            ...template,
           },
-        ],
-        { accessToken: undefined }
-      );
+        },
+      ]);
     });
 
     it('should work with quickReply', async () => {
@@ -1168,21 +988,17 @@ describe('send APIs', () => {
         { quickReply }
       );
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'template',
-            altText: 'this is a confirm template',
-            template: {
-              type: 'confirm',
-              ...template,
-            },
-            quickReply,
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+        {
+          type: 'template',
+          altText: 'this is a confirm template',
+          template: {
+            type: 'confirm',
+            ...template,
           },
-        ],
-        { quickReply }
-      );
+          quickReply,
+        },
+      ]);
     });
   });
 
@@ -1242,22 +1058,18 @@ describe('send APIs', () => {
         template
       );
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'template',
-            altText: 'this is a carousel template',
-            template: {
-              type: 'carousel',
-              imageAspectRatio: undefined,
-              imageSize: undefined,
-              columns: template,
-            },
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+        {
+          type: 'template',
+          altText: 'this is a carousel template',
+          template: {
+            type: 'carousel',
+            imageAspectRatio: undefined,
+            imageSize: undefined,
+            columns: template,
           },
-        ],
-        { accessToken: undefined }
-      );
+        },
+      ]);
     });
 
     it('should work with quickReply', async () => {
@@ -1269,23 +1081,19 @@ describe('send APIs', () => {
         { quickReply }
       );
 
-      expect(client.reply).toBeCalledWith(
-        REPLY_TOKEN,
-        [
-          {
-            type: 'template',
-            altText: 'this is a carousel template',
-            template: {
-              type: 'carousel',
-              imageAspectRatio: undefined,
-              imageSize: undefined,
-              columns: template,
-            },
-            quickReply,
+      expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+        {
+          type: 'template',
+          altText: 'this is a carousel template',
+          template: {
+            type: 'carousel',
+            imageAspectRatio: undefined,
+            imageSize: undefined,
+            columns: template,
           },
-        ],
-        { quickReply }
-      );
+          quickReply,
+        },
+      ]);
     });
   });
 });
@@ -1329,8 +1137,7 @@ describe('profile APIs', () => {
 
       expect(client.getGroupMemberProfile).toBeCalledWith(
         'fakeGroupId',
-        'fakeUserId',
-        { accessToken: undefined }
+        'fakeUserId'
       );
     });
 
@@ -1341,8 +1148,7 @@ describe('profile APIs', () => {
 
       expect(client.getRoomMemberProfile).toBeCalledWith(
         'fakeRoomId',
-        'fakeUserId',
-        { accessToken: undefined }
+        'fakeUserId'
       );
     });
 
@@ -1351,7 +1157,7 @@ describe('profile APIs', () => {
 
       await context.getUserProfile();
 
-      expect(client.getUserProfile).toBeCalledWith('fakeUserId', {});
+      expect(client.getUserProfile).toBeCalledWith('fakeUserId');
     });
   });
 
@@ -1373,8 +1179,7 @@ describe('profile APIs', () => {
 
       expect(client.getGroupMemberProfile).toBeCalledWith(
         'fakeGroupId',
-        'anotherUser',
-        { accessToken: undefined }
+        'anotherUser'
       );
     });
 
@@ -1385,8 +1190,7 @@ describe('profile APIs', () => {
 
       expect(client.getRoomMemberProfile).toBeCalledWith(
         'fakeRoomId',
-        'anotherUser',
-        { accessToken: undefined }
+        'anotherUser'
       );
     });
 
@@ -1421,8 +1225,7 @@ describe('member IDs APIs', () => {
 
       expect(client.getGroupMemberIds).toBeCalledWith(
         'fakeGroupId',
-        'startToken',
-        { accessToken: undefined }
+        'startToken'
       );
     });
 
@@ -1433,8 +1236,7 @@ describe('member IDs APIs', () => {
 
       expect(client.getRoomMemberIds).toBeCalledWith(
         'fakeRoomId',
-        'startToken',
-        { accessToken: undefined }
+        'startToken'
       );
     });
 
@@ -1465,7 +1267,7 @@ describe('member IDs APIs', () => {
 
       await context.getAllMemberIds();
 
-      expect(client.getAllGroupMemberIds).toBeCalledWith('fakeGroupId', {});
+      expect(client.getAllGroupMemberIds).toBeCalledWith('fakeGroupId');
     });
 
     it('get memeber ids in room', async () => {
@@ -1473,7 +1275,7 @@ describe('member IDs APIs', () => {
 
       await context.getAllMemberIds();
 
-      expect(client.getAllRoomMemberIds).toBeCalledWith('fakeRoomId', {});
+      expect(client.getAllRoomMemberIds).toBeCalledWith('fakeRoomId');
     });
 
     it('not get user profile in user session', async () => {
@@ -1499,7 +1301,7 @@ describe('ruchmenu APIs', () => {
 
       const result = await context.getLinkedRichMenu();
 
-      expect(client.getLinkedRichMenu).toBeCalledWith(session.user.id, {});
+      expect(client.getLinkedRichMenu).toBeCalledWith(session.user.id);
       expect(result.richMenuId).toEqual('richMenuId');
     });
 
@@ -1518,11 +1320,7 @@ describe('ruchmenu APIs', () => {
 
       await context.linkRichMenu('richMenuId');
 
-      expect(client.linkRichMenu).toBeCalledWith(
-        session.user.id,
-        'richMenuId',
-        { accessToken: undefined }
-      );
+      expect(client.linkRichMenu).toBeCalledWith(session.user.id, 'richMenuId');
     });
 
     it('should warn without user', async () => {
@@ -1540,7 +1338,7 @@ describe('ruchmenu APIs', () => {
 
       await context.unlinkRichMenu();
 
-      expect(client.unlinkRichMenu).toBeCalledWith(session.user.id, {});
+      expect(client.unlinkRichMenu).toBeCalledWith(session.user.id);
     });
 
     it('should warn without user', async () => {
@@ -1563,7 +1361,7 @@ describe('account link APIs', () => {
 
       const result = await context.issueLinkToken();
 
-      expect(client.issueLinkToken).toBeCalledWith(session.user.id, {});
+      expect(client.issueLinkToken).toBeCalledWith(session.user.id);
       expect(result).toEqual({
         token: 'xxxxx',
       });
@@ -1608,36 +1406,24 @@ describe('batch', () => {
 
     await context.handlerDidEnd();
 
-    expect(client.reply).toBeCalledWith(
-      REPLY_TOKEN,
-      [
-        {
-          type: 'text',
-          text: '1',
-        },
-      ],
-      { accessToken: undefined }
-    );
-    expect(client.push).toBeCalledWith(
-      session.user.id,
-      [
-        {
-          type: 'text',
-          text: '2',
-        },
-      ],
-      { accessToken: undefined }
-    );
-    expect(client.push).toBeCalledWith(
-      session.user.id,
-      [
-        {
-          type: 'text',
-          text: '3',
-        },
-      ],
-      { accessToken: undefined }
-    );
+    expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+      {
+        type: 'text',
+        text: '1',
+      },
+    ]);
+    expect(client.push).toBeCalledWith(session.user.id, [
+      {
+        type: 'text',
+        text: '2',
+      },
+    ]);
+    expect(client.push).toBeCalledWith(session.user.id, [
+      {
+        type: 'text',
+        text: '3',
+      },
+    ]);
   });
 
   it('should batch reply', async () => {
@@ -1649,24 +1435,20 @@ describe('batch', () => {
 
     await context.handlerDidEnd();
 
-    expect(client.reply).toBeCalledWith(
-      REPLY_TOKEN,
-      [
-        {
-          type: 'text',
-          text: '1',
-        },
-        {
-          type: 'text',
-          text: '2',
-        },
-        {
-          type: 'text',
-          text: '3',
-        },
-      ],
-      { accessToken: undefined }
-    );
+    expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+      {
+        type: 'text',
+        text: '1',
+      },
+      {
+        type: 'text',
+        text: '2',
+      },
+      {
+        type: 'text',
+        text: '3',
+      },
+    ]);
   });
 
   it('should work with context.reply', async () => {
@@ -1677,24 +1459,20 @@ describe('batch', () => {
 
     await context.handlerDidEnd();
 
-    expect(client.reply).toBeCalledWith(
-      REPLY_TOKEN,
-      [
-        {
-          type: 'text',
-          text: '1',
-        },
-        {
-          type: 'text',
-          text: '2',
-        },
-        {
-          type: 'text',
-          text: '3',
-        },
-      ],
-      { accessToken: undefined }
-    );
+    expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+      {
+        type: 'text',
+        text: '1',
+      },
+      {
+        type: 'text',
+        text: '2',
+      },
+      {
+        type: 'text',
+        text: '3',
+      },
+    ]);
   });
 
   it('should warning when reply over 5 messages', async () => {
@@ -1711,32 +1489,28 @@ describe('batch', () => {
     await context.handlerDidEnd();
 
     expect(client.reply).toHaveBeenCalledTimes(1);
-    expect(client.reply).toBeCalledWith(
-      REPLY_TOKEN,
-      [
-        {
-          type: 'text',
-          text: '1',
-        },
-        {
-          type: 'text',
-          text: '2',
-        },
-        {
-          type: 'text',
-          text: '3',
-        },
-        {
-          type: 'text',
-          text: '4',
-        },
-        {
-          type: 'text',
-          text: '5',
-        },
-      ],
-      { accessToken: undefined }
-    );
+    expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+      {
+        type: 'text',
+        text: '1',
+      },
+      {
+        type: 'text',
+        text: '2',
+      },
+      {
+        type: 'text',
+        text: '3',
+      },
+      {
+        type: 'text',
+        text: '4',
+      },
+      {
+        type: 'text',
+        text: '5',
+      },
+    ]);
     expect(warning).toBeCalledWith(false, expect.any(String));
   });
 
@@ -1749,24 +1523,20 @@ describe('batch', () => {
 
     await context.handlerDidEnd();
 
-    expect(client.push).toBeCalledWith(
-      session.user.id,
-      [
-        {
-          type: 'text',
-          text: '1',
-        },
-        {
-          type: 'text',
-          text: '2',
-        },
-        {
-          type: 'text',
-          text: '3',
-        },
-      ],
-      { accessToken: undefined }
-    );
+    expect(client.push).toBeCalledWith(session.user.id, [
+      {
+        type: 'text',
+        text: '1',
+      },
+      {
+        type: 'text',
+        text: '2',
+      },
+      {
+        type: 'text',
+        text: '3',
+      },
+    ]);
   });
 
   it('should work with context.push', async () => {
@@ -1777,24 +1547,20 @@ describe('batch', () => {
 
     await context.handlerDidEnd();
 
-    expect(client.push).toBeCalledWith(
-      session.user.id,
-      [
-        {
-          type: 'text',
-          text: '1',
-        },
-        {
-          type: 'text',
-          text: '2',
-        },
-        {
-          type: 'text',
-          text: '3',
-        },
-      ],
-      { accessToken: undefined }
-    );
+    expect(client.push).toBeCalledWith(session.user.id, [
+      {
+        type: 'text',
+        text: '1',
+      },
+      {
+        type: 'text',
+        text: '2',
+      },
+      {
+        type: 'text',
+        text: '3',
+      },
+    ]);
   });
 
   it('should have more requests when push over 5 messages', async () => {
@@ -1811,42 +1577,34 @@ describe('batch', () => {
     await context.handlerDidEnd();
 
     expect(client.push).toHaveBeenCalledTimes(2);
-    expect(client.push).toBeCalledWith(
-      session.user.id,
-      [
-        {
-          type: 'text',
-          text: '1',
-        },
-        {
-          type: 'text',
-          text: '2',
-        },
-        {
-          type: 'text',
-          text: '3',
-        },
-        {
-          type: 'text',
-          text: '4',
-        },
-        {
-          type: 'text',
-          text: '5',
-        },
-      ],
-      { accessToken: undefined }
-    );
-    expect(client.push).toBeCalledWith(
-      session.user.id,
-      [
-        {
-          type: 'text',
-          text: '6',
-        },
-      ],
-      { accessToken: undefined }
-    );
+    expect(client.push).toBeCalledWith(session.user.id, [
+      {
+        type: 'text',
+        text: '1',
+      },
+      {
+        type: 'text',
+        text: '2',
+      },
+      {
+        type: 'text',
+        text: '3',
+      },
+      {
+        type: 'text',
+        text: '4',
+      },
+      {
+        type: 'text',
+        text: '5',
+      },
+    ]);
+    expect(client.push).toBeCalledWith(session.user.id, [
+      {
+        type: 'text',
+        text: '6',
+      },
+    ]);
     expect(warning).not.toBeCalled();
   });
 
@@ -1861,40 +1619,28 @@ describe('batch', () => {
 
     await context.pushText('4');
 
-    expect(client.reply).toBeCalledWith(
-      REPLY_TOKEN,
-      [
-        {
-          type: 'text',
-          text: '1',
-        },
-      ],
-      { accessToken: undefined }
-    );
-    expect(client.push).toBeCalledWith(
-      session.user.id,
-      [
-        {
-          type: 'text',
-          text: '2',
-        },
-        {
-          type: 'text',
-          text: '3',
-        },
-      ],
-      { accessToken: undefined }
-    );
-    expect(client.push).toBeCalledWith(
-      session.user.id,
-      [
-        {
-          type: 'text',
-          text: '4',
-        },
-      ],
-      { accessToken: undefined }
-    );
+    expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+      {
+        type: 'text',
+        text: '1',
+      },
+    ]);
+    expect(client.push).toBeCalledWith(session.user.id, [
+      {
+        type: 'text',
+        text: '2',
+      },
+      {
+        type: 'text',
+        text: '3',
+      },
+    ]);
+    expect(client.push).toBeCalledWith(session.user.id, [
+      {
+        type: 'text',
+        text: '4',
+      },
+    ]);
   });
 });
 
@@ -1904,11 +1650,9 @@ describe('sendMethod', () => {
 
     await context.sendText('hello');
 
-    expect(client.reply).toBeCalledWith(
-      REPLY_TOKEN,
-      [{ text: 'hello', type: 'text' }],
-      {}
-    );
+    expect(client.reply).toBeCalledWith(REPLY_TOKEN, [
+      { text: 'hello', type: 'text' },
+    ]);
     expect(client.push).not.toBeCalled();
   });
 
@@ -1919,11 +1663,9 @@ describe('sendMethod', () => {
 
     await context.sendText('hello');
 
-    expect(client.push).toBeCalledWith(
-      session.user.id,
-      [{ text: 'hello', type: 'text' }],
-      {}
-    );
+    expect(client.push).toBeCalledWith(session.user.id, [
+      { text: 'hello', type: 'text' },
+    ]);
     expect(client.reply).not.toBeCalled();
   });
 });
@@ -1934,14 +1676,6 @@ describe('#useAccessToken', () => {
 
     context.useAccessToken('anyToken');
 
-    await context.replyText('hello');
-
-    expect(client.reply).toBeCalledWith(
-      REPLY_TOKEN,
-      [{ text: 'hello', type: 'text' }],
-      {
-        accessToken: 'anyToken',
-      }
-    );
+    expect(client._accessToken).toEqual('anyToken');
   });
 });