Repository: neet/masto.js
Pull request #66 (2019-06-20 15:04:37)

Moderation APIs

codecov-io: # [Codecov](https://codecov.io/gh/neet/masto.js/pull/66?src=pr&el=h1) Report
> Merging [#66](https://codecov.io/gh/neet/masto.js/pull/66?src=pr&el=desc) into [master](https://codecov.io/gh/neet/masto.js/commit/bf0e4de0f2878c8758127ed84304fef5a22ac245?src=pr&el=desc) will **not change** coverage.
> The diff coverage is `62.5%`.

[![Impacted file tree graph](https://codecov.io/gh/neet/masto.js/pull/66/graphs/tree.svg?width=650&token=SW9FhwMnZ3&height=150&src=pr)](https://codecov.io/gh/neet/masto.js/pull/66?src=pr&el=tree)

```diff
@@           Coverage Diff           @@
##           master      #66   +/-   ##
=======================================
  Coverage   97.34%   97.34%           
=======================================
  Files           9        9           
  Lines         377      377           
  Branches       20       20           
=======================================
  Hits          367      367           
  Misses         10       10
```


| [Impacted Files](https://codecov.io/gh/neet/masto.js/pull/66?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/gateway/utils.ts](https://codecov.io/gh/neet/masto.js/pull/66/diff?src=pr&el=tree#diff-c3JjL2dhdGV3YXkvdXRpbHMudHM=) | `100% <ø> (ø)` | |
| [src/index.ts](https://codecov.io/gh/neet/masto.js/pull/66/diff?src=pr&el=tree#diff-c3JjL2luZGV4LnRz) | `0% <0%> (ø)` | :arrow_up: |
| [src/gateway/ws-events.ts](https://codecov.io/gh/neet/masto.js/pull/66/diff?src=pr&el=tree#diff-c3JjL2dhdGV3YXkvd3MtZXZlbnRzLnRz) | `95.23% <100%> (ø)` | |
| [src/gateway/gateway.ts](https://codecov.io/gh/neet/masto.js/pull/66/diff?src=pr&el=tree#diff-c3JjL2dhdGV3YXkvZ2F0ZXdheS50cw==) | `100% <100%> (ø)` | |
| [src/client/masto.ts](https://codecov.io/gh/neet/masto.js/pull/66/diff?src=pr&el=tree#diff-c3JjL2NsaWVudC9tYXN0by50cw==) | `100% <100%> (ø)` | :arrow_up: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/neet/masto.js/pull/66?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/neet/masto.js/pull/66?src=pr&el=footer). Last update [bf0e4de...aca77ed](https://codecov.io/gh/neet/masto.js/pull/66?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/src/client/__mocks__/gateway.ts b/src/client/__mocks__/gateway.ts
deleted file mode 100644
index 28dd0f03..00000000
--- a/src/client/__mocks__/gateway.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-export const getMock = jest.fn().mockResolvedValue({});
-export const postMock = jest.fn().mockResolvedValue({});
-export const deleteMock = jest.fn().mockResolvedValue({});
-export const patchMock = jest.fn().mockResolvedValue({});
-export const putMock = jest.fn().mockResolvedValue({});
-export const streamMock = jest.fn().mockResolvedValue({});
-export const paginateMock = jest.fn();
-
-export const Gateway = jest.fn(() => ({
-  uri: 'https://example.com',
-  streamingApiUrl: 'wss://example.com',
-  accessToken: 'token',
-  version: '99.99.9',
-  get: getMock,
-  post: postMock,
-  delete: deleteMock,
-  patch: patchMock,
-  put: putMock,
-  stream: streamMock,
-  paginate: paginateMock,
-}));
diff --git a/src/client/masto-events.ts b/src/client/masto-events.ts
deleted file mode 100644
index 540f46d7..00000000
--- a/src/client/masto-events.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-// tslint:disable no-unnecessary-override
-import EventEmitter from 'eventemitter3';
-import WebSocket from 'isomorphic-ws';
-import { Conversation } from '../entities/conversation';
-import { Notification } from '../entities/notification';
-import { Status } from '../entities/status';
-
-/** Callback argument of `ws` */
-export interface Message {
-  data: string;
-  type: string;
-  target: WebSocket;
-}
-
-export interface EventTypesMap {
-  /** Status posted */
-  update: Status;
-  /** Status deleted */
-  delete: Status['id'];
-  /** User's notification */
-  notification: Notification;
-  /** User's filter changed */
-  filters_changed: undefined;
-  /** Status added to a conversation */
-  conversation: Conversation;
-}
-
-export type EventTypes = keyof EventTypesMap;
-
-/**
- * Mastodon streaming api wrapper
- */
-export class MastoEvents extends EventEmitter {
-  private ws?: WebSocket;
-
-  /**
-   * Connect to the websocket endpoint
-   * @param url URL of the websocket endpoint
-   * @param protocols Subprotocol(s) for `Sec-Websocket-Protocol`
-   * @param params URL parameters
-   */
-  public connect(url: string, protocols?: string | string[]) {
-    return new Promise<MastoEvents>((resolve, reject) => {
-      this.ws = new WebSocket(url, protocols);
-
-      this.ws.addEventListener('message', this.handleMessage);
-      this.ws.addEventListener('error', reject);
-      this.ws.addEventListener('open', () => {
-        resolve(this);
-      });
-    });
-  }
-
-  /**
-   * Disconnect from the websocket endpoint
-   */
-  public disconnect() {
-    if (!this.ws) return;
-    this.ws.close();
-  }
-
-  /**
-   * Parse JSON data and emit it as an event
-   * @param message Websocket message
-   */
-  public handleMessage = (message: Message) => {
-    const parsedMessage = JSON.parse(message.data);
-    let data: string | { [key: string]: any };
-
-    try {
-      data = JSON.parse(parsedMessage.payload);
-    } catch {
-      // If parsing failed, returns raw data
-      // Basically this is handling for `filters_changed` event
-      // Which doesn't contain payload in the data
-      data = parsedMessage.payload;
-    }
-
-    this.emit(parsedMessage.event, data);
-  };
-
-  /**
-   * Add listener for the event
-   * @param event Type of the event. One of `update`, `delete`, `notification`, `filters_changed`, `conversation`
-   * @param callback Callback function
-   */
-  public on<T extends EventTypes>(
-    event: T,
-    callback: (payload: EventTypesMap[T]) => void,
-  ) {
-    return super.on(event, callback);
-  }
-}
diff --git a/src/client/decorators.ts b/src/clients/decorators.ts
similarity index 88%
rename from src/client/decorators.ts
rename to src/clients/decorators.ts
index 38987b22..5e111b95 100644
--- a/src/client/decorators.ts
+++ b/src/clients/decorators.ts
@@ -1,9 +1,9 @@
 import semver from 'semver';
 import { MastoNotFoundError } from '../errors/masto-not-found-error';
-import { Masto } from './masto';
+import { Gateway } from '../gateway/gateway';
 
 export type Decorator = (
-  masto: Masto,
+  gateway: Gateway,
   name: string,
   descriptor: TypedPropertyDescriptor<(...args: any[]) => any>,
 ) => void;
@@ -29,8 +29,8 @@ export const available = (parameters: AvailabeParams): Decorator => (
   const original = descriptor.value;
   const { since, until } = parameters;
 
-  descriptor.value = function(this: Masto, ...args: any[]) {
-    const version = semver.coerce(this.gateway.version);
+  descriptor.value = function(this: Gateway, ...args: any[]) {
+    const version = semver.coerce(this.version);
 
     if (since && version && semver.lt(version, since)) {
       throw new MastoNotFoundError(
diff --git a/src/clients/masto-admin/masto-admin.ts b/src/clients/masto-admin/masto-admin.ts
new file mode 100644
index 00000000..34cb92c6
--- /dev/null
+++ b/src/clients/masto-admin/masto-admin.ts
@@ -0,0 +1,158 @@
+import { AdminAccount } from '../../entities/admin-account';
+import { AdminReport } from '../../entities/admin-report';
+import { Gateway } from '../../gateway/gateway';
+import { available } from '../decorators';
+import {
+  AdminActionAccountParams,
+  AdminFetchAccountParams,
+  AdminFetchReportsParams,
+} from './params';
+
+/**
+ * Mastodon Moderation API client
+ */
+export class MastoAdmin extends Gateway {
+  /**
+   * Get accounts
+   * @param params parameters
+   * @retunr Accounts
+   */
+  @available({ since: '2.9.1' })
+  public fetchAccounts(params?: AdminFetchAccountParams) {
+    return this.get<AdminAccount[]>('/api/v1/admin/accounts', params);
+  }
+
+  /**
+   * Get a specific account
+   * @param id ID of the account
+   * @return Account
+   */
+  @available({ since: '2.9.1' })
+  public fetchAccount(id: string) {
+    return this.get<AdminAccount>(`/api/v1/admin/accounts/${id}`);
+  }
+
+  /**
+   * Re-enable account
+   * @param id ID of the account
+   * @return Account
+   */
+  @available({ since: '2.9.1' })
+  public enableAccount(id: string) {
+    return this.post<AdminAccount>(`/api/v1/admin/accounts/${id}/enable`);
+  }
+
+  /**
+   * Approve pending account
+   * @param id ID of the account
+   * @return Account
+   */
+  @available({ since: '2.9.1' })
+  public approveAccount(id: string) {
+    return this.post<AdminAccount>(`/api/v1/admin/accounts/${id}/approve`);
+  }
+
+  /**
+   * Reject pending account
+   * @param id ID of the account
+   * @return Account
+   */
+  @available({ since: '2.9.1' })
+  public rejectAccount(id: string) {
+    return this.post<AdminAccount>(`/api/v1/admin/accounts/${id}/reject`);
+  }
+
+  /**
+   * Unsilence account
+   * @param id ID of the account
+   * @return Account
+   */
+  @available({ since: '2.9.1' })
+  public unsilenceAccount(id: string) {
+    return this.post<AdminAccount>(`/api/v1/admin/accounts/${id}/unsilence`);
+  }
+
+  /**
+   * Unsuspend account
+   * @param id ID of the account
+   * @return Account
+   */
+  @available({ since: '2.9.1' })
+  public unsuspendAccount(id: string) {
+    return this.post<AdminAccount>(`/api/v1/admin/accounts/${id}/unsuspend`);
+  }
+
+  /**
+   * Get reports
+   * @param params params
+   * @return Reports
+   */
+  @available({ since: '2.9.1' })
+  public fetchReports(params?: AdminFetchReportsParams) {
+    return this.get<AdminReport[]>('/api/v1/admin/reports', params);
+  }
+
+  /**
+   * Get a specific report
+   * @param id ID of the report
+   * @return Report
+   */
+  @available({ since: '2.9.1' })
+  public fetchReport(id: string) {
+    return this.get<AdminReport>(`/api/v1/admin/reports/${id}`);
+  }
+
+  /**
+   * Assign report to self
+   * @param id ID of the report
+   * @return Report
+   */
+  @available({ since: '2.9.1' })
+  public assignReportToSelf(id: string) {
+    return this.post<AdminReport>(`/api/v1/admin/reports/${id}/assign_to_self`);
+  }
+
+  /**
+   * Unassign report from self
+   * @param id ID of the report
+   * @return Report
+   */
+  @available({ since: '2.9.1' })
+  public unassignReport(id: string) {
+    return this.post<AdminReport>(`/api/v1/admin/reports/${id}/unassign`);
+  }
+
+  /**
+   * Re-open report
+   * @param id ID of the report
+   * @return Report
+   */
+  @available({ since: '2.9.1' })
+  public reopenReport(id: string) {
+    return this.post<AdminReport>(`/api/v1/admin/reports/${id}/reopen`);
+  }
+
+  /**
+   * Close report
+   * @param id ID of the report
+   * @return Report
+   */
+  @available({ since: '2.9.1' })
+  public resolveReport(id: string) {
+    return this.post<AdminReport>(`/api/v1/admin/reports/${id}/resolve`);
+  }
+
+  /**
+   * Perform a moderation action on an account
+   * @param id ID of the account
+   * @param params Params
+   * @return Acccount
+   */
+  @available({ since: '2.9.1' })
+  public actionAccount(id: string, params: AdminActionAccountParams) {
+    return this.post<AdminAccount>(
+      `/api/v1/admin/accounts/${id}/action`,
+      params,
+    );
+  }
+}
diff --git a/src/clients/masto-admin/params.ts b/src/clients/masto-admin/params.ts
new file mode 100644
index 00000000..506c7381
--- /dev/null
+++ b/src/clients/masto-admin/params.ts
@@ -0,0 +1,31 @@
+export interface AdminFetchAccountParams {
+  local?: boolean | null;
+  remote?: boolean | null;
+  by_domain?: string | null;
+  active?: boolean | null;
+  pending?: boolean | null;
+  disabled?: boolean | null;
+  silenced?: boolean | null;
+  suspended?: boolean | null;
+  usename?: string | null;
+  display_name?: string | null;
+  email?: string | null;
+  ip?: string | null;
+  staff?: boolean | null;
+}
+
+export interface AdminFetchReportsParams {
+  resolved?: boolean | null;
+  account_id?: string | null;
+  target_account_id?: string | null;
+}
+
+export type AccountActionType = 'none' | 'disable' | 'silence' | 'suspend';
+
+export interface AdminActionAccountParams {
+  type: AccountActionType;
+  report_id: string;
+  warning_preset_id?: string | null;
+  text?: string | null;
+  send_email_notification?: boolean | null;
+}
diff --git a/src/client/masto.ts b/src/clients/masto/masto.ts
similarity index 78%
rename from src/client/masto.ts
rename to src/clients/masto/masto.ts
index d79d455b..21f2e2c9 100644
--- a/src/client/masto.ts
+++ b/src/clients/masto/masto.ts
@@ -2,27 +2,27 @@ import {
   Account,
   AccountCredentials,
   AccountIdentityProof,
-} from '../entities/account';
-import { Application } from '../entities/application';
-import { Attachment } from '../entities/attachment';
-import { Card } from '../entities/card';
-import { Context } from '../entities/context';
-import { Conversation } from '../entities/conversation';
-import { Emoji } from '../entities/emoji';
-import { Filter } from '../entities/filter';
-import { Instance, InstanceActivity } from '../entities/instance';
-import { List } from '../entities/list';
-import { Notification } from '../entities/notification';
-import { OAuthClient, OAuthToken } from '../entities/oauth';
-import { Poll } from '../entities/poll';
-import { Preference } from '../entities/preference';
-import { PushSubscription } from '../entities/push-subscription';
-import { Relationship } from '../entities/relationship';
-import { Results, ResultsV1 } from '../entities/results';
-import { ScheduledStatus } from '../entities/scheduled-status';
-import { Status } from '../entities/status';
-import { available } from './decorators';
-import { Gateway } from './gateway';
+} from '../../entities/account';
+import { Application } from '../../entities/application';
+import { Attachment } from '../../entities/attachment';
+import { Card } from '../../entities/card';
+import { Context } from '../../entities/context';
+import { Conversation } from '../../entities/conversation';
+import { Emoji } from '../../entities/emoji';
+import { Filter } from '../../entities/filter';
+import { Instance, InstanceActivity } from '../../entities/instance';
+import { List } from '../../entities/list';
+import { Notification } from '../../entities/notification';
+import { OAuthClient, OAuthToken } from '../../entities/oauth';
+import { Poll } from '../../entities/poll';
+import { Preference } from '../../entities/preference';
+import { PushSubscription } from '../../entities/push-subscription';
+import { Relationship } from '../../entities/relationship';
+import { Results, ResultsV1 } from '../../entities/results';
+import { ScheduledStatus } from '../../entities/scheduled-status';
+import { Status } from '../../entities/status';
+import { Gateway } from '../../gateway/gateway';
+import { available } from '../decorators';
 import {
   AddPushSubscriptionParams,
   CreateAccountParams,
@@ -33,7 +33,6 @@ import {
   FetchNotificationsParams,
   FetchTimelineParams,
   FollowAccountParams,
-  LoginParams,
   ModifyFilterParams,
   ModifyListAccountsParams,
   ModifyListParams,
@@ -55,34 +54,7 @@ import {
 /**
  * Mastodon API client
  */
-export class Masto {
-  /** Instance of Gateway */
-  public gateway: Gateway;
-
-  /**
-   * Private constructor
-   * @param gateway Instance of Gateway
-   */
-  private constructor(gateway: Gateway) {
-    this.gateway = gateway;
-  }
-
-  /**
-   * Login to Mastodon
-   * @param params Paramters
-   * @return Instance of Mastodon class
-   */
-  public static async login(params: LoginParams) {
-    const gateway = new Gateway(params);
-    const masto = new Masto(gateway);
-    const instance = await masto.fetchInstance();
-
-    gateway.version = instance.version;
-    gateway.streamingApiUrl = instance.urls.streaming_api;
-
-    return masto;
-  }
-
+export class Masto extends Gateway {
   /**
    * Starting home timeline and notification streaming
    * @return Instance of EventEmitter
@@ -90,7 +62,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public streamUser() {
-    return this.gateway.stream('/api/v1/streaming', {
+    return this.stream('/api/v1/streaming', {
       stream: 'user',
     });
   }
@@ -102,7 +74,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public streamPublicTimeline() {
-    return this.gateway.stream('/api/v1/streaming', {
+    return this.stream('/api/v1/streaming', {
       stream: 'public',
     });
   }
@@ -114,7 +86,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public streamCommunityTimeline() {
-    return this.gateway.stream('/api/v1/streaming', {
+    return this.stream('/api/v1/streaming', {
       stream: 'public:local',
     });
   }
@@ -127,7 +99,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public streamTagTimeline(id: string) {
-    return this.gateway.stream('/api/v1/streaming', {
+    return this.stream('/api/v1/streaming', {
       stream: 'hashtag',
       tag: id,
     });
@@ -141,7 +113,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public streamLocalTagTimeline(id: string) {
-    return this.gateway.stream('/api/v1/streaming', {
+    return this.stream('/api/v1/streaming', {
       stream: 'hashtag:local',
       tag: id,
     });
@@ -155,7 +127,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public streamListTimeline(id: string) {
-    return this.gateway.stream('/api/v1/streaming', {
+    return this.stream('/api/v1/streaming', {
       stream: 'list',
       list: id,
     });
@@ -168,7 +140,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public streamDirectTimeline() {
-    return this.gateway.stream('/api/v1/streaming', {
+    return this.stream('/api/v1/streaming', {
       stream: 'direct',
     });
   }
@@ -180,7 +152,7 @@ export class Masto {
    * @see https://docs.joinmastodon.org/api/authentication/#post-oauth-token
    */
   public fetchAccessToken(params: FetchAccessTokenParams) {
-    return this.gateway.post<OAuthToken>('/oauth/token', params);
+    return this.post<OAuthToken>('/oauth/token', params);
   }
 
   /**
@@ -189,7 +161,7 @@ export class Masto {
    * @see https://docs.joinmastodon.org/api/authentication/#post-oauth-revoke
    */
   public revokeAccessToken(params: RevokeAccessTokenParams) {
-    return this.gateway.post<void>('/oauth/revoke', params);
+    return this.post<void>('/oauth/revoke', params);
   }
 
   /**
@@ -200,7 +172,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchAccount(id: string) {
-    return this.gateway.get<Account>(`/api/v1/accounts/${id}`);
+    return this.get<Account>(`/api/v1/accounts/${id}`);
   }
 
   /**
@@ -211,7 +183,7 @@ export class Masto {
    */
   @available({ since: '2.8.0' })
   public fetchAccountIdentityProofs(id: string) {
-    return this.gateway.get<AccountIdentityProof[]>(
+    return this.get<AccountIdentityProof[]>(
       `/api/v1/accounts/${id}/identity_proofs`,
     );
   }
@@ -223,7 +195,7 @@ export class Masto {
    */
   @available({ since: '2.7.0' })
   public createAccount(params: CreateAccountParams) {
-    return this.gateway.post<OAuthToken>('/api/v1/accounts', params);
+    return this.post<OAuthToken>('/api/v1/accounts', params);
   }
 
   /**
@@ -233,9 +205,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public verifyCredentials() {
-    return this.gateway.get<AccountCredentials>(
-      '/api/v1/accounts/verify_credentials',
-    );
+    return this.get<AccountCredentials>('/api/v1/accounts/verify_credentials');
   }
 
   /**
@@ -246,7 +216,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public updateCredentials(params?: UpdateCredentialsParams) {
-    return this.gateway.patch<AccountCredentials>(
+    return this.patch<AccountCredentials>(
       '/api/v1/accounts/update_credentials',
       params,
       { headers: { 'Content-Type': 'multipart/form-data' } },
@@ -262,10 +232,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchAccountFollowers(id: string, params?: PaginationParams) {
-    return this.gateway.paginate<Account[]>(
-      `/api/v1/accounts/${id}/followers`,
-      params,
-    );
+    return this.paginate<Account[]>(`/api/v1/accounts/${id}/followers`, params);
   }
 
   /**
@@ -277,10 +244,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchAccountFollowing(id: string, params?: PaginationParams) {
-    return this.gateway.paginate<Account[]>(
-      `/api/v1/accounts/${id}/following`,
-      params,
-    );
+    return this.paginate<Account[]>(`/api/v1/accounts/${id}/following`, params);
   }
 
   /**
@@ -292,10 +256,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchAccountStatuses(id: string, params?: FetchAccountStatusesParams) {
-    return this.gateway.paginate<Status[]>(
-      `/api/v1/accounts/${id}/statuses`,
-      params,
-    );
+    return this.paginate<Status[]>(`/api/v1/accounts/${id}/statuses`, params);
   }
 
   /**
@@ -307,10 +268,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public followAccount(id: string, params?: FollowAccountParams) {
-    return this.gateway.post<Relationship>(
-      `/api/v1/accounts/${id}/follow`,
-      params,
-    );
+    return this.post<Relationship>(`/api/v1/accounts/${id}/follow`, params);
   }
 
   /**
@@ -321,7 +279,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public unfollowAccount(id: string) {
-    return this.gateway.post<Relationship>(`/api/v1/accounts/${id}/unfollow`);
+    return this.post<Relationship>(`/api/v1/accounts/${id}/unfollow`);
   }
 
   /**
@@ -332,7 +290,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchAccountRelationships(id: string[]) {
-    return this.gateway.get<Relationship[]>(`/api/v1/accounts/relationship`, {
+    return this.get<Relationship[]>(`/api/v1/accounts/relationship`, {
       id,
     });
   }
@@ -345,7 +303,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public searchAccounts(params?: SearchAccountsParams) {
-    return this.gateway.get<Account[]>(`/api/v1/accounts/search`, params);
+    return this.get<Account[]>(`/api/v1/accounts/search`, params);
   }
 
   /**
@@ -356,7 +314,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public createApp(params: CreateAppParams) {
-    return this.gateway.post<OAuthClient>(`/api/v1/apps`, params);
+    return this.post<OAuthClient>(`/api/v1/apps`, params);
   }
 
   /**
@@ -366,7 +324,7 @@ export class Masto {
    */
   @available({ since: '2.0.0' })
   public verifyAppCredentials() {
-    return this.gateway.get<Application>(`/api/v1/apps/verify_credentials`);
+    return this.get<Application>(`/api/v1/apps/verify_credentials`);
   }
 
   /**
@@ -377,7 +335,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchBlocks(params?: PaginationParams) {
-    return this.gateway.paginate<Account[]>(`/api/v1/blocks`, params);
+    return this.paginate<Account[]>(`/api/v1/blocks`, params);
   }
 
   /**
@@ -388,7 +346,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public blockAccount(id: string) {
-    return this.gateway.post<Relationship>(`/api/v1/accounts/${id}/block`);
+    return this.post<Relationship>(`/api/v1/accounts/${id}/block`);
   }
 
   /**
@@ -399,7 +357,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public unblockAccount(id: string) {
-    return this.gateway.post<Relationship>(`/api/v1/accounts/${id}/unblock`);
+    return this.post<Relationship>(`/api/v1/accounts/${id}/unblock`);
   }
 
   /**
@@ -409,7 +367,7 @@ export class Masto {
    */
   @available({ since: '2.0.0' })
   public fetchCustomEmojis() {
-    return this.gateway.get<Emoji[]>(`/api/v1/custom_emojis`);
+    return this.get<Emoji[]>(`/api/v1/custom_emojis`);
   }
 
   /**
@@ -420,7 +378,7 @@ export class Masto {
    */
   @available({ since: '1.4.0' })
   public fetchDomainBlocks(params?: PaginationParams) {
-    return this.gateway.paginate<string[]>(`/api/v1/domain_blocks`, params);
+    return this.paginate<string[]>(`/api/v1/domain_blocks`, params);
   }
 
   /**
@@ -431,7 +389,7 @@ export class Masto {
    */
   @available({ since: '1.4.0' })
   public blockDomain(domain: string) {
-    return this.gateway.post<void>(`/api/v1/domain_blocks`, {
+    return this.post<void>(`/api/v1/domain_blocks`, {
       domain,
     });
   }
@@ -444,7 +402,7 @@ export class Masto {
    */
   @available({ since: '1.4.0' })
   public unblockDomain(domain: string) {
-    return this.gateway.delete<void>(`/api/v1/domain_blocks`, {
+    return this.delete<void>(`/api/v1/domain_blocks`, {
       domain,
     });
   }
@@ -456,7 +414,7 @@ export class Masto {
    */
   @available({ since: '2.5.0' })
   public fetchEndorsements(params?: PaginationParams) {
-    return this.gateway.paginate<Account[]>(`/api/v1/endorsements`, params);
+    return this.paginate<Account[]>(`/api/v1/endorsements`, params);
   }
 
   /**
@@ -467,7 +425,7 @@ export class Masto {
    */
   @available({ since: '2.5.0' })
   public pinAccount(id: string) {
-    return this.gateway.post<Relationship>(`/api/v1/accounts/${id}/pin`);
+    return this.post<Relationship>(`/api/v1/accounts/${id}/pin`);
   }
 
   /**
@@ -478,7 +436,7 @@ export class Masto {
    */
   @available({ since: '2.5.0' })
   public unpinAccount(id: string) {
-    return this.gateway.post<Relationship>(`/api/v1/accounts/${id}/unpin`);
+    return this.post<Relationship>(`/api/v1/accounts/${id}/unpin`);
   }
 
   /**
@@ -489,7 +447,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchFavourites(params?: PaginationParams) {
-    return this.gateway.paginate<Status[]>(`/api/v1/favourites`, params);
+    return this.paginate<Status[]>(`/api/v1/favourites`, params);
   }
 
   /**
@@ -500,7 +458,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public favouriteStatus(id: string) {
-    return this.gateway.post<Status>(`/api/v1/statuses/${id}/favourite`);
+    return this.post<Status>(`/api/v1/statuses/${id}/favourite`);
   }
 
   /**
@@ -511,7 +469,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public unfavouriteStatus(id: string) {
-    return this.gateway.post<Status>(`/api/v1/statuses/${id}/unfavourite`);
+    return this.post<Status>(`/api/v1/statuses/${id}/unfavourite`);
   }
 
   /**
@@ -521,7 +479,7 @@ export class Masto {
    */
   @available({ since: '2.4.3' })
   public fetchFilters() {
-    return this.gateway.get<Filter[]>(`/api/v1/filters`);
+    return this.get<Filter[]>(`/api/v1/filters`);
   }
 
   /**
@@ -532,7 +490,7 @@ export class Masto {
    */
   @available({ since: '2.4.3' })
   public fetchFilter(id: string) {
-    return this.gateway.get<Filter>(`/api/v1/filters/${id}`);
+    return this.get<Filter>(`/api/v1/filters/${id}`);
   }
 
   /**
@@ -543,7 +501,7 @@ export class Masto {
    */
   @available({ since: '2.4.3' })
   public createFiler(params?: ModifyFilterParams) {
-    return this.gateway.post<Filter>(`/api/v1/filters`, params);
+    return this.post<Filter>(`/api/v1/filters`, params);
   }
 
   /**
@@ -555,7 +513,7 @@ export class Masto {
    */
   @available({ since: '2.4.3' })
   public updateFilter(id: string, params?: ModifyFilterParams) {
-    return this.gateway.put<Filter>(`/api/v1/filters/${id}`, params);
+    return this.put<Filter>(`/api/v1/filters/${id}`, params);
   }
 
   /**
@@ -566,7 +524,7 @@ export class Masto {
    */
   @available({ since: '2.4.3' })
   public removeFilter(id: string) {
-    return this.gateway.delete<void>(`/api/v1/filters/${id}`);
+    return this.delete<void>(`/api/v1/filters/${id}`);
   }
 
   /**
@@ -577,7 +535,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchFollowRequests(params?: PaginationParams) {
-    return this.gateway.paginate<Account[]>(`/api/v1/follow_requests`, params);
+    return this.paginate<Account[]>(`/api/v1/follow_requests`, params);
   }
 
   /**
@@ -588,7 +546,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public authorizeFollowRequest(id: string) {
-    return this.gateway.post<void>(`/api/v1/follow_requests/${id}/authorize`);
+    return this.post<void>(`/api/v1/follow_requests/${id}/authorize`);
   }
 
   /**
@@ -599,7 +557,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public rejectFollowRequest(id: string) {
-    return this.gateway.post<void>(`/api/v1/follow_requests/${id}/reject`);
+    return this.post<void>(`/api/v1/follow_requests/${id}/reject`);
   }
 
   /**
@@ -609,7 +567,7 @@ export class Masto {
    */
   @available({ since: '2.4.3' })
   public fetchSuggestions() {
-    return this.gateway.get<Account[]>('/api/v1/suggestions');
+    return this.get<Account[]>('/api/v1/suggestions');
   }
 
   /**
@@ -620,7 +578,7 @@ export class Masto {
    */
   @available({ since: '2.4.3' })
   public removeSuggestion(id: string) {
-    return this.gateway.delete<void>(`/api/v1/suggestions/${id}`);
+    return this.delete<void>(`/api/v1/suggestions/${id}`);
   }
 
   /**
@@ -630,7 +588,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchInstance() {
-    return this.gateway.get<Instance>('/api/v1/instance');
+    return this.get<Instance>('/api/v1/instance');
   }
 
   /**
@@ -640,7 +598,7 @@ export class Masto {
    */
   @available({ since: '2.1.2' })
   public fetchInstancesPeers() {
-    return this.gateway.get<string[]>('/api/v1/instance/peers');
+    return this.get<string[]>('/api/v1/instance/peers');
   }
 
   /**
@@ -650,7 +608,7 @@ export class Masto {
    */
   @available({ since: '2.1.2' })
   public fetchInstanceActivity() {
-    return this.gateway.get<InstanceActivity[]>('/api/v1/instance/activity');
+    return this.get<InstanceActivity[]>('/api/v1/instance/activity');
   }
 
   /**
@@ -660,7 +618,7 @@ export class Masto {
    */
   @available({ since: '2.1.0' })
   public fetchLists() {
-    return this.gateway.get<List[]>('/api/v1/lists');
+    return this.get<List[]>('/api/v1/lists');
   }
 
   /**
@@ -671,7 +629,7 @@ export class Masto {
    */
   @available({ since: '2.1.0' })
   public fetchAccountLists(id: string) {
-    return this.gateway.get<List[]>(`/api/v1/accounts/${id}/lists`);
+    return this.get<List[]>(`/api/v1/accounts/${id}/lists`);
   }
 
   /**
@@ -683,10 +641,7 @@ export class Masto {
    */
   @available({ since: '2.1.0' })
   public fetchListAccounts(id: string, params?: PaginationParams) {
-    return this.gateway.paginate<Account[]>(
-      `/api/v1/list/${id}/accounts`,
-      params,
-    );
+    return this.paginate<Account[]>(`/api/v1/list/${id}/accounts`, params);
   }
 
   /**
@@ -697,7 +652,7 @@ export class Masto {
    */
   @available({ since: '2.1.0' })
   public fetchList(id: string) {
-    return this.gateway.get<List>(`/api/v1/lists/${id}`);
+    return this.get<List>(`/api/v1/lists/${id}`);
   }
 
   /**
@@ -708,7 +663,7 @@ export class Masto {
    */
   @available({ since: '2.1.0' })
   public createList(params: ModifyListParams) {
-    return this.gateway.post<List>('/api/v1/lists', params);
+    return this.post<List>('/api/v1/lists', params);
   }
 
   /**
@@ -720,7 +675,7 @@ export class Masto {
    */
   @available({ since: '2.1.0' })
   public updateList(id: string, params: ModifyListParams) {
-    return this.gateway.put<List>(`/api/v1/lists/${id}`, params);
+    return this.put<List>(`/api/v1/lists/${id}`, params);
   }
 
   /**
@@ -731,7 +686,7 @@ export class Masto {
    */
   @available({ since: '2.1.0' })
   public removeList(id: string) {
-    return this.gateway.delete<void>(`/api/v1/lists/${id}`);
+    return this.delete<void>(`/api/v1/lists/${id}`);
   }
 
   /**
@@ -743,7 +698,7 @@ export class Masto {
    */
   @available({ since: '2.1.0' })
   public addAccountToList(id: string, params: ModifyListAccountsParams) {
-    return this.gateway.post<void>(`/api/v1/lists/${id}/accounts`, params);
+    return this.post<void>(`/api/v1/lists/${id}/accounts`, params);
   }
 
   /**
@@ -755,7 +710,7 @@ export class Masto {
    */
   @available({ since: '2.1.0' })
   public removeAccountFromList(id: string, params: ModifyListAccountsParams) {
-    return this.gateway.delete<void>(`/api/v1/lists/${id}/accounts`, params);
+    return this.delete<void>(`/api/v1/lists/${id}/accounts`, params);
   }
 
   /**
@@ -766,7 +721,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public uploadMediaAttachment(params: UploadMediaAttachmentParams) {
-    return this.gateway.post<Attachment>('/api/v1/media', params, {
+    return this.post<Attachment>('/api/v1/media', params, {
       headers: { 'Content-Type': 'multipart/form-data' },
     });
   }
@@ -783,7 +738,7 @@ export class Masto {
     id: string,
     params: UpdateMediaAttachmentParams,
   ) {
-    return this.gateway.put<Attachment>(`/api/v1/media/${id}`, params);
+    return this.put<Attachment>(`/api/v1/media/${id}`, params);
   }
 
   /**
@@ -794,7 +749,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchMutes(params?: PaginationParams) {
-    return this.gateway.paginate<Account[]>('/api/v1/mutes', params);
+    return this.paginate<Account[]>('/api/v1/mutes', params);
   }
 
   /**
@@ -806,10 +761,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public muteAccount(id: string, params: MuteAccountParams) {
-    return this.gateway.post<Relationship>(
-      `/api/v1/accounts/${id}/mute`,
-      params,
-    );
+    return this.post<Relationship>(`/api/v1/accounts/${id}/mute`, params);
   }
 
   /**
@@ -820,7 +772,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public unmuteAccount(id: string) {
-    return this.gateway.post<Relationship>(`/api/v1/accounts/${id}/unmute`);
+    return this.post<Relationship>(`/api/v1/accounts/${id}/unmute`);
   }
 
   /**
@@ -831,7 +783,7 @@ export class Masto {
    */
   @available({ since: '1.4.2' })
   public muteStatus(id: string) {
-    return this.gateway.post<Status>(`/api/v1/statuses/${id}/mute`);
+    return this.post<Status>(`/api/v1/statuses/${id}/mute`);
   }
 
   /**
@@ -842,7 +794,7 @@ export class Masto {
    */
   @available({ since: '1.4.2' })
   public unmuteStatus(id: string) {
-    return this.gateway.post<Status>(`/api/v1/statuses/${id}/unmute`);
+    return this.post<Status>(`/api/v1/statuses/${id}/unmute`);
   }
 
   /**
@@ -853,7 +805,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchNotifications(params?: FetchNotificationsParams) {
-    return this.gateway.get<Notification[]>('/api/v1/notifications', params);
+    return this.get<Notification[]>('/api/v1/notifications', params);
   }
 
   /**
@@ -864,7 +816,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchNotification(id: string) {
-    return this.gateway.get<Notification>(`/api/v1/notifications/${id}`);
+    return this.get<Notification>(`/api/v1/notifications/${id}`);
   }
 
   /**
@@ -874,7 +826,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public clearNotifications() {
-    return this.gateway.post<void>('/api/v1/notifications/clear');
+    return this.post<void>('/api/v1/notifications/clear');
   }
 
   /**
@@ -885,7 +837,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public dissmissNotification(id: string) {
-    return this.gateway.post<void>('/api/v1/notifications/dismiss', {
+    return this.post<void>('/api/v1/notifications/dismiss', {
       id,
     });
   }
@@ -898,10 +850,7 @@ export class Masto {
    */
   @available({ since: '2.4.0' })
   public addPushSubscription(params: AddPushSubscriptionParams) {
-    return this.gateway.post<PushSubscription>(
-      '/api/v1/push/subscription',
-      params,
-    );
+    return this.post<PushSubscription>('/api/v1/push/subscription', params);
   }
 
   /**
@@ -911,7 +860,7 @@ export class Masto {
    */
   @available({ since: '2.4.0' })
   public fetchPushSubscription() {
-    return this.gateway.get<PushSubscription>('/api/v1/push/subscription');
+    return this.get<PushSubscription>('/api/v1/push/subscription');
   }
 
   /**
@@ -922,10 +871,7 @@ export class Masto {
    */
   @available({ since: '2.4.0' })
   public updatePushSubscription(params: UpdatePushSubscriptionParams) {
-    return this.gateway.put<PushSubscription>(
-      '/api/v1/push/subscription',
-      params,
-    );
+    return this.put<PushSubscription>('/api/v1/push/subscription', params);
   }
 
   /**
@@ -935,7 +881,7 @@ export class Masto {
    */
   @available({ since: '2.4.0' })
   public removePushSubscription() {
-    return this.gateway.delete<void>('/api/v1/push/subscription');
+    return this.delete<void>('/api/v1/push/subscription');
   }
 
   /**
@@ -946,7 +892,7 @@ export class Masto {
    */
   @available({ since: '2.8.0' })
   public fetchPoll(id: string) {
-    return this.gateway.get<Poll>(`/api/v1/polls/${id}`);
+    return this.get<Poll>(`/api/v1/polls/${id}`);
   }
 
   /**
@@ -958,7 +904,7 @@ export class Masto {
    */
   @available({ since: '2.8.0' })
   public votePoll(id: string, params: VotePollParams) {
-    return this.gateway.post<Poll>(`/api/v1/polls/${id}/votes`, params);
+    return this.post<Poll>(`/api/v1/polls/${id}/votes`, params);
   }
 
   /**
@@ -969,7 +915,7 @@ export class Masto {
    */
   @available({ since: '1.1.0' })
   public reportAccount(params: ReportAccountParams) {
-    return this.gateway.post<void>('/api/v1/reports', params);
+    return this.post<void>('/api/v1/reports', params);
   }
 
   /**
@@ -979,7 +925,7 @@ export class Masto {
    */
   @available({ since: '2.7.0' })
   public fetchScheduledStatuses() {
-    return this.gateway.get<ScheduledStatus[]>('/api/v1/scheduled_statuses');
+    return this.get<ScheduledStatus[]>('/api/v1/scheduled_statuses');
   }
 
   /**
@@ -990,9 +936,7 @@ export class Masto {
    */
   @available({ since: '2.7.0' })
   public fetchScheduledStatus(id: string) {
-    return this.gateway.get<ScheduledStatus>(
-      `/api/v1/scheduled_statuses/${id}`,
-    );
+    return this.get<ScheduledStatus>(`/api/v1/scheduled_statuses/${id}`);
   }
 
   /**
@@ -1007,7 +951,7 @@ export class Masto {
     id: string,
     params: UpdateScheduledStatusParams,
   ) {
-    return this.gateway.put<ScheduledStatus>(
+    return this.put<ScheduledStatus>(
       `/api/v1/scheduled_statuses/${id}`,
       params,
     );
@@ -1021,7 +965,7 @@ export class Masto {
    */
   @available({ since: '2.7.0' })
   public removeScheduledStatus(id: string) {
-    return this.gateway.delete<void>(`/api/v1/scheduled_statuses/${id}`);
+    return this.delete<void>(`/api/v1/scheduled_statuses/${id}`);
   }
 
   /**
@@ -1036,7 +980,7 @@ export class Masto {
     params: SearchParams,
     version = 'v2' as V,
   ) {
-    return this.gateway.paginate<V extends 'v2' ? Results : ResultsV1>(
+    return this.paginate<V extends 'v2' ? Results : ResultsV1>(
       `/api/${version}/search`,
       params,
     );
@@ -1050,7 +994,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchStatus(id: string) {
-    return this.gateway.get<Status>(`/api/v1/statuses/${id}`);
+    return this.get<Status>(`/api/v1/statuses/${id}`);
   }
 
   /**
@@ -1061,7 +1005,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchStatusContext(id: string) {
-    return this.gateway.get<Context>(`/api/v1/statuses/${id}/context`);
+    return this.get<Context>(`/api/v1/statuses/${id}/context`);
   }
 
   /**
@@ -1071,7 +1015,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchStatusCard(id: string) {
-    return this.gateway.get<Card>(`/api/v1/statuses/${id}/card`);
+    return this.get<Card>(`/api/v1/statuses/${id}/card`);
   }
 
   /**
@@ -1083,7 +1027,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchStatusRebloggedBy(id: string, params?: PaginationParams) {
-    return this.gateway.paginate<Account[]>(
+    return this.paginate<Account[]>(
       `/api/v1/statuses/${id}/reblogged_by`,
       params,
     );
@@ -1098,7 +1042,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchStatusFavouritedBy(id: string, params?: PaginationParams) {
-    return this.gateway.paginate<Account[]>(
+    return this.paginate<Account[]>(
       `/api/v1/statuses/${id}/favourited_by`,
       params,
     );
@@ -1114,12 +1058,12 @@ export class Masto {
   @available({ since: '0.0.0' })
   public createStatus(params?: CreateStatusParams, idempotencyKey?: string) {
     if (idempotencyKey) {
-      return this.gateway.post<Status>('/api/v1/statuses', params, {
+      return this.post<Status>('/api/v1/statuses', params, {
         headers: { 'Idempotency-Key': idempotencyKey },
       });
     }
 
-    return this.gateway.post<Status>('/api/v1/statuses', params);
+    return this.post<Status>('/api/v1/statuses', params);
   }
 
   /**
@@ -1130,7 +1074,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public removeStatus(id: string) {
-    return this.gateway.delete<Status>(`/api/v1/statuses/${id}`);
+    return this.delete<Status>(`/api/v1/statuses/${id}`);
   }
 
   /**
@@ -1141,7 +1085,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public reblogStatus(id: string, params?: ReblogStatusParams) {
-    return this.gateway.post<Status>(`/api/v1/statuses/${id}/reblog`, params);
+    return this.post<Status>(`/api/v1/statuses/${id}/reblog`, params);
   }
 
   /**
@@ -1152,7 +1096,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public unreblogStatus(id: string) {
-    return this.gateway.post<Status>(`/api/v1/statuses/${id}/unreblog`);
+    return this.post<Status>(`/api/v1/statuses/${id}/unreblog`);
   }
 
   /**
@@ -1163,7 +1107,7 @@ export class Masto {
    */
   @available({ since: '1.6.0' })
   public pinStatus(id: string) {
-    return this.gateway.post<Status>(`/api/v1/statuses/${id}/pin`);
+    return this.post<Status>(`/api/v1/statuses/${id}/pin`);
   }
 
   /**
@@ -1174,7 +1118,7 @@ export class Masto {
    */
   @available({ since: '1.6.0' })
   public unpinStatus(id: string) {
-    return this.gateway.post<Status>(`/api/v1/statuses/${id}/unpin`);
+    return this.post<Status>(`/api/v1/statuses/${id}/unpin`);
   }
 
   /**
@@ -1185,7 +1129,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchHomeTimeline(params?: FetchTimelineParams) {
-    return this.gateway.paginate<Status[]>('/api/v1/timelines/home', params);
+    return this.paginate<Status[]>('/api/v1/timelines/home', params);
   }
 
   /**
@@ -1196,7 +1140,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchCommunityTimeline(params?: FetchTimelineParams) {
-    return this.gateway.paginate<Status[]>('/api/v1/timelines/public', {
+    return this.paginate<Status[]>('/api/v1/timelines/public', {
       local: true,
       ...params,
     });
@@ -1210,7 +1154,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchPublicTimeline(params?: FetchTimelineParams) {
-    return this.gateway.paginate<Status[]>('/api/v1/timelines/public', params);
+    return this.paginate<Status[]>('/api/v1/timelines/public', params);
   }
 
   /**
@@ -1222,10 +1166,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public fetchTagTimeline(id: string, params?: FetchTimelineParams) {
-    return this.gateway.paginate<Status[]>(
-      `/api/v1/timelines/tag/${id}`,
-      params,
-    );
+    return this.paginate<Status[]>(`/api/v1/timelines/tag/${id}`, params);
   }
 
   /**
@@ -1237,10 +1178,7 @@ export class Masto {
    */
   @available({ since: '2.1.0' })
   public fetchListTimeline(id: string, params?: FetchTimelineParams) {
-    return this.gateway.paginate<Status[]>(
-      `/api/v1/timelines/list/${id}`,
-      params,
-    );
+    return this.paginate<Status[]>(`/api/v1/timelines/list/${id}`, params);
   }
 
   /**
@@ -1249,7 +1187,7 @@ export class Masto {
    */
   @available({ since: '0.0.0', until: '2.5.2' })
   public fetchDirectTimeline(params?: FetchTimelineParams) {
-    return this.gateway.paginate<Status[]>('/api/v1/timelines/direct', params);
+    return this.paginate<Status[]>('/api/v1/timelines/direct', params);
   }
 
   /**
@@ -1258,10 +1196,7 @@ export class Masto {
    */
   @available({ since: '2.6.0' })
   public fetchConversations(params?: PaginationParams) {
-    return this.gateway.paginate<Conversation[]>(
-      '/api/v1/conversations',
-      params,
-    );
+    return this.paginate<Conversation[]>('/api/v1/conversations', params);
   }
 
   /**
@@ -1272,7 +1207,7 @@ export class Masto {
    */
   @available({ since: '0.0.0' })
   public followAccountByUsername(uri: string) {
-    return this.gateway.post<Account>('/api/v1/follows', { uri });
+    return this.post<Account>('/api/v1/follows', { uri });
   }
 
   /**
@@ -1282,6 +1217,6 @@ export class Masto {
    */
   @available({ since: '2.8.0' })
   public fetchPreferences() {
-    return this.gateway.get<Preference>('/api/v1/preferences');
+    return this.get<Preference>('/api/v1/preferences');
   }
 }
diff --git a/src/client/params.ts b/src/clients/masto/params.ts
similarity index 95%
rename from src/client/params.ts
rename to src/clients/masto/params.ts
index 128f68bb..381d4909 100644
--- a/src/client/params.ts
+++ b/src/clients/masto/params.ts
@@ -1,16 +1,13 @@
 import { ReadStream } from 'fs';
-import { AccountField, AccountSource } from '../entities/account';
-import { FilterContext } from '../entities/filter';
-import { NotificationType } from '../entities/notification';
-import { PushSubscriptionAlerts } from '../entities/push-subscription';
-import { StatusVisibility } from '../entities/status';
-import { GatewayConstructor } from './gateway';
+import { AccountField, AccountSource } from '../../entities/account';
+import { FilterContext } from '../../entities/filter';
+import { NotificationType } from '../../entities/notification';
+import { PushSubscriptionAlerts } from '../../entities/push-subscription';
+import { StatusVisibility } from '../../entities/status';
 
 /** Union of acceptable values of form-data for browser and node */
 export type IsomorphicFormDataValue = string | Blob | Buffer | ReadStream;
 
-export type LoginParams = Pick<GatewayConstructor, 'uri' | 'accessToken'>;
-
 export interface PaginationParams {
   /** Get a list of items with ID less than this value */
   max_id?: string | null;
diff --git a/src/entities/admin-account.ts b/src/entities/admin-account.ts
new file mode 100644
index 00000000..a4aa080e
--- /dev/null
+++ b/src/entities/admin-account.ts
@@ -0,0 +1,24 @@
+export type AdminAccountRole = 'moderator' | 'admin' | 'user';
+
+/**
+ * Account entity from moderation apis
+ */
+export interface AdminAccount {
+  id: string;
+  username: string;
+  domain: string;
+  created_at: string;
+  email: string;
+  role: AdminAccountRole;
+  ip: string;
+  confirmed: boolean;
+  suspended: boolean;
+  silenced: boolean;
+  disabled: boolean;
+  approved: boolean;
+  account: Account;
+  locale?: string | null;
+  invite_request?: string | null;
+  created_by_application_id?: string | null;
+  invited_by_account_id?: string | null;
+}
diff --git a/src/entities/admin-report.ts b/src/entities/admin-report.ts
new file mode 100644
index 00000000..8f73414e
--- /dev/null
+++ b/src/entities/admin-report.ts
@@ -0,0 +1,14 @@
+import { Status } from './status';
+
+export interface AdminReport {
+  id: string;
+  action_taken: boolean;
+  comment: string;
+  created_at: string;
+  updated_at: string;
+  account_id: string;
+  target_account_id: string;
+  assigned_account_id: string;
+  action_taken_by_account_id: string;
+  statuses: Status[];
+}
diff --git a/src/client/__mocks__/masto-events.ts b/src/gateway/__mocks__/websocket.ts
similarity index 58%
rename from src/client/__mocks__/masto-events.ts
rename to src/gateway/__mocks__/websocket.ts
index 33729dea..3595a662 100644
--- a/src/client/__mocks__/masto-events.ts
+++ b/src/gateway/__mocks__/websocket.ts
@@ -1,5 +1,5 @@
 export const connectMock = jest.fn();
 
-export const MastoEvents = jest.fn(() => ({
+export const WebSocketEvents = jest.fn(() => ({
   connect: connectMock,
 }));
diff --git a/src/client/gateway.ts b/src/gateway/gateway.ts
similarity index 92%
rename from src/client/gateway.ts
rename to src/gateway/gateway.ts
index f3a4f012..bb831415 100644
--- a/src/client/gateway.ts
+++ b/src/gateway/gateway.ts
@@ -3,16 +3,17 @@ import normalizeUrl from 'normalize-url';
 import querystring from 'querystring';
 import semver from 'semver';
 import { oc } from 'ts-optchain';
+import { Instance } from '../entities/instance';
 import { MastoNotFoundError } from '../errors/masto-not-found-error';
 import { MastoRateLimitError } from '../errors/masto-rate-limit-error';
 import { MastoUnauthorizedError } from '../errors/masto-unauthorized-error';
-import { MastoEvents } from './masto-events';
 import { isAxiosError } from './utils';
+import { WebSocketEvents } from './websocket';
 
 // tslint:disable-next-line no-import-side-effect
 import 'isomorphic-form-data';
 
-export interface GatewayConstructor {
+export interface GatewayConstructorParams {
   /** URI of the instance */
   uri: string;
   /** Streaming API URL */
@@ -23,6 +24,8 @@ export interface GatewayConstructor {
   accessToken?: string;
 }
 
+export type LoginParams = Pick<GatewayConstructorParams, 'uri' | 'accessToken'>;
+
 export type PaginateNextOptions<Params> = {
   /** Reset pagination */
   reset?: boolean;
@@ -49,7 +52,7 @@ export class Gateway {
   /**
    * @param params Parameters
    */
-  public constructor(params: GatewayConstructor) {
+  constructor(params: GatewayConstructorParams) {
     this.uri = params.uri;
 
     if (params.streamingApiUrl) {
@@ -81,6 +84,23 @@ export class Gateway {
     this._streamingApiUrl = normalizeUrl(streamingApiUrl);
   }
 
+  /**
+   * Login to Mastodon
+   * @param params Paramters
+   * @return Instance of Mastodon class
+   */
+  public static async login<T extends typeof Gateway>(
+    this: T,
+    params: LoginParams,
+  ) {
+    const gateway = new this(params) as InstanceType<T>;
+    const instance = await gateway.get<Instance>('/api/v1/instance');
+    gateway.version = instance.version;
+    gateway.streamingApiUrl = instance.urls.streaming_api;
+
+    return gateway;
+  }
+
   /**
    * Transform JSON to JS object
    * @param response Response object
@@ -333,7 +353,7 @@ export class Gateway {
       path +
       (Object.keys(params).length ? `?${querystring.stringify(params)}` : '');
 
-    return new MastoEvents().connect(url, protocols);
+    return new WebSocketEvents().connect(url, protocols);
   }
 
   /**
@@ -372,7 +392,7 @@ export class Gateway {
         );
 
         // Set next url from the link header
-        const link = oc(response.headers.link)('');
+        const link = oc(response.headers).link('');
         const match = link.match(/<(.+?)>; rel="next"/) as string[];
 
         currentUrl = (match && match.length && match[1]) || '';
diff --git a/src/client/utils.ts b/src/gateway/utils.ts
similarity index 100%
rename from src/client/utils.ts
rename to src/gateway/utils.ts
diff --git a/src/gateway/websocket.ts b/src/gateway/websocket.ts
new file mode 100644
index 00000000..9c3a3203
--- /dev/null
+++ b/src/gateway/websocket.ts
@@ -0,0 +1,147 @@
+// tslint:disable no-unnecessary-override
+import EventEmitter from 'eventemitter3';
+import WebSocket from 'isomorphic-ws';
+import { Conversation } from '../entities/conversation';
+import { Notification } from '../entities/notification';
+import { Status } from '../entities/status';
+
+/** Mastodon event */
+export interface Event {
+  event: EventType;
+  payload: string;
+}
+
+export interface EventTypeMap {
+  /** Status posted */
+  update: Status;
+  /** Status deleted */
+  delete: Status['id'];
+  /** User's notification */
+  notification: Notification;
+  /** User's filter changed */
+  filters_changed: undefined;
+  /** Status added to a conversation */
+  conversation: Conversation;
+}
+
+export type EventType = keyof EventTypeMap;
+export type EventListener<T extends EventType> = (
+  payload: EventTypeMap[T],
+) => void;
+
+/**
+ * Mastodon streaming api wrapper
+ */
+export class WebSocketEvents extends EventEmitter {
+  private ws?: WebSocket;
+
+  /**
+   * Connect to the websocket endpoint
+   * @param url URL of the websocket endpoint
+   * @param protocols Subprotocol(s) for `Sec-Websocket-Protocol`
+   * @param params URL parameters
+   */
+  public connect(url: string, protocols?: string | string[]) {
+    return new Promise<WebSocketEvents>((resolve, reject) => {
+      this.ws = new WebSocket(url, protocols);
+
+      this.ws.on('message', this.handleMessage);
+      this.ws.on('error', reject);
+      this.ws.on('open', () => {
+        resolve(this);
+      });
+    });
+  }
+
+  /**
+   * Disconnect from the websocket endpoint
+   */
+  public disconnect() {
+    if (!this.ws) return;
+    this.ws.close();
+  }
+
+  /**
+   * Parse JSON data and emit it as an event
+   * @param message Websocket message
+   */
+  public handleMessage = (message: string) => {
+    const event = JSON.parse(message) as Event;
+    let data: EventTypeMap[keyof EventTypeMap];
+
+    try {
+      data = JSON.parse(event.payload);
+    } catch {
+      // If parsing failed, returns raw data
+      // Basically this is handling for `filters_changed` event
+      // Which doesn't contain payload in the data
+      data = event.payload;
+    }
+
+    this.emit(event.event, data);
+  };
+
+  /*-------------------------------
+   *
+   * ↓ Overwriting signatures
+   *
+   *------------------------------*/
+
+  public listeners<T extends EventType>(event: T) {
+    return super.listeners(event);
+  }
+
+  public listenerCount<T extends EventType>(event: T) {
+    return super.listenerCount(event);
+  }
+
+  public emit<T extends EventType>(event: T, ...args: any[]) {
+    return super.emit(event, ...args);
+  }
+
+  public addListener<T extends EventType>(
+    event: T,
+    fn: EventListener<T>,
+    context?: any,
+  ) {
+    return super.addListener(event, fn, context);
+  }
+
+  public on<T extends EventType>(
+    event: T,
+    fn: EventListener<T>,
+    context?: any,
+  ) {
+    return super.on(event, fn, context);
+  }
+
+  public once<T extends EventType>(
+    event: T,
+    fn: EventListener<T>,
+    context?: any,
+  ) {
+    return super.once(event, fn, context);
+  }
+
+  public removeListener<T extends EventType>(
+    event: T,
+    fn?: EventListener<T>,
+    context?: any,
+    once?: boolean,
+  ) {
+    return super.removeListener(event, fn, context, once);
+  }
+
+  public off<T extends EventType>(
+    event: T,
+    fn?: EventListener<T>,
+    context?: any,
+    once?: boolean,
+  ) {
+    return super.off(event, fn, context, once);
+  }
+
+  public removeAllListeners<T extends EventType>(event?: T) {
+    return super.removeAllListeners(event);
+  }
+}
diff --git a/src/index.ts b/src/index.ts
index 889e9c34..25a90fad 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,8 +1,14 @@
-export * from './client/decorators';
-export * from './client/gateway';
-export * from './client/params';
-export * from './client/masto-events';
-export * from './client/utils';
+export * from './gateway/gateway';
+export * from './gateway/websocket';
+export * from './gateway/utils';
+
+export * from './clients/decorators';
+
+export * from './clients/masto/masto';
+export * from './clients/masto/params';
+
+export * from './clients/masto-admin/masto-admin';
+export * from './clients/masto-admin/params';
 
 export * from './entities/account';
 export * from './entities/application';
@@ -30,5 +36,4 @@ export * from './errors/masto-not-found-error';
 export * from './errors/masto-rate-limit-error';
 export * from './errors/masto-unauthorized-error';
 
-export * from './client/masto';
-export { Masto as default } from './client/masto';
+export { Masto as default } from './clients/masto/masto';


Test patch:
diff --git a/src/client/__tests__/__snapshots__/masto.spec.ts.snap b/src/client/__tests__/__snapshots__/masto.spec.ts.snap
deleted file mode 100644
index 02e6b0d6..00000000
--- a/src/client/__tests__/__snapshots__/masto.spec.ts.snap
+++ /dev/null
@@ -1,2056 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Masto addAccountToList 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/lists/123123/accounts",
-      Object {
-        "account_ids": Array [
-          "123",
-          "456",
-          "678",
-        ],
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto addPushSubscription 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/push/subscription",
-      Object {
-        "data": Object {
-          "alerts": Object {
-            "favourite": true,
-            "follow": true,
-            "mention": true,
-            "reblog": true,
-          },
-        },
-        "subscription": Object {
-          "endpoint": "https://example.com",
-          "keys": Object {
-            "auth": "yyyy",
-            "p256dh": "xxxx",
-          },
-        },
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto authorizeFollowRequest 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/follow_requests/123123/authorize",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto blockAccount 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/accounts/123123/block",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto blockDomain 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/domain_blocks",
-      Object {
-        "domain": "example.com",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto clearNotifications 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/notifications/clear",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto createAccount 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/accounts",
-      Object {
-        "agreement": true,
-        "email": "example@example.com",
-        "password": "password",
-        "username": "username",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto createApp 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/apps",
-      Object {
-        "client_name": "My Client",
-        "redirect_uris": "https://example.com",
-        "scopes": "write read",
-        "website": "https://example.com",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto createFiler 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/filters",
-      Object {
-        "context": Array [
-          "home",
-          "notifications",
-          "public",
-          "thread",
-        ],
-        "expires_in": 3600000,
-        "irreversible": true,
-        "phrase": "Twitter",
-        "whole_word": true,
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto createList 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/lists",
-      Object {
-        "title": "My list",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto createStatus with Idempotency-Key 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/statuses",
-      Object {
-        "status": "Too!",
-      },
-      Object {
-        "headers": Object {
-          "Idempotency-Key": "59fe7e30-1a74-4050-8af7-5a8c7a224794",
-        },
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto createStatus with content 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/statuses",
-      Object {
-        "in_reply_to_id": "123123",
-        "language": "en",
-        "poll": Object {
-          "expires_in": 60000,
-          "hide_totals": true,
-          "multiple": false,
-          "options": Array [
-            "xxx",
-            "yyy",
-            "zzz",
-          ],
-        },
-        "scheduled_at": "2019-03-28T04:39:31.121Z",
-        "sensitive": false,
-        "spoiler_text": "spoiler",
-        "status": "Toot!",
-        "visibility": "direct",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto createStatus with media ids 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/statuses",
-      Object {
-        "media_ids": Array [
-          "123",
-          "456",
-        ],
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto dissmissNotification 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/notifications/dismiss",
-      Object {
-        "id": "123123",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto favouriteStatus 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/statuses/123123/favourite",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchAccessToken with authorization code 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/oauth/token",
-      Object {
-        "client_id": "123123123",
-        "client_secret": "456456456",
-        "code": "789789789",
-        "grant_type": "authorization_code",
-        "redirect_uri": "https://example.com",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchAccessToken with password 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/oauth/token",
-      Object {
-        "grant_type": "password",
-        "password": "password",
-        "username": "username",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchAccount 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/accounts/123123123",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchAccountFollowers 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/accounts/123123123/followers",
-      Object {
-        "limit": 10,
-        "max_id": "5",
-        "min_id": "2",
-        "since_id": "3",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchAccountFollowing 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/accounts/123123123/following",
-      Object {
-        "limit": 10,
-        "max_id": "5",
-        "min_id": "2",
-        "since_id": "3",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchAccountIdentityProofs 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/accounts/123123123/identity_proofs",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchAccountLists 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/accounts/123123/lists",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchAccountRelationships 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/accounts/relationship",
-      Object {
-        "id": Array [
-          "123123",
-          "456456",
-        ],
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchAccountStatuses 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/accounts/123123123/statuses",
-      Object {
-        "limit": 10,
-        "max_id": "5",
-        "min_id": "2",
-        "since_id": "3",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchBlocks 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/blocks",
-      Object {
-        "limit": 10,
-        "max_id": "5",
-        "min_id": "2",
-        "since_id": "3",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchCommunityTimeline 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/timelines/public",
-      Object {
-        "limit": 10,
-        "local": true,
-        "max_id": "5",
-        "min_id": "2",
-        "since_id": "3",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchConversations 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/conversations",
-      Object {
-        "limit": 10,
-        "max_id": "5",
-        "min_id": "2",
-        "since_id": "3",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchCustomEmojis 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/custom_emojis",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchDirectTimeline 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/timelines/direct",
-      Object {
-        "limit": 10,
-        "max_id": "5",
-        "min_id": "2",
-        "since_id": "3",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchDomainBlocks 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/domain_blocks",
-      undefined,
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchEndorsements 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/endorsements",
-      Object {
-        "limit": 10,
-        "max_id": "5",
-        "min_id": "2",
-        "since_id": "3",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchFavourites 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/favourites",
-      Object {
-        "limit": 10,
-        "max_id": "5",
-        "min_id": "2",
-        "since_id": "3",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchFilter 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/filters/123123",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchFilters 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/filters",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchFollowRequests 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/follow_requests",
-      Object {
-        "limit": 10,
-        "max_id": "5",
-        "min_id": "2",
-        "since_id": "3",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchHomeTimeline 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/timelines/home",
-      Object {
-        "limit": 10,
-        "max_id": "5",
-        "min_id": "2",
-        "since_id": "3",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchInstance 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/suggestions",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchInstanceActivity 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/instance/activity",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchInstancesPeers 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/instance/peers",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchList 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/lists/123123",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchListAccounts 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/list/123123/accounts",
-      Object {
-        "limit": 10,
-        "max_id": "5",
-        "min_id": "2",
-        "since_id": "3",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchListTimeline 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/timelines/list/123123",
-      Object {
-        "limit": 10,
-        "max_id": "5",
-        "min_id": "2",
-        "since_id": "3",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchLists 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/lists",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchMutes 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/mutes",
-      Object {
-        "limit": 10,
-        "max_id": "5",
-        "min_id": "2",
-        "since_id": "3",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchNotification 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/notifications/123123",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchNotifications 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/notifications",
-      Object {
-        "exclude_types": Array [
-          "favourite",
-          "follow",
-          "mention",
-          "poll",
-          "reblog",
-        ],
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchPoll 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/polls/123123",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchPreferences 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/preferences",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchPublicTimeline 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/timelines/public",
-      Object {
-        "limit": 10,
-        "max_id": "5",
-        "min_id": "2",
-        "since_id": "3",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchPushSubscription 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/push/subscription",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchScheduledStatus 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/scheduled_statuses/123123",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchScheduledStatuses 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/scheduled_statuses",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchStatus 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/statuses/123123",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchStatusCard 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/statuses/123123/card",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchStatusContext 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/statuses/123123/context",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchStatusFavouritedBy 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/statuses/123123/favourited_by",
-      Object {
-        "limit": 10,
-        "max_id": "5",
-        "min_id": "2",
-        "since_id": "3",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchStatusRebloggedBy 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/statuses/123123/reblogged_by",
-      Object {
-        "limit": 10,
-        "max_id": "5",
-        "min_id": "2",
-        "since_id": "3",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchSuggestions 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/suggestions",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto fetchTagTimeline 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/timelines/tag/DeleteTwitter",
-      Object {
-        "limit": 10,
-        "max_id": "5",
-        "min_id": "2",
-        "since_id": "3",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto followAccount 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/accounts/123123/follow",
-      Object {
-        "reblogs": false,
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto followAccountByUsername 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/follows",
-      Object {
-        "uri": "user@example.com",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto muteAccount 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/accounts/123123/mute",
-      Object {
-        "notifications": false,
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto muteStatus 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/statuses/123123/mute",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto pinAccount 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/accounts/123123/pin",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto pinStatus 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/statuses/123123/pin",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto reblogStatus 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/statuses/123123/reblog",
-      Object {
-        "visibility": "direct",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto rejectFollowRequest 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/follow_requests/123123/reject",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto removeAccountFromList 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/lists/123123/accounts",
-      Object {
-        "account_ids": Array [
-          "123",
-          "456",
-          "678",
-        ],
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto removeFilter 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/filters/123123",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto removeList 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/lists/123123",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto removePushSubscription 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/push/subscription",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto removeScheduledStatus 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/scheduled_statuses/123123",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto removeStatus 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/statuses/123123",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto removeSuggestion 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/suggestions/123123",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto reportAccount 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/reports",
-      Object {
-        "account_id": "123123",
-        "comment": "this is a report",
-        "forward": true,
-        "status_ids": Array [
-          "456456",
-        ],
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto revokeAccessToken 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/oauth/revoke",
-      Object {
-        "client_id": "123123123",
-        "client_secret": "456456456",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto search (v1) 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/search",
-      Object {
-        "q": "query",
-        "resolve": true,
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto search 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v2/search",
-      Object {
-        "account_id": "123",
-        "limit": 10,
-        "max_id": "5",
-        "min_id": "2",
-        "q": "query",
-        "resolve": true,
-        "since_id": "3",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": undefined,
-    },
-  ],
-}
-`;
-
-exports[`Masto searchAccounts 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/accounts/search",
-      Object {
-        "following": false,
-        "limit": 123,
-        "q": "query",
-        "resolve": true,
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto streamCommunityTimeline 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/streaming",
-      Object {
-        "stream": "public:local",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto streamDirectTimeline 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/streaming",
-      Object {
-        "stream": "direct",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto streamListTimeline 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/streaming",
-      Object {
-        "list": "123123",
-        "stream": "list",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto streamLocalTagTimeline 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/streaming",
-      Object {
-        "stream": "hashtag:local",
-        "tag": "deletetwitter",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto streamPublicTimeline 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/streaming",
-      Object {
-        "stream": "public",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto streamTagTimeline 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/streaming",
-      Object {
-        "stream": "hashtag",
-        "tag": "deletetwitter",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto streamUser 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/streaming",
-      Object {
-        "stream": "user",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto unblockAccount 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/accounts/123123/unblock",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto unblockDomain 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/domain_blocks",
-      Object {
-        "domain": "example.com",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto unfavouriteStatus 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/statuses/123123/unfavourite",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto unfollowAccount 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/accounts/123123/unfollow",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto unmuteAccount 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/accounts/123123/unmute",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto unmuteStatus 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/statuses/123123/unmute",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto unpinAccount 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/accounts/123123/unpin",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto unpinStatus 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/statuses/123123/unpin",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto unreblogStatus 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/statuses/123123/unreblog",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto updateCredentials 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/accounts/update_credentials",
-      Object {
-        "avatar": "...",
-        "display_name": "Neetshin",
-        "fields_attributes": Array [
-          Object {
-            "name": "GitHub",
-            "value": "https://github.com/neet",
-          },
-        ],
-        "header": "...",
-        "locked": false,
-        "note": "web frontend engineer",
-        "source": Object {
-          "language": "ja",
-          "privacy": "direct",
-          "sensitive": false,
-        },
-      },
-      Object {
-        "headers": Object {
-          "Content-Type": "multipart/form-data",
-        },
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto updateFilter 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/filters/123123",
-      Object {
-        "context": Array [
-          "home",
-          "notifications",
-          "public",
-          "thread",
-        ],
-        "expires_in": 3600000,
-        "irreversible": true,
-        "phrase": "Twitter",
-        "whole_word": true,
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto updateList 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/lists/123123",
-      Object {
-        "title": "My list",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto updateMediaAttachment 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/media/123123",
-      Object {
-        "description": "Nice image",
-        "focus": "0, 0",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto updatePushSubscription 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/push/subscription",
-      Object {
-        "data": Object {
-          "alerts": Object {
-            "favourite": true,
-            "follow": true,
-            "mention": true,
-            "reblog": true,
-          },
-        },
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto updateScheduledStatus 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/scheduled_statuses/123123",
-      Object {
-        "scheduled_at": "2019-03-28T04:39:31.121Z",
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto uploadMediaAttachment 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/media",
-      Object {
-        "description": "Nice image",
-        "file": "...",
-      },
-      Object {
-        "headers": Object {
-          "Content-Type": "multipart/form-data",
-        },
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto verifyAppCredentials 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/apps/verify_credentials",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto verifyCredentials 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/accounts/verify_credentials",
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
-
-exports[`Masto votePoll 1`] = `
-[MockFunction] {
-  "calls": Array [
-    Array [
-      "/api/v1/polls/123123/votes",
-      Object {
-        "choices": Array [
-          "xxx",
-          "yyy",
-          "zzz",
-        ],
-      },
-    ],
-  ],
-  "results": Array [
-    Object {
-      "type": "return",
-      "value": Promise {},
-    },
-  ],
-}
-`;
diff --git a/src/client/__tests__/masto.spec.ts b/src/client/__tests__/masto.spec.ts
deleted file mode 100644
index 4dc34408..00000000
--- a/src/client/__tests__/masto.spec.ts
+++ /dev/null
@@ -1,908 +0,0 @@
-// tslint:disable
-// @ts-ignore
-// prettier-ignore
-import { getMock, postMock, deleteMock, patchMock, putMock, streamMock, paginateMock, Gateway } from '../gateway';
-import { Masto } from '../masto';
-
-jest.mock('../gateway');
-
-describe('Masto', () => {
-  let masto!: Masto;
-
-  beforeEach(() => {
-    // @ts-ignore
-    masto = new Masto(new Gateway());
-
-    (getMock as jest.Mock).mockClear();
-    (postMock as jest.Mock).mockClear();
-    (deleteMock as jest.Mock).mockClear();
-    (patchMock as jest.Mock).mockClear();
-    (putMock as jest.Mock).mockClear();
-    (streamMock as jest.Mock).mockClear();
-    (paginateMock as jest.Mock).mockClear();
-  });
-
-  test('login', async () => {
-    (getMock as jest.Mock).mockResolvedValueOnce({
-      version: '2.8.0',
-      urls: {
-        streaming_api: 'wss://example.com/stream',
-      },
-    });
-
-    const params = {
-      uri: 'https://example.com',
-      accessToken: 'tokentoken',
-    };
-    const masto = await Masto.login(params);
-
-    expect((Gateway as any) as jest.Mock).toBeCalledWith(params);
-    expect(getMock).toBeCalledWith(expect.stringContaining('/api/v1/instance'));
-    expect(masto.gateway.version).toBe('2.8.0');
-    expect(masto.gateway.streamingApiUrl).toBe('wss://example.com/stream');
-  });
-
-  test('streamUser', async () => {
-    await masto.streamUser();
-    expect(streamMock).toBeCalledTimes(1);
-    expect(streamMock).toMatchSnapshot();
-  });
-
-  test('streamPublicTimeline', async () => {
-    await masto.streamPublicTimeline();
-    expect(streamMock).toBeCalledTimes(1);
-    expect(streamMock).toMatchSnapshot();
-  });
-
-  test('streamCommunityTimeline', async () => {
-    await masto.streamCommunityTimeline();
-    expect(streamMock).toBeCalledTimes(1);
-    expect(streamMock).toMatchSnapshot();
-  });
-
-  test('streamTagTimeline', async () => {
-    await masto.streamTagTimeline('deletetwitter');
-    expect(streamMock).toBeCalledTimes(1);
-    expect(streamMock).toMatchSnapshot();
-  });
-
-  test('streamLocalTagTimeline', async () => {
-    await masto.streamLocalTagTimeline('deletetwitter');
-    expect(streamMock).toBeCalledTimes(1);
-    expect(streamMock).toMatchSnapshot();
-  });
-
-  test('streamListTimeline', async () => {
-    await masto.streamListTimeline('123123');
-    expect(streamMock).toBeCalledTimes(1);
-    expect(streamMock).toMatchSnapshot();
-  });
-
-  test('streamDirectTimeline', async () => {
-    await masto.streamDirectTimeline();
-    expect(streamMock).toBeCalledTimes(1);
-    expect(streamMock).toMatchSnapshot();
-  });
-
-  test('fetchAccessToken with authorization code', async () => {
-    await masto.fetchAccessToken({
-      grant_type: 'authorization_code',
-      code: '789789789',
-      redirect_uri: 'https://example.com',
-      client_id: '123123123',
-      client_secret: '456456456',
-    });
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('fetchAccessToken with password', async () => {
-    await masto.fetchAccessToken({
-      grant_type: 'password',
-      username: 'username',
-      password: 'password',
-    });
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('revokeAccessToken', async () => {
-    await masto.revokeAccessToken({
-      client_id: '123123123',
-      client_secret: '456456456',
-    });
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('fetchAccount', async () => {
-    await masto.fetchAccount('123123123');
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('fetchAccountIdentityProofs', async () => {
-    await masto.fetchAccountIdentityProofs('123123123');
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('createAccount', async () => {
-    await masto.createAccount({
-      username: 'username',
-      password: 'password',
-      email: 'example@example.com',
-      agreement: true,
-    });
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('verifyCredentials', async () => {
-    await masto.verifyCredentials();
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('updateCredentials', async () => {
-    await masto.updateCredentials({
-      display_name: 'Neetshin',
-      avatar: '...',
-      header: '...',
-      note: 'web frontend engineer',
-      locked: false,
-      source: {
-        privacy: 'direct',
-        sensitive: false,
-        language: 'ja',
-      },
-      fields_attributes: [
-        {
-          name: 'GitHub',
-          value: 'https://github.com/neet',
-        },
-      ],
-    });
-    expect(patchMock).toBeCalledTimes(1);
-    expect(patchMock).toMatchSnapshot();
-  });
-
-  test('fetchAccountFollowers', async () => {
-    await masto.fetchAccountFollowers('123123123', {
-      max_id: '5',
-      since_id: '3',
-      min_id: '2',
-      limit: 10,
-    });
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('fetchAccountFollowing', async () => {
-    await masto.fetchAccountFollowing('123123123', {
-      max_id: '5',
-      since_id: '3',
-      min_id: '2',
-      limit: 10,
-    });
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('fetchAccountStatuses', async () => {
-    await masto.fetchAccountStatuses('123123123', {
-      max_id: '5',
-      since_id: '3',
-      min_id: '2',
-      limit: 10,
-    });
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('followAccount', async () => {
-    await masto.followAccount('123123', {
-      reblogs: false,
-    });
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('unfollowAccount', async () => {
-    await masto.unfollowAccount('123123');
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('fetchAccountRelationships', async () => {
-    await masto.fetchAccountRelationships(['123123', '456456']);
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('searchAccounts', async () => {
-    await masto.searchAccounts({
-      q: 'query',
-      resolve: true,
-      limit: 123,
-      following: false,
-    });
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('createApp', async () => {
-    await masto.createApp({
-      client_name: 'My Client',
-      redirect_uris: 'https://example.com',
-      scopes: 'write read',
-      website: 'https://example.com',
-    });
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('verifyAppCredentials', async () => {
-    await masto.verifyAppCredentials();
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('fetchBlocks', async () => {
-    await masto.fetchBlocks({
-      max_id: '5',
-      since_id: '3',
-      min_id: '2',
-      limit: 10,
-    });
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('blockAccount', async () => {
-    await masto.blockAccount('123123');
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('unblockAccount', async () => {
-    await masto.unblockAccount('123123');
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('fetchCustomEmojis', async () => {
-    await masto.fetchCustomEmojis();
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('fetchDomainBlocks', async () => {
-    await masto.fetchDomainBlocks();
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('blockDomain', async () => {
-    await masto.blockDomain('example.com');
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('unblockDomain', async () => {
-    await masto.unblockDomain('example.com');
-    expect(deleteMock).toBeCalledTimes(1);
-    expect(deleteMock).toMatchSnapshot();
-  });
-
-  test('fetchEndorsements', async () => {
-    await masto.fetchEndorsements({
-      max_id: '5',
-      since_id: '3',
-      min_id: '2',
-      limit: 10,
-    });
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('pinAccount', async () => {
-    await masto.pinAccount('123123');
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('unpinAccount', async () => {
-    await masto.unpinAccount('123123');
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('fetchFavourites', async () => {
-    await masto.fetchFavourites({
-      max_id: '5',
-      since_id: '3',
-      min_id: '2',
-      limit: 10,
-    });
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('favouriteStatus', async () => {
-    await masto.favouriteStatus('123123');
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('unfavouriteStatus', async () => {
-    await masto.unfavouriteStatus('123123');
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('fetchFilters', async () => {
-    await masto.fetchFilters();
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('fetchFilter', async () => {
-    await masto.fetchFilter('123123');
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('createFiler', async () => {
-    await masto.createFiler({
-      phrase: 'Twitter',
-      context: ['home', 'notifications', 'public', 'thread'],
-      irreversible: true,
-      whole_word: true,
-      expires_in: 1000 * 60 * 60,
-    });
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('updateFilter', async () => {
-    await masto.updateFilter('123123', {
-      phrase: 'Twitter',
-      context: ['home', 'notifications', 'public', 'thread'],
-      irreversible: true,
-      whole_word: true,
-      expires_in: 1000 * 60 * 60,
-    });
-    expect(putMock).toBeCalledTimes(1);
-    expect(putMock).toMatchSnapshot();
-  });
-
-  test('removeFilter', async () => {
-    await masto.removeFilter('123123');
-    expect(deleteMock).toBeCalledTimes(1);
-    expect(deleteMock).toMatchSnapshot();
-  });
-
-  test('fetchFollowRequests', async () => {
-    await masto.fetchFollowRequests({
-      max_id: '5',
-      since_id: '3',
-      min_id: '2',
-      limit: 10,
-    });
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('authorizeFollowRequest', async () => {
-    await masto.authorizeFollowRequest('123123');
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('rejectFollowRequest', async () => {
-    await masto.rejectFollowRequest('123123');
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('fetchSuggestions', async () => {
-    await masto.fetchSuggestions();
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('removeSuggestion', async () => {
-    await masto.removeSuggestion('123123');
-    expect(deleteMock).toBeCalledTimes(1);
-    expect(deleteMock).toMatchSnapshot();
-  });
-
-  test('fetchInstance', async () => {
-    await masto.fetchSuggestions();
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('fetchInstancesPeers', async () => {
-    await masto.fetchInstancesPeers();
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('fetchInstanceActivity', async () => {
-    await masto.fetchInstanceActivity();
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('fetchLists', async () => {
-    await masto.fetchLists();
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('fetchAccountLists', async () => {
-    await masto.fetchAccountLists('123123');
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('fetchListAccounts', async () => {
-    await masto.fetchListAccounts('123123', {
-      max_id: '5',
-      since_id: '3',
-      min_id: '2',
-      limit: 10,
-    });
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('fetchList', async () => {
-    await masto.fetchList('123123');
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('createList', async () => {
-    await masto.createList({
-      title: 'My list',
-    });
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('updateList', async () => {
-    await masto.updateList('123123', {
-      title: 'My list',
-    });
-    expect(putMock).toBeCalledTimes(1);
-    expect(putMock).toMatchSnapshot();
-  });
-
-  test('removeList', async () => {
-    await masto.removeList('123123');
-    expect(deleteMock).toBeCalledTimes(1);
-    expect(deleteMock).toMatchSnapshot();
-  });
-
-  test('addAccountToList', async () => {
-    await masto.addAccountToList('123123', {
-      account_ids: ['123', '456', '678'],
-    });
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('removeAccountFromList', async () => {
-    await masto.removeAccountFromList('123123', {
-      account_ids: ['123', '456', '678'],
-    });
-    expect(deleteMock).toBeCalledTimes(1);
-    expect(deleteMock).toMatchSnapshot();
-  });
-
-  test('uploadMediaAttachment', async () => {
-    await masto.uploadMediaAttachment({
-      file: '...',
-      description: 'Nice image',
-    });
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('updateMediaAttachment', async () => {
-    await masto.updateMediaAttachment('123123', {
-      description: 'Nice image',
-      focus: '0, 0',
-    });
-    expect(putMock).toBeCalledTimes(1);
-    expect(putMock).toMatchSnapshot();
-  });
-
-  test('fetchMutes', async () => {
-    await masto.fetchMutes({
-      max_id: '5',
-      since_id: '3',
-      min_id: '2',
-      limit: 10,
-    });
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('muteAccount', async () => {
-    await masto.muteAccount('123123', {
-      notifications: false,
-    });
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('unmuteAccount', async () => {
-    await masto.unmuteAccount('123123');
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('muteStatus', async () => {
-    await masto.muteStatus('123123');
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('unmuteStatus', async () => {
-    await masto.unmuteStatus('123123');
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('fetchNotifications', async () => {
-    await masto.fetchNotifications({
-      exclude_types: ['favourite', 'follow', 'mention', 'poll', 'reblog'],
-    });
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('fetchNotification', async () => {
-    await masto.fetchNotification('123123');
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('clearNotifications', async () => {
-    await masto.clearNotifications();
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('dissmissNotification', async () => {
-    await masto.dissmissNotification('123123');
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('addPushSubscription', async () => {
-    await masto.addPushSubscription({
-      subscription: {
-        endpoint: 'https://example.com',
-        keys: { p256dh: 'xxxx', auth: 'yyyy' },
-      },
-      data: {
-        alerts: {
-          follow: true,
-          favourite: true,
-          reblog: true,
-          mention: true,
-        },
-      },
-    });
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('fetchPushSubscription', async () => {
-    await masto.fetchPushSubscription();
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('updatePushSubscription', async () => {
-    await masto.updatePushSubscription({
-      data: {
-        alerts: {
-          follow: true,
-          favourite: true,
-          reblog: true,
-          mention: true,
-        },
-      },
-    });
-    expect(putMock).toBeCalledTimes(1);
-    expect(putMock).toMatchSnapshot();
-  });
-
-  test('removePushSubscription', async () => {
-    await masto.removePushSubscription();
-    expect(deleteMock).toBeCalledTimes(1);
-    expect(deleteMock).toMatchSnapshot();
-  });
-
-  test('fetchPoll', async () => {
-    await masto.fetchPoll('123123');
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('votePoll', async () => {
-    await masto.votePoll('123123', {
-      choices: ['xxx', 'yyy', 'zzz'],
-    });
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('reportAccount', async () => {
-    await masto.reportAccount({
-      account_id: '123123',
-      status_ids: ['456456'],
-      comment: 'this is a report',
-      forward: true,
-    });
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('fetchScheduledStatuses', async () => {
-    await masto.fetchScheduledStatuses();
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('fetchScheduledStatus', async () => {
-    await masto.fetchScheduledStatus('123123');
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('updateScheduledStatus', async () => {
-    await masto.updateScheduledStatus('123123', {
-      scheduled_at: '2019-03-28T04:39:31.121Z',
-    });
-    expect(putMock).toBeCalledTimes(1);
-    expect(putMock).toMatchSnapshot();
-  });
-
-  test('removeScheduledStatus', async () => {
-    await masto.removeScheduledStatus('123123');
-    expect(deleteMock).toBeCalledTimes(1);
-    expect(deleteMock).toMatchSnapshot();
-  });
-
-  test('search (v1)', async () => {
-    await masto.search(
-      {
-        q: 'query',
-        resolve: true,
-      },
-      'v1',
-    );
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('search', async () => {
-    await masto.search({
-      q: 'query',
-      resolve: true,
-      max_id: '5',
-      since_id: '3',
-      min_id: '2',
-      limit: 10,
-      account_id: '123',
-    });
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('fetchStatus', async () => {
-    await masto.fetchStatus('123123');
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('fetchStatusContext', async () => {
-    await masto.fetchStatusContext('123123');
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('fetchStatusCard', async () => {
-    await masto.fetchStatusCard('123123');
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-
-  test('fetchStatusRebloggedBy', async () => {
-    await masto.fetchStatusRebloggedBy('123123', {
-      max_id: '5',
-      since_id: '3',
-      min_id: '2',
-      limit: 10,
-    });
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('fetchStatusFavouritedBy', async () => {
-    await masto.fetchStatusFavouritedBy('123123', {
-      max_id: '5',
-      since_id: '3',
-      min_id: '2',
-      limit: 10,
-    });
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('createStatus with content', async () => {
-    await masto.createStatus({
-      status: 'Toot!',
-      in_reply_to_id: '123123',
-      poll: {
-        options: ['xxx', 'yyy', 'zzz'],
-        expires_in: 1000 * 60,
-        multiple: false,
-        hide_totals: true,
-      },
-      sensitive: false,
-      spoiler_text: 'spoiler',
-      visibility: 'direct',
-      scheduled_at: '2019-03-28T04:39:31.121Z',
-      language: 'en',
-    });
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('createStatus with media ids', async () => {
-    await masto.createStatus({
-      media_ids: ['123', '456'],
-    });
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('createStatus with Idempotency-Key', async () => {
-    await masto.createStatus(
-      {
-        status: 'Too!',
-      },
-      '59fe7e30-1a74-4050-8af7-5a8c7a224794',
-    );
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('removeStatus', async () => {
-    await masto.removeStatus('123123');
-    expect(deleteMock).toBeCalledTimes(1);
-    expect(deleteMock).toMatchSnapshot();
-  });
-
-  test('reblogStatus', async () => {
-    await masto.reblogStatus('123123', { visibility: 'direct' });
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('unreblogStatus', async () => {
-    await masto.unreblogStatus('123123');
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('pinStatus', async () => {
-    await masto.pinStatus('123123');
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('unpinStatus', async () => {
-    await masto.unpinStatus('123123');
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('fetchHomeTimeline', async () => {
-    await masto.fetchHomeTimeline({
-      max_id: '5',
-      since_id: '3',
-      min_id: '2',
-      limit: 10,
-    });
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('fetchCommunityTimeline', async () => {
-    await masto.fetchCommunityTimeline({
-      max_id: '5',
-      since_id: '3',
-      min_id: '2',
-      limit: 10,
-    });
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('fetchPublicTimeline', async () => {
-    await masto.fetchPublicTimeline({
-      max_id: '5',
-      since_id: '3',
-      min_id: '2',
-      limit: 10,
-    });
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('fetchTagTimeline', async () => {
-    await masto.fetchTagTimeline('DeleteTwitter', {
-      max_id: '5',
-      since_id: '3',
-      min_id: '2',
-      limit: 10,
-    });
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('fetchListTimeline', async () => {
-    await masto.fetchListTimeline('123123', {
-      max_id: '5',
-      since_id: '3',
-      min_id: '2',
-      limit: 10,
-    });
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('fetchDirectTimeline', async () => {
-    masto.gateway.version = '2.5.0';
-    await masto.fetchDirectTimeline({
-      max_id: '5',
-      since_id: '3',
-      min_id: '2',
-      limit: 10,
-    });
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('fetchConversations', async () => {
-    await masto.fetchConversations({
-      max_id: '5',
-      since_id: '3',
-      min_id: '2',
-      limit: 10,
-    });
-    expect(paginateMock).toBeCalledTimes(1);
-    expect(paginateMock).toMatchSnapshot();
-  });
-
-  test('followAccountByUsername', async () => {
-    await masto.followAccountByUsername('user@example.com');
-    expect(postMock).toBeCalledTimes(1);
-    expect(postMock).toMatchSnapshot();
-  });
-
-  test('fetchPreferences', async () => {
-    await masto.fetchPreferences();
-    expect(getMock).toBeCalledTimes(1);
-    expect(getMock).toMatchSnapshot();
-  });
-});
diff --git a/src/client/__tests__/decorators.spec.ts b/src/clients/__tests__/decorators.spec.ts
similarity index 88%
rename from src/client/__tests__/decorators.spec.ts
rename to src/clients/__tests__/decorators.spec.ts
index d22763ac..024fa731 100644
--- a/src/client/__tests__/decorators.spec.ts
+++ b/src/clients/__tests__/decorators.spec.ts
@@ -4,9 +4,7 @@ import { available } from '../decorators';
 describe('available', () => {
   test('throw an error when this.version and param.since is incompatible', () => {
     class Context {
-      gateway = {
-        version: '2.0.0',
-      };
+      public version = '2.0.0';
 
       // @ts-ignore
       @available({ since: '2.1.0' })
@@ -22,9 +20,7 @@ describe('available', () => {
 
   test('throw an error when this.version and param.until is incompatible', () => {
     class Context {
-      gateway = {
-        version: '2.0.0',
-      };
+      public version = '2.0.0';
 
       // @ts-ignore
       @available({ until: '1.9.0' })
@@ -40,9 +36,7 @@ describe('available', () => {
 
   test('not throw an error when this.version and params are compatible', () => {
     class Context {
-      gateway = {
-        version: '2.0.0',
-      };
+      public version = '2.0.0';
 
       // @ts-ignore
       @available({ sicne: '1.9.0', until: '2.1.0' })
diff --git a/src/clients/masto-admin/__tests__/__snapshots__/masto-admin.spec.ts.snap b/src/clients/masto-admin/__tests__/__snapshots__/masto-admin.spec.ts.snap
new file mode 100644
index 00000000..00dd13f6
--- /dev/null
+++ b/src/clients/masto-admin/__tests__/__snapshots__/masto-admin.spec.ts.snap
@@ -0,0 +1,369 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`MastoAdmin actionAccount 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"type\\":\\"disable\\",\\"report_id\\":\\"123123\\",\\"warning_preset_id\\":\\"123123\\",\\"text\\":\\"Your account have been disabled\\",\\"send_email_notification\\":false}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/admin/accounts/123/action",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`MastoAdmin approveAccount 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/admin/accounts/123/approve",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`MastoAdmin assignReportToSelf 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/admin/reports/123/assign_to_self",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`MastoAdmin enableAccount 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/admin/accounts/123/enable",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`MastoAdmin fetchAccount 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/admin/accounts/123",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`MastoAdmin fetchAccounts 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/admin/accounts",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`MastoAdmin fetchReport 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/admin/reports/123",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`MastoAdmin fetchReports 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/admin/reports",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`MastoAdmin rejectAccount 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/admin/accounts/123/reject",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`MastoAdmin reopenReport 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/admin/reports/123/reopen",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`MastoAdmin resolveReport 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/admin/reports/123/resolve",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`MastoAdmin unassignReport 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/admin/reports/123/unassign",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`MastoAdmin unsilenceAccount 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/admin/accounts/123/unsilence",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`MastoAdmin unsuspendAccount 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/admin/accounts/123/unsuspend",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
diff --git a/src/clients/masto-admin/__tests__/masto-admin.spec.ts b/src/clients/masto-admin/__tests__/masto-admin.spec.ts
new file mode 100644
index 00000000..95ecc7b3
--- /dev/null
+++ b/src/clients/masto-admin/__tests__/masto-admin.spec.ts
@@ -0,0 +1,117 @@
+// @ts-ignore
+import axios from 'axios';
+import { MastoAdmin } from '../masto-admin';
+
+jest.mock('axios');
+
+describe('MastoAdmin', () => {
+  const masto = new MastoAdmin({
+    uri: 'https://example.com',
+    version: '99.99.9',
+    streamingApiUrl: 'wss://example.com/stream',
+  });
+
+  beforeAll(async () => {
+    (axios.request as jest.Mock).mockResolvedValue({
+      headers: {
+        link: '<https://example.com/next>; rel="next"',
+      },
+      data: {},
+    });
+  });
+
+  beforeEach(async () => {
+    masto.version = '99.99.9'; // avoid version error
+    (axios.request as jest.Mock).mockClear();
+  });
+
+  test('fetchAccounts', async () => {
+    await masto.fetchAccounts();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchAccount', async () => {
+    await masto.fetchAccount('123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('enableAccount', async () => {
+    await masto.enableAccount('123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('approveAccount', async () => {
+    await masto.approveAccount('123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('rejectAccount', async () => {
+    await masto.rejectAccount('123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('unsilenceAccount', async () => {
+    await masto.unsilenceAccount('123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('unsuspendAccount', async () => {
+    await masto.unsuspendAccount('123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchReports', async () => {
+    await masto.fetchReports();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchReport', async () => {
+    await masto.fetchReport('123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('assignReportToSelf', async () => {
+    await masto.assignReportToSelf('123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('unassignReport', async () => {
+    await masto.unassignReport('123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('reopenReport', async () => {
+    await masto.reopenReport('123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('resolveReport', async () => {
+    await masto.resolveReport('123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('actionAccount', async () => {
+    await masto.actionAccount('123', {
+      type: 'disable',
+      report_id: '123123',
+      warning_preset_id: '123123',
+      text: 'Your account have been disabled',
+      send_email_notification: false,
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+});
diff --git a/src/clients/masto/__tests__/__snapshots__/masto.spec.ts.snap b/src/clients/masto/__tests__/__snapshots__/masto.spec.ts.snap
new file mode 100644
index 00000000..c816c4db
--- /dev/null
+++ b/src/clients/masto/__tests__/__snapshots__/masto.spec.ts.snap
@@ -0,0 +1,2784 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Masto addAccountToList 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"account_ids\\":[\\"123\\",\\"456\\",\\"678\\"]}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/lists/123123/accounts",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto addPushSubscription 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"subscription\\":{\\"endpoint\\":\\"https://example.com\\",\\"keys\\":{\\"p256dh\\":\\"xxxx\\",\\"auth\\":\\"yyyy\\"}},\\"data\\":{\\"alerts\\":{\\"follow\\":true,\\"favourite\\":true,\\"reblog\\":true,\\"mention\\":true}}}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/push/subscription",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto authorizeFollowRequest 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/follow_requests/123123/authorize",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto blockAccount 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/accounts/123123/block",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto blockDomain 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"domain\\":\\"example.com\\"}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/domain_blocks",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto clearNotifications 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/notifications/clear",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto createAccount 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"username\\":\\"username\\",\\"password\\":\\"password\\",\\"email\\":\\"example@example.com\\",\\"agreement\\":true}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/accounts",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto createApp 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"client_name\\":\\"My Client\\",\\"redirect_uris\\":\\"https://example.com\\",\\"scopes\\":\\"write read\\",\\"website\\":\\"https://example.com\\"}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/apps",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto createFiler 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"phrase\\":\\"Twitter\\",\\"context\\":[\\"home\\",\\"notifications\\",\\"public\\",\\"thread\\"],\\"irreversible\\":true,\\"whole_word\\":true,\\"expires_in\\":3600000}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/filters",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto createList 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"title\\":\\"My list\\"}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/lists",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto createStatus with Idempotency-Key 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"status\\":\\"Too!\\"}",
+        "headers": Object {
+          "Content-Type": "application/json",
+          "Idempotency-Key": "59fe7e30-1a74-4050-8af7-5a8c7a224794",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/statuses",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto createStatus with content 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"status\\":\\"Toot!\\",\\"in_reply_to_id\\":\\"123123\\",\\"poll\\":{\\"options\\":[\\"xxx\\",\\"yyy\\",\\"zzz\\"],\\"expires_in\\":60000,\\"multiple\\":false,\\"hide_totals\\":true},\\"sensitive\\":false,\\"spoiler_text\\":\\"spoiler\\",\\"visibility\\":\\"direct\\",\\"scheduled_at\\":\\"2019-03-28T04:39:31.121Z\\",\\"language\\":\\"en\\"}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/statuses",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto createStatus with media ids 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"media_ids\\":[\\"123\\",\\"456\\"]}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/statuses",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto dissmissNotification 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"id\\":\\"123123\\"}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/notifications/dismiss",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto favouriteStatus 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/statuses/123123/favourite",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchAccessToken with authorization code 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"grant_type\\":\\"authorization_code\\",\\"code\\":\\"789789789\\",\\"redirect_uri\\":\\"https://example.com\\",\\"client_id\\":\\"123123123\\",\\"client_secret\\":\\"456456456\\"}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/oauth/token",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchAccessToken with password 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"grant_type\\":\\"password\\",\\"username\\":\\"username\\",\\"password\\":\\"password\\"}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/oauth/token",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchAccount 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/accounts/123123123",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchAccountFollowers 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "limit": 10,
+          "max_id": "5",
+          "min_id": "2",
+          "since_id": "3",
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/accounts/123123123/followers",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchAccountFollowing 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "limit": 10,
+          "max_id": "5",
+          "min_id": "2",
+          "since_id": "3",
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/accounts/123123123/following",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchAccountIdentityProofs 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/accounts/123123123/identity_proofs",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchAccountLists 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/accounts/123123/lists",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchAccountRelationships 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "id": Array [
+            "123123",
+            "456456",
+          ],
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/accounts/relationship",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchAccountStatuses 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "limit": 10,
+          "max_id": "5",
+          "min_id": "2",
+          "since_id": "3",
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/accounts/123123123/statuses",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchBlocks 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "limit": 10,
+          "max_id": "5",
+          "min_id": "2",
+          "since_id": "3",
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/blocks",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchCommunityTimeline 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "limit": 10,
+          "local": true,
+          "max_id": "5",
+          "min_id": "2",
+          "since_id": "3",
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/timelines/public",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchConversations 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "limit": 10,
+          "max_id": "5",
+          "min_id": "2",
+          "since_id": "3",
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/conversations",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchCustomEmojis 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/custom_emojis",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchDirectTimeline 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "limit": 10,
+          "max_id": "5",
+          "min_id": "2",
+          "since_id": "3",
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/timelines/direct",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchDomainBlocks 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": undefined,
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/domain_blocks",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchEndorsements 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "limit": 10,
+          "max_id": "5",
+          "min_id": "2",
+          "since_id": "3",
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/endorsements",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchFavourites 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "limit": 10,
+          "max_id": "5",
+          "min_id": "2",
+          "since_id": "3",
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/favourites",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchFilter 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/filters/123123",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchFilters 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/filters",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchFollowRequests 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "limit": 10,
+          "max_id": "5",
+          "min_id": "2",
+          "since_id": "3",
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/follow_requests",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchHomeTimeline 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "limit": 10,
+          "max_id": "5",
+          "min_id": "2",
+          "since_id": "3",
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/timelines/home",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchInstance 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/instance",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchInstanceActivity 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/instance/activity",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchInstancesPeers 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/instance/peers",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchList 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/lists/123123",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchListAccounts 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "limit": 10,
+          "max_id": "5",
+          "min_id": "2",
+          "since_id": "3",
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/list/123123/accounts",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchListTimeline 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "limit": 10,
+          "max_id": "5",
+          "min_id": "2",
+          "since_id": "3",
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/timelines/list/123123",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchLists 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/lists",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchMutes 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "limit": 10,
+          "max_id": "5",
+          "min_id": "2",
+          "since_id": "3",
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/mutes",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchNotification 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/notifications/123123",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchNotifications 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "exclude_types": Array [
+            "favourite",
+            "follow",
+            "mention",
+            "poll",
+            "reblog",
+          ],
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/notifications",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchPoll 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/polls/123123",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchPreferences 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/preferences",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchPublicTimeline 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "limit": 10,
+          "max_id": "5",
+          "min_id": "2",
+          "since_id": "3",
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/timelines/public",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchPushSubscription 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/push/subscription",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchScheduledStatus 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/scheduled_statuses/123123",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchScheduledStatuses 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/scheduled_statuses",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchStatus 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/statuses/123123",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchStatusCard 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/statuses/123123/card",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchStatusContext 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/statuses/123123/context",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchStatusFavouritedBy 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "limit": 10,
+          "max_id": "5",
+          "min_id": "2",
+          "since_id": "3",
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/statuses/123123/favourited_by",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchStatusRebloggedBy 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "limit": 10,
+          "max_id": "5",
+          "min_id": "2",
+          "since_id": "3",
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/statuses/123123/reblogged_by",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchSuggestions 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/suggestions",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto fetchTagTimeline 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "limit": 10,
+          "max_id": "5",
+          "min_id": "2",
+          "since_id": "3",
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/timelines/tag/DeleteTwitter",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto followAccount 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"reblogs\\":false}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/accounts/123123/follow",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto followAccountByUsername 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"uri\\":\\"user@example.com\\"}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/follows",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto muteAccount 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"notifications\\":false}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/accounts/123123/mute",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto muteStatus 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/statuses/123123/mute",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto pinAccount 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/accounts/123123/pin",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto pinStatus 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/statuses/123123/pin",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto reblogStatus 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"visibility\\":\\"direct\\"}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/statuses/123123/reblog",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto rejectFollowRequest 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/follow_requests/123123/reject",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto removeAccountFromList 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"account_ids\\":[\\"123\\",\\"456\\",\\"678\\"]}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "DELETE",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/lists/123123/accounts",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto removeFilter 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "DELETE",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/filters/123123",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto removeList 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "DELETE",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/lists/123123",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto removePushSubscription 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "DELETE",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/push/subscription",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto removeScheduledStatus 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "DELETE",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/scheduled_statuses/123123",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto removeStatus 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "DELETE",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/statuses/123123",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto removeSuggestion 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "DELETE",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/suggestions/123123",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto reportAccount 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"account_id\\":\\"123123\\",\\"status_ids\\":[\\"456456\\"],\\"comment\\":\\"this is a report\\",\\"forward\\":true}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/reports",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto revokeAccessToken 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"client_id\\":\\"123123123\\",\\"client_secret\\":\\"456456456\\"}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/oauth/revoke",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto search (v1) 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "q": "query",
+          "resolve": true,
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/search",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto search 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "account_id": "123",
+          "limit": 10,
+          "max_id": "5",
+          "min_id": "2",
+          "q": "query",
+          "resolve": true,
+          "since_id": "3",
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v2/search",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto searchAccounts 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {
+          "following": false,
+          "limit": 123,
+          "q": "query",
+          "resolve": true,
+        },
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/accounts/search",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto streamCommunityTimeline 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      "wss://example.com/stream/api/v1/streaming?stream=public%3Alocal",
+      Array [],
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": undefined,
+    },
+  ],
+}
+`;
+
+exports[`Masto streamDirectTimeline 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      "wss://example.com/stream/api/v1/streaming?stream=direct",
+      Array [],
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": undefined,
+    },
+  ],
+}
+`;
+
+exports[`Masto streamListTimeline 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      "wss://example.com/stream/api/v1/streaming?stream=list&list=123123",
+      Array [],
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": undefined,
+    },
+  ],
+}
+`;
+
+exports[`Masto streamLocalTagTimeline 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      "wss://example.com/stream/api/v1/streaming?stream=hashtag%3Alocal&tag=deletetwitter",
+      Array [],
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": undefined,
+    },
+  ],
+}
+`;
+
+exports[`Masto streamPublicTimeline 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      "wss://example.com/stream/api/v1/streaming?stream=public",
+      Array [],
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": undefined,
+    },
+  ],
+}
+`;
+
+exports[`Masto streamTagTimeline 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      "wss://example.com/stream/api/v1/streaming?stream=hashtag&tag=deletetwitter",
+      Array [],
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": undefined,
+    },
+  ],
+}
+`;
+
+exports[`Masto streamUser 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      "wss://example.com/stream/api/v1/streaming?stream=user",
+      Array [],
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": undefined,
+    },
+  ],
+}
+`;
+
+exports[`Masto unblockAccount 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/accounts/123123/unblock",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto unblockDomain 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"domain\\":\\"example.com\\"}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "DELETE",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/domain_blocks",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto unfavouriteStatus 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/statuses/123123/unfavourite",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto unfollowAccount 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/accounts/123123/unfollow",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto unmuteAccount 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/accounts/123123/unmute",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto unmuteStatus 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/statuses/123123/unmute",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto unpinAccount 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/accounts/123123/unpin",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto unpinStatus 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/statuses/123123/unpin",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto unreblogStatus 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/statuses/123123/unreblog",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto updateFilter 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"phrase\\":\\"Twitter\\",\\"context\\":[\\"home\\",\\"notifications\\",\\"public\\",\\"thread\\"],\\"irreversible\\":true,\\"whole_word\\":true,\\"expires_in\\":3600000}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "PUT",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/filters/123123",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto updateList 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"title\\":\\"My list\\"}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "PUT",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/lists/123123",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto updateMediaAttachment 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"description\\":\\"Nice image\\",\\"focus\\":\\"0, 0\\"}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "PUT",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/media/123123",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto updatePushSubscription 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"data\\":{\\"alerts\\":{\\"follow\\":true,\\"favourite\\":true,\\"reblog\\":true,\\"mention\\":true}}}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "PUT",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/push/subscription",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto updateScheduledStatus 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"scheduled_at\\":\\"2019-03-28T04:39:31.121Z\\"}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "PUT",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/scheduled_statuses/123123",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto verifyAppCredentials 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/apps/verify_credentials",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto verifyCredentials 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": undefined,
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "GET",
+        "params": Object {},
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/accounts/verify_credentials",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
+
+exports[`Masto votePoll 1`] = `
+[MockFunction] {
+  "calls": Array [
+    Array [
+      Object {
+        "data": "{\\"choices\\":[\\"xxx\\",\\"yyy\\",\\"zzz\\"]}",
+        "headers": Object {
+          "Content-Type": "application/json",
+        },
+        "method": "POST",
+        "transformResponse": Array [
+          [Function],
+        ],
+        "url": "https://example.com/api/v1/polls/123123/votes",
+      },
+    ],
+  ],
+  "results": Array [
+    Object {
+      "type": "return",
+      "value": Promise {},
+    },
+  ],
+}
+`;
diff --git a/src/clients/masto/__tests__/masto.spec.ts b/src/clients/masto/__tests__/masto.spec.ts
new file mode 100644
index 00000000..09f88ac1
--- /dev/null
+++ b/src/clients/masto/__tests__/masto.spec.ts
@@ -0,0 +1,925 @@
+// tslint:disable
+// @ts-ignore
+// prettier-ignore
+import axios from 'axios';
+import { Masto } from '../masto';
+// @ts-ignore
+import { WebSocketEvents, connectMock } from '../../../gateway/websocket';
+
+jest.mock('axios');
+jest.mock('../../../gateway/websocket');
+
+describe('Masto', () => {
+  const masto = new Masto({
+    uri: 'https://example.com',
+    version: '99.99.9',
+    streamingApiUrl: 'wss://example.com/stream',
+  });
+
+  beforeAll(async () => {
+    (axios.request as jest.Mock).mockResolvedValue({
+      headers: {
+        link: '<https://example.com/next>; rel="next"',
+      },
+      data: {},
+    });
+  });
+
+  beforeEach(async () => {
+    masto.version = '99.99.9'; // avoid version error
+    (connectMock as jest.Mock).mockClear();
+    (axios.request as jest.Mock).mockClear();
+  });
+
+  test('streamUser', async () => {
+    await masto.streamUser();
+    expect(connectMock).toBeCalledTimes(1);
+    expect(connectMock).toMatchSnapshot();
+  });
+
+  test('streamPublicTimeline', async () => {
+    await masto.streamPublicTimeline();
+    expect(connectMock).toBeCalledTimes(1);
+    expect(connectMock).toMatchSnapshot();
+  });
+
+  test('streamCommunityTimeline', async () => {
+    await masto.streamCommunityTimeline();
+    expect(connectMock).toBeCalledTimes(1);
+    expect(connectMock).toMatchSnapshot();
+  });
+
+  test('streamTagTimeline', async () => {
+    await masto.streamTagTimeline('deletetwitter');
+    expect(connectMock).toBeCalledTimes(1);
+    expect(connectMock).toMatchSnapshot();
+  });
+
+  test('streamLocalTagTimeline', async () => {
+    await masto.streamLocalTagTimeline('deletetwitter');
+    expect(connectMock).toBeCalledTimes(1);
+    expect(connectMock).toMatchSnapshot();
+  });
+
+  test('streamListTimeline', async () => {
+    await masto.streamListTimeline('123123');
+    expect(connectMock).toBeCalledTimes(1);
+    expect(connectMock).toMatchSnapshot();
+  });
+
+  test('streamDirectTimeline', async () => {
+    await masto.streamDirectTimeline();
+    expect(connectMock).toBeCalledTimes(1);
+    expect(connectMock).toMatchSnapshot();
+  });
+
+  test('fetchAccessToken with authorization code', async () => {
+    await masto.fetchAccessToken({
+      grant_type: 'authorization_code',
+      code: '789789789',
+      redirect_uri: 'https://example.com',
+      client_id: '123123123',
+      client_secret: '456456456',
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchAccessToken with password', async () => {
+    await masto.fetchAccessToken({
+      grant_type: 'password',
+      username: 'username',
+      password: 'password',
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('revokeAccessToken', async () => {
+    await masto.revokeAccessToken({
+      client_id: '123123123',
+      client_secret: '456456456',
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchAccount', async () => {
+    await masto.fetchAccount('123123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchAccountIdentityProofs', async () => {
+    await masto.fetchAccountIdentityProofs('123123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('createAccount', async () => {
+    await masto.createAccount({
+      username: 'username',
+      password: 'password',
+      email: 'example@example.com',
+      agreement: true,
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('verifyCredentials', async () => {
+    await masto.verifyCredentials();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('updateCredentials', async () => {
+    await masto.updateCredentials({
+      display_name: 'Neetshin',
+      avatar: '...',
+      header: '...',
+      note: 'web frontend engineer',
+      locked: false,
+      // source: {
+      //   privacy: 'direct',
+      //   sensitive: false,
+      //   language: 'ja',
+      // },
+      // fields_attributes: [
+      //   {
+      //     name: 'GitHub',
+      //     value: 'https://github.com/neet',
+      //   },
+      // ],
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toBeCalledWith(
+      expect.objectContaining({
+        data: expect.any(FormData),
+      }),
+    );
+  });
+
+  test('fetchAccountFollowers', async () => {
+    const iterable = masto.fetchAccountFollowers('123123123', {
+      max_id: '5',
+      since_id: '3',
+      min_id: '2',
+      limit: 10,
+    });
+    await iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchAccountFollowing', async () => {
+    const iterable = masto.fetchAccountFollowing('123123123', {
+      max_id: '5',
+      since_id: '3',
+      min_id: '2',
+      limit: 10,
+    });
+    await iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchAccountStatuses', async () => {
+    const iterable = masto.fetchAccountStatuses('123123123', {
+      max_id: '5',
+      since_id: '3',
+      min_id: '2',
+      limit: 10,
+    });
+    await iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('followAccount', async () => {
+    await masto.followAccount('123123', {
+      reblogs: false,
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('unfollowAccount', async () => {
+    await masto.unfollowAccount('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchAccountRelationships', async () => {
+    await masto.fetchAccountRelationships(['123123', '456456']);
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('searchAccounts', async () => {
+    await masto.searchAccounts({
+      q: 'query',
+      resolve: true,
+      limit: 123,
+      following: false,
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('createApp', async () => {
+    await masto.createApp({
+      client_name: 'My Client',
+      redirect_uris: 'https://example.com',
+      scopes: 'write read',
+      website: 'https://example.com',
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('verifyAppCredentials', async () => {
+    await masto.verifyAppCredentials();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchBlocks', async () => {
+    const iterable = masto.fetchBlocks({
+      max_id: '5',
+      since_id: '3',
+      min_id: '2',
+      limit: 10,
+    });
+    await iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('blockAccount', async () => {
+    await masto.blockAccount('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('unblockAccount', async () => {
+    await masto.unblockAccount('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchCustomEmojis', async () => {
+    await masto.fetchCustomEmojis();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchDomainBlocks', async () => {
+    const iterable = masto.fetchDomainBlocks();
+    await iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('blockDomain', async () => {
+    await masto.blockDomain('example.com');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('unblockDomain', async () => {
+    await masto.unblockDomain('example.com');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchEndorsements', async () => {
+    const iterable = masto.fetchEndorsements({
+      max_id: '5',
+      since_id: '3',
+      min_id: '2',
+      limit: 10,
+    });
+    await iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('pinAccount', async () => {
+    await masto.pinAccount('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('unpinAccount', async () => {
+    await masto.unpinAccount('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchFavourites', async () => {
+    const iterable = masto.fetchFavourites({
+      max_id: '5',
+      since_id: '3',
+      min_id: '2',
+      limit: 10,
+    });
+    await iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('favouriteStatus', async () => {
+    await masto.favouriteStatus('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('unfavouriteStatus', async () => {
+    await masto.unfavouriteStatus('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchFilters', async () => {
+    await masto.fetchFilters();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchFilter', async () => {
+    await masto.fetchFilter('123123');
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('createFiler', async () => {
+    await masto.createFiler({
+      phrase: 'Twitter',
+      context: ['home', 'notifications', 'public', 'thread'],
+      irreversible: true,
+      whole_word: true,
+      expires_in: 1000 * 60 * 60,
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('updateFilter', async () => {
+    await masto.updateFilter('123123', {
+      phrase: 'Twitter',
+      context: ['home', 'notifications', 'public', 'thread'],
+      irreversible: true,
+      whole_word: true,
+      expires_in: 1000 * 60 * 60,
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('removeFilter', async () => {
+    await masto.removeFilter('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchFollowRequests', async () => {
+    const iterable = masto.fetchFollowRequests({
+      max_id: '5',
+      since_id: '3',
+      min_id: '2',
+      limit: 10,
+    });
+    await iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('authorizeFollowRequest', async () => {
+    await masto.authorizeFollowRequest('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('rejectFollowRequest', async () => {
+    await masto.rejectFollowRequest('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchSuggestions', async () => {
+    await masto.fetchSuggestions();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('removeSuggestion', async () => {
+    await masto.removeSuggestion('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchInstance', async () => {
+    await masto.fetchInstance();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchInstancesPeers', async () => {
+    await masto.fetchInstancesPeers();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchInstanceActivity', async () => {
+    await masto.fetchInstanceActivity();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchLists', async () => {
+    await masto.fetchLists();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchAccountLists', async () => {
+    await masto.fetchAccountLists('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchListAccounts', async () => {
+    const iterable = masto.fetchListAccounts('123123', {
+      max_id: '5',
+      since_id: '3',
+      min_id: '2',
+      limit: 10,
+    });
+    await iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchList', async () => {
+    await masto.fetchList('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('createList', async () => {
+    await masto.createList({
+      title: 'My list',
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('updateList', async () => {
+    await masto.updateList('123123', {
+      title: 'My list',
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('removeList', async () => {
+    await masto.removeList('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('addAccountToList', async () => {
+    await masto.addAccountToList('123123', {
+      account_ids: ['123', '456', '678'],
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('removeAccountFromList', async () => {
+    await masto.removeAccountFromList('123123', {
+      account_ids: ['123', '456', '678'],
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('uploadMediaAttachment', async () => {
+    await masto.uploadMediaAttachment({
+      file: '...',
+      description: 'Nice image',
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toBeCalledWith(
+      expect.objectContaining({
+        data: expect.any(FormData),
+      }),
+    );
+  });
+
+  test('updateMediaAttachment', async () => {
+    await masto.updateMediaAttachment('123123', {
+      description: 'Nice image',
+      focus: '0, 0',
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchMutes', async () => {
+    const iterable = masto.fetchMutes({
+      max_id: '5',
+      since_id: '3',
+      min_id: '2',
+      limit: 10,
+    });
+    await iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('muteAccount', async () => {
+    await masto.muteAccount('123123', {
+      notifications: false,
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('unmuteAccount', async () => {
+    await masto.unmuteAccount('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('muteStatus', async () => {
+    await masto.muteStatus('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('unmuteStatus', async () => {
+    await masto.unmuteStatus('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchNotifications', async () => {
+    await masto.fetchNotifications({
+      exclude_types: ['favourite', 'follow', 'mention', 'poll', 'reblog'],
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchNotification', async () => {
+    await masto.fetchNotification('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('clearNotifications', async () => {
+    await masto.clearNotifications();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('dissmissNotification', async () => {
+    await masto.dissmissNotification('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('addPushSubscription', async () => {
+    await masto.addPushSubscription({
+      subscription: {
+        endpoint: 'https://example.com',
+        keys: { p256dh: 'xxxx', auth: 'yyyy' },
+      },
+      data: {
+        alerts: {
+          follow: true,
+          favourite: true,
+          reblog: true,
+          mention: true,
+        },
+      },
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchPushSubscription', async () => {
+    await masto.fetchPushSubscription();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('updatePushSubscription', async () => {
+    await masto.updatePushSubscription({
+      data: {
+        alerts: {
+          follow: true,
+          favourite: true,
+          reblog: true,
+          mention: true,
+        },
+      },
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('removePushSubscription', async () => {
+    await masto.removePushSubscription();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchPoll', async () => {
+    await masto.fetchPoll('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('votePoll', async () => {
+    await masto.votePoll('123123', {
+      choices: ['xxx', 'yyy', 'zzz'],
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('reportAccount', async () => {
+    await masto.reportAccount({
+      account_id: '123123',
+      status_ids: ['456456'],
+      comment: 'this is a report',
+      forward: true,
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchScheduledStatuses', async () => {
+    await masto.fetchScheduledStatuses();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchScheduledStatus', async () => {
+    await masto.fetchScheduledStatus('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('updateScheduledStatus', async () => {
+    await masto.updateScheduledStatus('123123', {
+      scheduled_at: '2019-03-28T04:39:31.121Z',
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('removeScheduledStatus', async () => {
+    await masto.removeScheduledStatus('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('search (v1)', async () => {
+    const iterable = masto.search(
+      {
+        q: 'query',
+        resolve: true,
+      },
+      'v1',
+    );
+    iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('search', async () => {
+    const iterable = masto.search({
+      q: 'query',
+      resolve: true,
+      max_id: '5',
+      since_id: '3',
+      min_id: '2',
+      limit: 10,
+      account_id: '123',
+    });
+    await iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchStatus', async () => {
+    await masto.fetchStatus('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchStatusContext', async () => {
+    await masto.fetchStatusContext('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchStatusCard', async () => {
+    await masto.fetchStatusCard('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchStatusRebloggedBy', async () => {
+    const iterable = masto.fetchStatusRebloggedBy('123123', {
+      max_id: '5',
+      since_id: '3',
+      min_id: '2',
+      limit: 10,
+    });
+    await iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchStatusFavouritedBy', async () => {
+    const iterable = masto.fetchStatusFavouritedBy('123123', {
+      max_id: '5',
+      since_id: '3',
+      min_id: '2',
+      limit: 10,
+    });
+    iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('createStatus with content', async () => {
+    await masto.createStatus({
+      status: 'Toot!',
+      in_reply_to_id: '123123',
+      poll: {
+        options: ['xxx', 'yyy', 'zzz'],
+        expires_in: 1000 * 60,
+        multiple: false,
+        hide_totals: true,
+      },
+      sensitive: false,
+      spoiler_text: 'spoiler',
+      visibility: 'direct',
+      scheduled_at: '2019-03-28T04:39:31.121Z',
+      language: 'en',
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('createStatus with media ids', async () => {
+    await masto.createStatus({
+      media_ids: ['123', '456'],
+    });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('createStatus with Idempotency-Key', async () => {
+    await masto.createStatus(
+      {
+        status: 'Too!',
+      },
+      '59fe7e30-1a74-4050-8af7-5a8c7a224794',
+    );
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('removeStatus', async () => {
+    await masto.removeStatus('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('reblogStatus', async () => {
+    await masto.reblogStatus('123123', { visibility: 'direct' });
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('unreblogStatus', async () => {
+    await masto.unreblogStatus('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('pinStatus', async () => {
+    await masto.pinStatus('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('unpinStatus', async () => {
+    await masto.unpinStatus('123123');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchHomeTimeline', async () => {
+    const iterable = masto.fetchHomeTimeline({
+      max_id: '5',
+      since_id: '3',
+      min_id: '2',
+      limit: 10,
+    });
+    await iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchCommunityTimeline', async () => {
+    const iterable = await masto.fetchCommunityTimeline({
+      max_id: '5',
+      since_id: '3',
+      min_id: '2',
+      limit: 10,
+    });
+    await iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchPublicTimeline', async () => {
+    const iterable = await masto.fetchPublicTimeline({
+      max_id: '5',
+      since_id: '3',
+      min_id: '2',
+      limit: 10,
+    });
+    await iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchTagTimeline', async () => {
+    const iterable = masto.fetchTagTimeline('DeleteTwitter', {
+      max_id: '5',
+      since_id: '3',
+      min_id: '2',
+      limit: 10,
+    });
+    await iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchListTimeline', async () => {
+    const iterable = masto.fetchListTimeline('123123', {
+      max_id: '5',
+      since_id: '3',
+      min_id: '2',
+      limit: 10,
+    });
+    iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchDirectTimeline', async () => {
+    masto.version = '2.5.0';
+    const iterable = masto.fetchDirectTimeline({
+      max_id: '5',
+      since_id: '3',
+      min_id: '2',
+      limit: 10,
+    });
+    iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchConversations', async () => {
+    const iterable = masto.fetchConversations({
+      max_id: '5',
+      since_id: '3',
+      min_id: '2',
+      limit: 10,
+    });
+    await iterable.next();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('followAccountByUsername', async () => {
+    await masto.followAccountByUsername('user@example.com');
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+
+  test('fetchPreferences', async () => {
+    await masto.fetchPreferences();
+    expect(axios.request as jest.Mock).toBeCalledTimes(1);
+    expect(axios.request as jest.Mock).toMatchSnapshot();
+  });
+});
diff --git a/src/client/__tests__/gateway.spec.ts b/src/gateway/__tests__/gateway.spec.ts
similarity index 89%
rename from src/client/__tests__/gateway.spec.ts
rename to src/gateway/__tests__/gateway.spec.ts
index e64a7241..9f7a3e2b 100644
--- a/src/client/__tests__/gateway.spec.ts
+++ b/src/gateway/__tests__/gateway.spec.ts
@@ -1,21 +1,23 @@
 // tslint:disable
 import axios from 'axios';
-import FormData from 'form-data';
-import { Gateway } from '../gateway';
 // @ts-ignore
-import { MastoEvents, connectMock } from '../masto-events';
+import { Gateway, getMock } from '../gateway';
+// @ts-ignore
+import { WebSocketEvents, connectMock } from '../websocket';
 import { MastoUnauthorizedError } from '../../errors/masto-unauthorized-error';
 import { MastoNotFoundError } from '../../errors/masto-not-found-error';
 import { MastoRateLimitError } from '../../errors/masto-rate-limit-error';
 
 jest.mock('axios');
-jest.mock('../masto-events');
+jest.mock('../websocket');
 
 describe('Gateway', () => {
-  let gateway!: Gateway;
+  class InheritedGateway extends Gateway {}
+
+  let gateway!: InheritedGateway;
 
   beforeEach(() => {
-    gateway = new Gateway({
+    gateway = new InheritedGateway({
       uri: 'https://example.com',
       version: '99.9.9',
       streamingApiUrl: 'wss://example.com',
@@ -27,8 +29,28 @@ describe('Gateway', () => {
     });
   });
 
+  test('login', async () => {
+    (axios.request as jest.Mock).mockResolvedValueOnce({
+      data: {
+        version: '2.8.0',
+        urls: {
+          streaming_api: 'wss://example.com/stream',
+        },
+      },
+    });
+
+    const params = {
+      uri: 'https://example.com',
+      accessToken: 'tokentoken',
+    };
+    const gateway = await InheritedGateway.login(params);
+
+    expect(gateway.version).toBe('2.8.0');
+    expect(gateway.streamingApiUrl).toBe('wss://example.com/stream');
+  });
+
   test('streamingApiUrl has been set if construct with streamingApiUrl', () => {
-    gateway = new Gateway({
+    gateway = new InheritedGateway({
       uri: 'https://example.com',
       streamingApiUrl: 'wss://example.com',
     });
@@ -36,7 +58,7 @@ describe('Gateway', () => {
   });
 
   test('version has been set if construct with version ', () => {
-    gateway = new Gateway({
+    gateway = new InheritedGateway({
       uri: 'https://example.com',
       version: '1.2.3',
     });
@@ -44,7 +66,7 @@ describe('Gateway', () => {
   });
 
   test('accessToken has been set if construct with accessToken', () => {
-    gateway = new Gateway({
+    gateway = new InheritedGateway({
       uri: 'https://example.com',
       accessToken: 'token token',
     });
@@ -52,7 +74,7 @@ describe('Gateway', () => {
   });
 
   test('this._uri accessor works', () => {
-    gateway = new Gateway({
+    gateway = new InheritedGateway({
       uri: 'https://example.com/aaa',
     });
     gateway.uri = 'https://example.com/bbb';
@@ -60,7 +82,7 @@ describe('Gateway', () => {
   });
 
   test('this._streamingApiUrl accessor works', () => {
-    gateway = new Gateway({
+    gateway = new InheritedGateway({
       uri: 'wss://example.com/aaa',
     });
     gateway.uri = 'wss://example.com/bbb';
@@ -298,19 +320,19 @@ describe('Gateway', () => {
     );
   });
 
-  test('initialize MastoEvents and call connect with given params', async () => {
+  test('initialize WebSocketEvents and call connect with given params', async () => {
     const params = { a: 'a', b: 'b' };
     await gateway.stream('/', params);
     expect(connectMock).toBeCalledWith('wss://example.com/?a=a&b=b', []);
   });
 
-  test('initialize MastoEvents and call connect with access token', async () => {
+  test('initialize WebSocketEvents and call connect with access token', async () => {
     gateway.accessToken = 'tokentoken';
     await gateway.stream('/');
     expect(connectMock).toBeCalledWith('wss://example.com/', ['tokentoken']);
   });
 
-  test('initialize MastoEvents and call connect with access token as a param for Mastodon < v2.8.4', async () => {
+  test('initialize WebSocketEvents and call connect with access token as a param for Mastodon < v2.8.4', async () => {
     gateway.version = '2.8.3';
     gateway.accessToken = 'tokentoken';
     await gateway.stream('/');
diff --git a/src/client/__tests__/utils.spec.ts b/src/gateway/__tests__/utils.spec.ts
similarity index 100%
rename from src/client/__tests__/utils.spec.ts
rename to src/gateway/__tests__/utils.spec.ts
diff --git a/src/client/__tests__/masto-events.spec.ts b/src/gateway/__tests__/websocket.spec.ts
similarity index 64%
rename from src/client/__tests__/masto-events.spec.ts
rename to src/gateway/__tests__/websocket.spec.ts
index 9f2ee56f..64e74d76 100644
--- a/src/client/__tests__/masto-events.spec.ts
+++ b/src/gateway/__tests__/websocket.spec.ts
@@ -1,11 +1,11 @@
 // tslint:disable
 import WebSocket from 'isomorphic-ws';
-import { MastoEvents } from '../masto-events';
+import { WebSocketEvents } from '../websocket';
 
 const onMock = jest.fn();
+const onMockWs = jest.fn();
 const emitMock = jest.fn();
 const closeMock = jest.fn();
-const addEventListenerMock = jest.fn();
 
 jest.mock('eventemitter3', () => {
   return class {
@@ -17,20 +17,27 @@ jest.mock('eventemitter3', () => {
 jest.mock('isomorphic-ws', () => {
   return jest.fn(() => ({
     close: closeMock,
-    addEventListener: addEventListenerMock,
+    on: onMockWs,
   }));
 });
 
-describe('MastoEvents', () => {
-  let mastoEvents!: MastoEvents;
+describe('WebSocketEvents', () => {
+  let mastoEvents!: WebSocketEvents;
 
   beforeAll(() => {
-    mastoEvents = new MastoEvents();
+    mastoEvents = new WebSocketEvents();
+  });
+
+  beforeEach(() => {
+    onMock.mockClear();
+    onMockWs.mockClear();
+    emitMock.mockClear();
+    closeMock.mockClear();
   });
 
   test('connect to ws server', async () => {
     // Resolve open
-    addEventListenerMock.mockImplementation((e, fn) => {
+    onMockWs.mockImplementation((e, fn) => {
       if (e === 'open') {
         fn();
       }
@@ -43,20 +50,9 @@ describe('MastoEvents', () => {
       [],
     );
 
-    expect(addEventListenerMock).toHaveBeenCalledWith(
-      'message',
-      expect.any(Function),
-    );
-
-    expect(addEventListenerMock).toHaveBeenCalledWith(
-      'error',
-      expect.any(Function),
-    );
-
-    expect(addEventListenerMock).toHaveBeenCalledWith(
-      'open',
-      expect.any(Function),
-    );
+    expect(onMockWs).toBeCalledWith('message', expect.any(Function));
+    expect(onMockWs).toBeCalledWith('error', expect.any(Function));
+    expect(onMockWs).toBeCalledWith('open', expect.any(Function));
   });
 
   test('disconnect from the server', async () => {
@@ -68,35 +64,23 @@ describe('MastoEvents', () => {
     const originalPayload = {
       aaaa: 'foobar',
     };
-
     const originalData = {
       event: 'update',
       payload: JSON.stringify(originalPayload),
     };
 
-    mastoEvents.handleMessage({
-      type: 'utf8',
-      data: JSON.stringify(originalData),
-      target: {} as any,
-    });
-
+    mastoEvents.handleMessage(JSON.stringify(originalData));
     expect(emitMock).toBeCalledWith('update', originalPayload);
   });
 
   test('emit event with given props, with raw payload', () => {
     const originalPayload = 'foobar';
-
     const originalData = {
       event: 'update',
       payload: originalPayload,
     };
 
-    mastoEvents.handleMessage({
-      type: 'utf8',
-      data: JSON.stringify(originalData),
-      target: {} as any,
-    });
-
+    mastoEvents.handleMessage(JSON.stringify(originalData));
     expect(emitMock).toBeCalledWith('update', originalPayload);
   });