From b1a261f786665534e57e6bd0d27183e4df079a85 Mon Sep 17 00:00:00 2001 From: Koki Takahashi Date: Tue, 1 Aug 2023 17:40:13 +0000 Subject: [PATCH] lib: [WIP] Convert slackMock.js to TypeScript --- achievement-quiz/index.test.ts | 5 +- achievements/index_production.test.ts | 3 +- ahokusa/index.test.js | 2 +- atequiz/index.ts | 4 +- channel-notifier/index.test.js | 2 +- checkin/index.test.js | 2 +- dajare/index.test.js | 2 +- discord/hayaoshiUtils.test.ts | 5 ++ emoji-notifier/index.test.js | 2 +- hitandblow/index.test.ts | 3 +- lib/slack.ts | 4 +- lib/slackCache.test.ts | 1 - lib/slackCache.ts | 5 +- lib/slackEventClient.ts | 17 ++--- lib/{slackMock.js => slackMock.ts} | 90 ++++++++++++++++++--------- lib/slackUtils.ts | 2 +- lyrics/index.test.ts | 3 +- mahjong/index.test.js | 2 +- octas/index.test.ts | 6 +- pocky/index.test.js | 2 +- ponpe/index.test.ts | 3 +- prime/index.test.js | 2 +- pwnyaa/index.test.ts | 31 +++++---- remember-english/index.test.ts | 5 +- ricochet-robots/index.test.js | 2 +- room-gacha/index.test.ts | 11 +++- scrapbox/index.test.ts | 3 +- shogi/index.test.js | 2 +- slack-log/index.test.ts | 11 ++-- sunrise/index.test.ts | 3 +- sushi-bot/index.test.js | 2 +- tahoiya/index.test.js | 2 +- tiobot/index.test.ts | 5 +- vocabwar/index.test.js | 2 +- voiperrobot/index.test.ts | 3 +- wadokaichin/index.test.ts | 3 +- welcome/index.test.ts | 1 - wordle-battle/index.test.ts | 11 ++-- 38 files changed, 144 insertions(+), 120 deletions(-) rename lib/{slackMock.js => slackMock.ts} (50%) diff --git a/achievement-quiz/index.test.ts b/achievement-quiz/index.test.ts index 9fdc93d6..494939bb 100644 --- a/achievement-quiz/index.test.ts +++ b/achievement-quiz/index.test.ts @@ -1,8 +1,7 @@ import achievementQuiz from './index'; +import Slack from '../lib/slackMock'; -const Slack = require('../lib/slackMock.js'); - -let slack: typeof Slack; +let slack: Slack; beforeEach(() => { slack = new Slack(); diff --git a/achievements/index_production.test.ts b/achievements/index_production.test.ts index c632bb53..4c35058a 100644 --- a/achievements/index_production.test.ts +++ b/achievements/index_production.test.ts @@ -2,8 +2,7 @@ import noop from 'lodash/noop'; // @ts-expect-error import MockFirebase from 'mock-cloud-firestore'; -// @ts-expect-error -import Slack from '../lib/slackMock.js'; +import Slack from '../lib/slackMock'; import achievements from './index_production'; diff --git a/ahokusa/index.test.js b/ahokusa/index.test.js index 2f777934..ec007fc0 100644 --- a/ahokusa/index.test.js +++ b/ahokusa/index.test.js @@ -3,7 +3,7 @@ jest.mock('../achievements'); const ahokusa = require('./index.js'); -const Slack = require('../lib/slackMock.js'); +const {default: Slack} = require('../lib/slackMock.ts'); let slack = null; diff --git a/atequiz/index.ts b/atequiz/index.ts index 2ba83d55..55375f9f 100644 --- a/atequiz/index.ts +++ b/atequiz/index.ts @@ -1,5 +1,5 @@ import { WebAPICallOptions, WebClient } from '@slack/web-api'; -import type { TeamEventClient } from '../lib/slackEventClient'; +import type { TeamEventClientInterface } from '../lib/slackEventClient'; import { SlackInterface } from '../lib/slack'; import { ChatPostMessageArguments } from '@slack/web-api/dist/methods'; import assert from 'assert'; @@ -52,7 +52,7 @@ export const typicalMessageTextsGenerator = { * To use other judge/watSecGen/ngReaction, please extend this class. */ export class AteQuiz { - eventClient: TeamEventClient; + eventClient: TeamEventClientInterface; slack: WebClient; problem: AteQuizProblem; ngReaction: string | null = 'no_good'; diff --git a/channel-notifier/index.test.js b/channel-notifier/index.test.js index 09b52bc7..9d82e9c0 100644 --- a/channel-notifier/index.test.js +++ b/channel-notifier/index.test.js @@ -2,7 +2,7 @@ jest.mock('axios'); -const Slack = require('../lib/slackMock.js'); +const {default: Slack} = require('../lib/slackMock.ts'); const channelNotifier = require('./index.js'); let slack = null; diff --git a/checkin/index.test.js b/checkin/index.test.js index f5c7d152..4cc397c6 100644 --- a/checkin/index.test.js +++ b/checkin/index.test.js @@ -3,7 +3,7 @@ jest.mock('axios'); const axios = require('axios'); -const Slack = require('../lib/slackMock.js'); +const {default: Slack} = require('../lib/slackMock.ts'); const checkin = require('./index.js'); let slack = null; diff --git a/dajare/index.test.js b/dajare/index.test.js index fced3c2b..7ace9b33 100644 --- a/dajare/index.test.js +++ b/dajare/index.test.js @@ -5,7 +5,7 @@ jest.mock('./tokenize.js'); jest.mock('../achievements'); const dajare = require('./index.js'); -const Slack = require('../lib/slackMock.js'); +const {default: Slack} = require('../lib/slackMock.ts'); const tokenize = require('./tokenize.js'); tokenize.virtualTokens = { diff --git a/discord/hayaoshiUtils.test.ts b/discord/hayaoshiUtils.test.ts index 75f3c4f9..9479138c 100644 --- a/discord/hayaoshiUtils.test.ts +++ b/discord/hayaoshiUtils.test.ts @@ -3,6 +3,11 @@ import {inspect} from 'util'; import {extractValidAnswers} from './hayaoshiUtils'; +jest.mock('../hayaoshi', () => ({ + isCorrectAnswer: jest.fn(), + normalize: jest.fn(), +})); + const testCases: [string, string, string[]][] = [ ['', 'リトグラフ[lithograph]【「石版画」「石版印刷」「リトグラフィー[lithographie]」も○】', ['リトグラフ', 'lithograph', '石版画', '石版印刷', 'リトグラフィー', 'lithographie'], diff --git a/emoji-notifier/index.test.js b/emoji-notifier/index.test.js index 4538c147..4155936d 100644 --- a/emoji-notifier/index.test.js +++ b/emoji-notifier/index.test.js @@ -1,6 +1,6 @@ /* eslint-env node, jest */ -const Slack = require('../lib/slackMock.js'); +const {default: Slack} = require('../lib/slackMock.ts'); const emojiNotifier = require('./index.js'); let slack = null; diff --git a/hitandblow/index.test.ts b/hitandblow/index.test.ts index f0597926..a0d8d11f 100644 --- a/hitandblow/index.test.ts +++ b/hitandblow/index.test.ts @@ -1,7 +1,6 @@ import { stripIndent } from 'common-tags'; import hitandblow from './'; - -const Slack = require('../lib/slackMock.js'); +import Slack from '../lib/slackMock'; let slack: typeof Slack; diff --git a/lib/slack.ts b/lib/slack.ts index 7a0de2b7..fae708a5 100644 --- a/lib/slack.ts +++ b/lib/slack.ts @@ -5,13 +5,13 @@ import sql from 'sql-template-strings'; import * as sqlite from 'sqlite'; import sqlite3 from 'sqlite3'; import path from 'path'; -import {TeamEventClient} from './slackEventClient'; +import {TeamEventClient, TeamEventClientInterface} from './slackEventClient'; import {Deferred} from './utils'; import {Token} from '../oauth/tokens'; export interface SlackInterface { webClient: WebClient; - eventClient: TeamEventClient; + eventClient: TeamEventClientInterface; messageClient: ReturnType; }; diff --git a/lib/slackCache.test.ts b/lib/slackCache.test.ts index 115a501c..9d35019c 100644 --- a/lib/slackCache.test.ts +++ b/lib/slackCache.test.ts @@ -8,7 +8,6 @@ import type { EmojiListArguments, EmojiListResponse, } from '@slack/web-api'; -// @ts-expect-error import Slack from './slackMock'; import SlackCache from './slackCache'; diff --git a/lib/slackCache.ts b/lib/slackCache.ts index ff741a27..362f40cc 100644 --- a/lib/slackCache.ts +++ b/lib/slackCache.ts @@ -1,10 +1,9 @@ import {get} from 'lodash'; import type {Token} from '../oauth/tokens'; import {Deferred} from './utils'; -import {TeamEventClient} from './slackEventClient'; +import {TeamEventClient, TeamEventClientInterface} from './slackEventClient'; import logger from './logger'; -import type {SlackEventAdapter} from '@slack/events-api'; import type {Reaction} from '@slack/web-api/dist/response/ConversationsHistoryResponse'; import type {Member} from '@slack/web-api/dist/response/UsersListResponse'; import type { @@ -32,7 +31,7 @@ interface WebClient { interface Config { token: Token; - eventClient: SlackEventAdapter; + eventClient: TeamEventClientInterface; webClient: WebClient; enableReactions?: boolean; } diff --git a/lib/slackEventClient.ts b/lib/slackEventClient.ts index 0c793787..624ab0b3 100644 --- a/lib/slackEventClient.ts +++ b/lib/slackEventClient.ts @@ -1,27 +1,27 @@ import type {SlackEventAdapter} from '@slack/events-api'; export class TeamEventClient { - private readonly eventAdapter: SlackEventAdapter; - private readonly team: string; + #eventAdapter: SlackEventAdapter; + #team: string; // contract: 渡されるeventAdapterは、EventAdapterOptions.includeBodyがtrueでなければならない。 constructor(eventAdapter: SlackEventAdapter, team: string) { - this.eventAdapter = eventAdapter; - this.team = team; + this.#eventAdapter = eventAdapter; + this.#team = team; } // listen on events against all teams. onAllTeam(event: string, listener: (...args: any[]) => void): any { - return this.eventAdapter.on(event, listener); + return this.#eventAdapter.on(event, listener); } // listen on events against the team. on(event: string, listener: (...args: any[]) => void): any { - return this.eventAdapter.on(event, (...args: any[]) => { + return this.#eventAdapter.on(event, (...args: any[]) => { // https://slack.dev/node-slack-sdk/events-api#receive-additional-event-data // https://github.com/slackapi/node-slack-sdk/blob/3e9c483c593d6aa28f6f5680f287722df3327609/packages/events-api/src/http-handler.ts#L212-L223 // https://api.slack.com/apis/connections/events-api#the-events-api__receiving-events__events-dispatched-as-json // args: [body.event, body: {team_id: string}] - if (args[1].team_id === this.team) { + if (args[1].team_id === this.#team) { listener(...args); } }); @@ -29,3 +29,6 @@ export class TeamEventClient { // feel free to add any other [Events](https://nodejs.org/api/events.html) methods you want! } + +// https://stackoverflow.com/a/48953930 +export type TeamEventClientInterface = Pick; diff --git a/lib/slackMock.js b/lib/slackMock.ts similarity index 50% rename from lib/slackMock.js rename to lib/slackMock.ts index 07fd0302..04b192af 100644 --- a/lib/slackMock.js +++ b/lib/slackMock.ts @@ -1,8 +1,10 @@ /* eslint-env node, jest */ -const EventEmitter = require('events'); -const noop = require('lodash/noop'); -const last = require('lodash/last'); +import type {ChatPostMessageArguments, ChatPostMessageResponse, ReactionsAddArguments, ReactionsAddResponse, WebClient} from '@slack/web-api'; +import {EventEmitter} from 'events'; +import {noop, last} from 'lodash'; +import type {SlackInterface} from './slack'; +import { TeamEventClient, TeamEventClientInterface } from './slackEventClient'; // https://jestjs.io/docs/mock-function-api const mockMethodCalls = [ @@ -19,20 +21,33 @@ const mockMethodCalls = [ 'mockClear', 'mockReset', 'mockName', -]; +] as const; -const createWebClient = (fallbackFn, registeredMocks) => { - const handler = (stack) => { +const isMockMethodCall = (name: string): name is (typeof mockMethodCalls)[number] => ( + (mockMethodCalls as readonly string[]).includes(name) +); + +interface MockWebClient extends Record { + (...args: any[]): any; +} + +const createWebClient = ( + fallbackFn: (stack: string[], ...args: any[]) => Promise, + registeredMocks: Map, +) => { + const handler = (stack: string[]): MockWebClient => { return new Proxy( - (...args) => { + (...args: any[]) => { const path = stack.join('.'); + const methodName = last(stack); if (registeredMocks.has(path)) { return registeredMocks.get(path)(...args); } - if (mockMethodCalls.includes(last(stack))) { + if (isMockMethodCall(methodName)) { const mock = jest.fn(); registeredMocks.set(stack.slice(0, -1).join('.'), mock); - return mock[last(stack)](...args); + const mockArgs = args as Parameters; + return mock[methodName](...mockArgs); } return fallbackFn(stack, ...args) }, @@ -48,66 +63,82 @@ const createWebClient = (fallbackFn, registeredMocks) => { return Reflect.get(name, property, receiver); }, } - ); + ) as MockWebClient; }; return handler([]); }; -module.exports = class SlackMock extends EventEmitter { - constructor(...args) { - super(...args); - this.fakeChannel = 'C00000000'; - this.fakeUser = 'U00000000'; - this.fakeTimestamp = '1234567890.123456'; - this.eventClient = new EventEmitter(); +class MockTeamEventClient extends EventEmitter { + onAllTeam(event: string, listener: (...args: any[]) => void): any { + return this.on(event, listener); + } +} + +export default class SlackMock extends EventEmitter implements SlackInterface { + fakeChannel = 'C00000000'; + fakeUser = 'U00000000'; + fakeTeam = 'T00000000'; + fakeTimestamp = '1234567890.123456'; + + readonly eventClient: TeamEventClientInterface & EventEmitter; + readonly registeredMocks: Map; + readonly webClient: WebClient; + readonly messageClient: any; + + constructor() { + super(); + this.eventClient = new MockTeamEventClient(); this.registeredMocks = new Map(); - this.webClient = createWebClient((...args) => this.handleWebcall(...args), this.registeredMocks); + this.webClient = createWebClient( + (stack: string[], ...args: any[]) => this.handleWebcall(stack, ...args), + this.registeredMocks, + ) as unknown as WebClient; this.messageClient = { action: noop, viewSubmission: noop, }; } - handleWebcall(stack, ...args) { + handleWebcall(stack: string[], ...args: any[]) { this.emit('webcall', stack, ...args); this.emit(stack.join('.'), ...args); if (stack.join('.') === "emoji.list") { return Promise.resolve({ok: true, emoji: {"fakeemoji": "https://example.com"}}); } if (stack.join('.') === "users.list") { - return {members: []} + return Promise.resolve({ok: true, members: []}); } if (stack.join('.') === "conversations.list") { return Promise.resolve({ok: true, channels: [ {id: 'CGENERAL', is_general: true}, ]}); } - if (stack.join('.') === "chat.postMessage") { + if (stack.join('.') === "chat.postMessage") { return Promise.resolve({ok: true, ts: this.fakeTimestamp}); } - if (stack.join('.') === "chat.unfurl") { + if (stack.join('.') === "chat.unfurl") { return Promise.resolve({ok: true}); } // TODO: make returned value customizable return Promise.resolve([]); } - postMessage(message, options={}) { + postMessage(message: string, options = {}) { const data = { channel: this.fakeChannel, text: message, user: this.fakeUser, ts: this.fakeTimestamp, - type: "message", + type: 'message', ...options }; this.eventClient.emit('message', data); } - waitForEvent(eventName){ + waitForEvent(eventName: string) { return new Promise((resolve) => { - const handleResponse = (options) => { + const handleResponse = (options: {channel: string} & Record) => { if (options.channel === this.fakeChannel) { this.removeListener(eventName, handleResponse); resolve(options); @@ -119,14 +150,14 @@ module.exports = class SlackMock extends EventEmitter { } waitForResponse() { - return this.waitForEvent('chat.postMessage'); + return this.waitForEvent('chat.postMessage') as Promise; } waitForReaction() { - return this.waitForEvent('reactions.add'); + return this.waitForEvent('reactions.add') as Promise; } - getResponseTo(message, options={}) { + getResponseTo(message: string, options = {}) { const res = this.waitForResponse(); this.postMessage(message, options); return res; @@ -134,7 +165,6 @@ module.exports = class SlackMock extends EventEmitter { // Not recommended. Instanciate a new SlackMock instead. reset() { - this.eventClient.removeAllListeners(); this.removeAllListeners(); this.registeredMocks.clear(); } diff --git a/lib/slackUtils.ts b/lib/slackUtils.ts index 2072a35e..dc53e4b3 100644 --- a/lib/slackUtils.ts +++ b/lib/slackUtils.ts @@ -100,7 +100,7 @@ export const mrkdwn = (text: string): MrkdwnElement => ({ const isGenericMessage = (message: MessageEvent): message is GenericMessageEvent => ( message.subtype === undefined -) +); export const extractMessage = (message: MessageEvent) => { if (isGenericMessage(message)) { diff --git a/lyrics/index.test.ts b/lyrics/index.test.ts index bc211c59..5c2293d3 100644 --- a/lyrics/index.test.ts +++ b/lyrics/index.test.ts @@ -2,8 +2,7 @@ jest.mock('tinyreq'); jest.mock('axios'); import lyrics from './index'; -// @ts-expect-error -import Slack from '../lib/slackMock.js'; +import Slack from '../lib/slackMock'; // @ts-expect-error import tinyreq from 'tinyreq'; import axios from 'axios'; diff --git a/mahjong/index.test.js b/mahjong/index.test.js index fc06a946..2d38e1b4 100644 --- a/mahjong/index.test.js +++ b/mahjong/index.test.js @@ -2,7 +2,7 @@ jest.mock('../achievements'); -const Slack = require('../lib/slackMock.js'); +const {default: Slack} = require('../lib/slackMock.ts'); const mahjong = require('./index.js'); let slack = null; diff --git a/octas/index.test.ts b/octas/index.test.ts index dd92c769..6e0f3863 100644 --- a/octas/index.test.ts +++ b/octas/index.test.ts @@ -1,9 +1,7 @@ jest.mock('cloudinary'); import octas from './index'; -// @ts-expect-error -import Slack from '../lib/slackMock.js'; -import { List } from 'lodash'; +import Slack from '../lib/slackMock'; let slack: Slack = null; @@ -15,7 +13,7 @@ beforeEach(async () => { describe('octas', () => { it('respond to octas', async () => { - const { channel, text, attachments }: { channel: string, text: string, attachments: List } = await slack.getResponseTo('octas'); + const { channel, text, attachments } = await slack.getResponseTo('octas'); expect(channel).toBe(slack.fakeChannel); expect(text).toContain('Octas対人を始めるよ~'); diff --git a/pocky/index.test.js b/pocky/index.test.js index 9880d658..e56e8d67 100644 --- a/pocky/index.test.js +++ b/pocky/index.test.js @@ -7,7 +7,7 @@ jest.mock('../lib/state.ts'); const axios = require('axios'); const pocky = require('./index.js'); -const Slack = require('../lib/slackMock.js'); +const {default: Slack} = require('../lib/slackMock.ts'); let slack = null; diff --git a/ponpe/index.test.ts b/ponpe/index.test.ts index 4840c638..66a3700b 100644 --- a/ponpe/index.test.ts +++ b/ponpe/index.test.ts @@ -15,8 +15,7 @@ fs.virtualFiles = { }; import ponpe from './index'; -// @ts-expect-error -import Slack from '../lib/slackMock.js'; +import Slack from '../lib/slackMock'; let slack: Slack = null; diff --git a/prime/index.test.js b/prime/index.test.js index 672ddcb9..6cc940a0 100644 --- a/prime/index.test.js +++ b/prime/index.test.js @@ -2,7 +2,7 @@ jest.mock('../achievements'); -const Slack = require('../lib/slackMock.js'); +const {default: Slack} = require('../lib/slackMock.ts'); const shogi = require('./index.js'); let slack = null; diff --git a/pwnyaa/index.test.ts b/pwnyaa/index.test.ts index 738e51b1..46ee9d9b 100644 --- a/pwnyaa/index.test.ts +++ b/pwnyaa/index.test.ts @@ -1,8 +1,7 @@ /* eslint-disable no-undef */ import {constants, promises as fs} from 'fs'; import path from 'path'; -// @ts-expect-error -import Slack from '../lib/slackMock.js'; +import Slack from '../lib/slackMock'; import {getMemberName} from '../lib/slackUtils'; import {Challenge, SolvedInfo, Profile} from './lib/BasicTypes'; import {fetchChallsCH, fetchUserProfileCH} from './lib/CHManager'; @@ -231,7 +230,7 @@ beforeEach(async () => { it('respond to usage', async () => { - const {channel, text}: { channel: string, text: string } = await slack.getResponseTo('@pwnyaa usage'); + const {channel, text} = await slack.getResponseTo('@pwnyaa usage'); expect(channel).toBe(slack.fakeChannel); expect(text).toContain('list'); @@ -240,7 +239,7 @@ it('respond to usage', async () => { }); it('respond to help', async () => { - const {channel, text}: { channel: string, text: string } = await slack.getResponseTo('@pwnyaa help'); + const {channel, text} = await slack.getResponseTo('@pwnyaa help'); expect(channel).toBe(slack.fakeChannel); expect(text).toContain('list'); @@ -249,13 +248,13 @@ it('respond to help', async () => { }); it('respond to list', async () => { - const {channel}: { channel: string, text: string } = await slack.getResponseTo('@pwnyaa list'); + const {channel} = await slack.getResponseTo('@pwnyaa list'); expect(channel).toBe(slack.fakeChannel); }); it('respond to check tw', async () => { - const {channel, text}: { channel: string, text: string } = await slack.getResponseTo('@pwnyaa check tw'); + const {channel, text} = await slack.getResponseTo('@pwnyaa check tw'); expect(channel).toBe(slack.fakeChannel); expect(text).toContain('azaika'); @@ -264,27 +263,27 @@ it('respond to check tw', async () => { }); it('respond to check xyz without joining', async () => { - const {channel, text}: { channel: string, text: string } = await slack.getResponseTo('@pwnyaa check xyz'); + const {channel, text} = await slack.getResponseTo('@pwnyaa check xyz'); expect(channel).toBe(slack.fakeChannel); expect(text).toContain('参加してないよ'); }); it('respond to check ch without joining', async () => { - const {channel, text}: { channel: string, text: string } = await slack.getResponseTo('@pwnyaa check ch'); + const {channel, text} = await slack.getResponseTo('@pwnyaa check ch'); expect(channel).toBe(slack.fakeChannel); expect(text).toContain('参加してないよ'); }); it('respond to check ksn without joining', async () => { - const {channel, text}: { channel: string, text: string } = await slack.getResponseTo('@pwnyaa check ksn'); + const {channel, text} = await slack.getResponseTo('@pwnyaa check ksn'); expect(channel).toBe(slack.fakeChannel); expect(text).toContain('参加してないよ'); }); it('respond to check', async () => { - const {channel, text}: { channel: string, text: string } = await slack.getResponseTo('@pwnyaa check'); + const {channel, text} = await slack.getResponseTo('@pwnyaa check'); expect(channel).toBe(slack.fakeChannel); expect(text).toContain('check'); @@ -292,14 +291,14 @@ it('respond to check', async () => { }); it('respond to join hoge fuga', async () => { - const {channel, text}: { channel: string, text: string } = await slack.getResponseTo('@pwnyaa join hoge fuga'); + const {channel, text} = await slack.getResponseTo('@pwnyaa join hoge fuga'); expect(channel).toBe(slack.fakeChannel); expect(text).toContain('は見つからなかったよ'); }); it('respond to join tw', async () => { - const {channel, text}: { channel: string, text: string } = await slack.getResponseTo('@pwnyaa join tw'); + const {channel, text} = await slack.getResponseTo('@pwnyaa join tw'); expect(channel).toBe(slack.fakeChannel); expect(text).toContain('join'); @@ -307,7 +306,7 @@ it('respond to join tw', async () => { }); it('respond to join xyz', async () => { - const {channel, text}: { channel: string, text: string } = await slack.getResponseTo('@pwnyaa join xyz'); + const {channel, text} = await slack.getResponseTo('@pwnyaa join xyz'); expect(channel).toBe(slack.fakeChannel); expect(text).toContain('join'); @@ -315,7 +314,7 @@ it('respond to join xyz', async () => { }); it('respond to join ch', async () => { - const {channel, text}: { channel: string, text: string } = await slack.getResponseTo('@pwnyaa join ch'); + const {channel, text} = await slack.getResponseTo('@pwnyaa join ch'); expect(channel).toBe(slack.fakeChannel); expect(text).toContain('join'); @@ -323,7 +322,7 @@ it('respond to join ch', async () => { }); it('respond to join ksn', async () => { - const {channel, text}: { channel: string, text: string } = await slack.getResponseTo('@pwnyaa join ksn'); + const {channel, text} = await slack.getResponseTo('@pwnyaa join ksn'); expect(channel).toBe(slack.fakeChannel); expect(text).toContain('join'); @@ -331,7 +330,7 @@ it('respond to join ksn', async () => { }); it('respond to stat', async () => { - const {channel, text}: { channel: string, text: string } = await slack.getResponseTo('@pwnyaa stat'); + const {channel, text} = await slack.getResponseTo('@pwnyaa stat'); expect(channel).toBe(slack.fakeChannel); expect(text).toContain('状況だよ'); diff --git a/remember-english/index.test.ts b/remember-english/index.test.ts index 799c1b27..9bf49f67 100644 --- a/remember-english/index.test.ts +++ b/remember-english/index.test.ts @@ -5,8 +5,7 @@ jest.mock('../lib/slackUtils'); jest.mock('../lib/state'); import type {KnownBlock, WebAPICallResult, ViewsOpenArguments} from '@slack/web-api'; -// @ts-expect-error -import Slack from '../lib/slackMock.js'; +import Slack from '../lib/slackMock'; import {RememberEnglish} from '.'; let slack: Slack = null; @@ -47,7 +46,7 @@ beforeEach(async () => { .useFakeTimers() .setSystemTime(now); - rememberEnglish = new MockedRememberEnglish(slack); + rememberEnglish = new MockedRememberEnglish({slack: slack.webClient}); await rememberEnglish.initialize(); }); diff --git a/ricochet-robots/index.test.js b/ricochet-robots/index.test.js index 47abd880..4e76fe8a 100644 --- a/ricochet-robots/index.test.js +++ b/ricochet-robots/index.test.js @@ -8,7 +8,7 @@ const cloudinary = require('cloudinary'); const rust_proxy = require('./rust-proxy.js'); const hyperrobot = require('./index.js'); -const Slack = require('../lib/slackMock.js'); +const {default: Slack} = require('../lib/slackMock.ts'); const fs = require('fs'); const path = require('path'); diff --git a/room-gacha/index.test.ts b/room-gacha/index.test.ts index 02e5461e..9a8a765d 100644 --- a/room-gacha/index.test.ts +++ b/room-gacha/index.test.ts @@ -1,12 +1,13 @@ jest.mock('tinyreq'); import roomGacha from './index'; -// @ts-expect-error -import Slack from '../lib/slackMock.js'; +import Slack from '../lib/slackMock'; // @ts-expect-error import tinyreq from 'tinyreq'; import { promises as fs } from 'fs'; import { stripIndents } from 'common-tags'; +import assert from 'assert'; +import type { Block, KnownBlock } from '@slack/web-api'; let slack: Slack = null; @@ -27,7 +28,11 @@ describe('room-gacha', () => { expect(response.username).toBe('物件ガチャ'); expect(response.icon_emoji).toBe(':house:'); expect(response.text).toBe('物件ガチャの結果だよ〜:full_moon_with_face:'); - expect(response.blocks[0].text.text).toBe('*東京都文京区の賃貸住宅[賃貸マンション・アパート]情報* (12,345件) から選んだよ〜 :full_moon_with_face:'); + + const block0 = response.blocks[0] as KnownBlock; + expect(block0.type).toBe('section'); + assert(block0.type === 'section'); + expect(block0.text.text).toBe('*東京都文京区の賃貸住宅[賃貸マンション・アパート]情報* (12,345件) から選んだよ〜 :full_moon_with_face:'); expect(response.blocks[3].text.text).toBe(stripIndents`** *住所*: 東京都文京区本郷7丁目3−1 *アクセス*: 本郷三丁目駅(地下鉄丸の内線)より徒歩8分 diff --git a/scrapbox/index.test.ts b/scrapbox/index.test.ts index 2c86635f..53fff0f2 100644 --- a/scrapbox/index.test.ts +++ b/scrapbox/index.test.ts @@ -1,7 +1,6 @@ import type {ChatUnfurlArguments} from '@slack/web-api'; import axios from 'axios'; -// @ts-expect-error -import Slack from '../lib/slackMock.js'; +import Slack from '../lib/slackMock'; import scrapbox, {scrapbox2slack} from './index'; jest.mock('axios'); diff --git a/shogi/index.test.js b/shogi/index.test.js index 61ede063..706ab2f7 100644 --- a/shogi/index.test.js +++ b/shogi/index.test.js @@ -5,7 +5,7 @@ jest.mock('sqlite'); const cloudinary = require('cloudinary'); const sqlite = require('sqlite'); -const Slack = require('../lib/slackMock.js'); +const {default: Slack} = require('../lib/slackMock.ts'); const shogi = require('./index.js'); let slack = null; diff --git a/slack-log/index.test.ts b/slack-log/index.test.ts index 3d2b3d12..0a425943 100644 --- a/slack-log/index.test.ts +++ b/slack-log/index.test.ts @@ -1,8 +1,7 @@ import type {ChatUnfurlArguments} from '@slack/web-api'; import axios from 'axios'; import slacklog from './index'; -// @ts-expect-error -import Slack from '../lib/slackMock.js'; +import Slack from '../lib/slackMock'; jest.mock('axios'); @@ -24,7 +23,7 @@ beforeEach(async () => { describe('slacklog', () => { it('respond to slacklog url request', async () => { - const {channel, text}: {channel: string, text: string} = await slack.getResponseTo('slacklog'); + const {channel, text} = await slack.getResponseTo('slacklog'); expect(channel).toBe(slack.fakeChannel); expect(text).toMatch('slack-log.tsg.ne.jp'); @@ -33,7 +32,7 @@ describe('slacklog', () => { it('respond to canonical slacklog-ize request', async () => { const requestURL: string = ''; - const {channel, text}: {channel: string, text: string} = await slack.getResponseTo(`slacklog ${requestURL}`); + const {channel, text} = await slack.getResponseTo(`slacklog ${requestURL}`); const expectURL: string = ''; expect(channel).toBe(slack.fakeChannel); @@ -42,7 +41,7 @@ describe('slacklog', () => { it('respond to slacklog-ize request of practical url from default web UI', async () => { const requestURL: string = ''; - const {channel, text}: {channel: string, text: string} = await slack.getResponseTo(`slacklog ${requestURL}`); + const {channel, text} = await slack.getResponseTo(`slacklog ${requestURL}`); const expectURL: string = ''; expect(channel).toBe(slack.fakeChannel); @@ -51,7 +50,7 @@ describe('slacklog', () => { it('respond to slacklog-ize request of practical url from iOS app', async () => { const requestURL: string = ''; - const {channel, text}: {channel: string, text: string} = await slack.getResponseTo(`slacklog ${requestURL}`); + const {channel, text} = await slack.getResponseTo(`slacklog ${requestURL}`); const expectURL: string = ''; expect(channel).toBe(slack.fakeChannel); diff --git a/sunrise/index.test.ts b/sunrise/index.test.ts index d0f30464..0c3bf385 100644 --- a/sunrise/index.test.ts +++ b/sunrise/index.test.ts @@ -11,8 +11,7 @@ jest.mock('../lib/state'); import FakeTimers from '@sinonjs/fake-timers'; import type {InstalledClock} from '@sinonjs/fake-timers'; -// @ts-expect-error: Untyped -import Slack from '../lib/slackMock.js'; +import Slack from '../lib/slackMock'; import sunrise from './index'; let slack: Slack = null; diff --git a/sushi-bot/index.test.js b/sushi-bot/index.test.js index 5c3c1a9e..7d921e01 100644 --- a/sushi-bot/index.test.js +++ b/sushi-bot/index.test.js @@ -11,7 +11,7 @@ jest.mock('fs-extra', () => ({ const moment = require('moment'); const {default: sushi} = require('./index.ts'); -const Slack = require('../lib/slackMock.js'); +const {default: Slack} = require('../lib/slackMock.ts'); let slack = null; diff --git a/tahoiya/index.test.js b/tahoiya/index.test.js index b3e1bc43..8848ea82 100644 --- a/tahoiya/index.test.js +++ b/tahoiya/index.test.js @@ -8,7 +8,7 @@ const download = require('download'); download.response = Array(10).fill('単語\tたんご\t単語\t000').join('\n'); -const Slack = require('../lib/slackMock.js'); +const {default: Slack} = require('../lib/slackMock.ts'); const tahoiya = require('./index.js'); let slack = null; diff --git a/tiobot/index.test.ts b/tiobot/index.test.ts index 53d138a4..1fef32b9 100644 --- a/tiobot/index.test.ts +++ b/tiobot/index.test.ts @@ -1,6 +1,5 @@ +import Slack from '../lib/slackMock'; import cubebot from './index'; -// @ts-expect-error -import Slack from '../lib/slackMock.js'; let slack: Slack = null; @@ -13,7 +12,7 @@ beforeEach(() => { describe('tiobot', () => { it('responds to tio.run URL', async () => { const {text, username} = await slack.getResponseTo( - 'https://tio.run/##y0osSyxOLsosKNHNy09J/f8/OT@vOD8nVS8nP11DySM1JydfRyE8vygnRVFJ0/r/fwA' + 'https://tio.run/##y0osSyxOLsosKNHNy09J/f8/OT@vOD8nVS8nP11DySM1JydfRyE8vygnRVFJ0/r/fwA', ); expect(username).toBe('tiobot'); diff --git a/vocabwar/index.test.js b/vocabwar/index.test.js index f50d4043..872a8106 100644 --- a/vocabwar/index.test.js +++ b/vocabwar/index.test.js @@ -7,7 +7,7 @@ jest.mock('word2vec'); jest.mock('./state.json', () => ({}), {virtual: true}); const vocabwar = require('./index.js'); -const Slack = require('../lib/slackMock.js'); +const {default: Slack} = require('../lib/slackMock.ts'); const {promisify} = require('util'); const path = require('path'); const fs = require('fs'); diff --git a/voiperrobot/index.test.ts b/voiperrobot/index.test.ts index 8630dee5..5925b6ac 100644 --- a/voiperrobot/index.test.ts +++ b/voiperrobot/index.test.ts @@ -1,8 +1,7 @@ jest.mock('../achievements'); import voiperrobot from './index'; -// @ts-expect-error -import Slack from '../lib/slackMock.js'; +import Slack from '../lib/slackMock'; let slack: Slack = null; diff --git a/wadokaichin/index.test.ts b/wadokaichin/index.test.ts index f254a906..410a25f4 100644 --- a/wadokaichin/index.test.ts +++ b/wadokaichin/index.test.ts @@ -1,5 +1,4 @@ -// @ts-expect-error -import Slack from '../lib/slackMock.js'; +import Slack from '../lib/slackMock'; import path from 'path'; jest.mock('fs'); diff --git a/welcome/index.test.ts b/welcome/index.test.ts index 66b7a493..4a2c7532 100644 --- a/welcome/index.test.ts +++ b/welcome/index.test.ts @@ -1,6 +1,5 @@ import axios from 'axios'; -// @ts-expect-error import Slack from '../lib/slackMock'; import welcome from './index'; diff --git a/wordle-battle/index.test.ts b/wordle-battle/index.test.ts index 6e7235fe..4857c9b0 100644 --- a/wordle-battle/index.test.ts +++ b/wordle-battle/index.test.ts @@ -1,6 +1,5 @@ import wordle_battle from './index'; -// @ts-expect-error -import Slack from '../lib/slackMock.js'; +import Slack from '../lib/slackMock'; let slack: Slack = null; @@ -12,28 +11,28 @@ beforeEach(async () => { describe('wordle battle', () => { it('respond to wordle battle', async () => { - const { channel, text }: { channel: string, text: string } = await slack.getResponseTo('wordle battle'); + const { channel, text } = await slack.getResponseTo('wordle battle'); expect(channel).toBe(slack.fakeChannel); expect(text).toContain('Wordle Battle を開始します!'); }); it('respond to wordle battle 10', async () => { - const { channel, text }: { channel: string, text: string } = await slack.getResponseTo('wordle battle 10'); + const { channel, text } = await slack.getResponseTo('wordle battle 10'); expect(channel).toBe(slack.fakeChannel); expect(text).toContain('Wordle Battle を開始します!'); }); it('respond to wordle battle 100', async () => { - const { channel, text }: { channel: string, text: string } = await slack.getResponseTo('wordle battle 100'); + const { channel, text } = await slack.getResponseTo('wordle battle 100'); expect(channel).toBe(slack.fakeChannel); expect(text).toContain('単語のみに対応しています。'); }); it('respond to wordle reset', async () => { - const { channel, text }: { channel: string, text: string } = await slack.getResponseTo('wordle reset'); + const { channel, text } = await slack.getResponseTo('wordle reset'); expect(channel).toBe(slack.fakeChannel); expect(text).toContain('Wordle Battle をリセットしました。');