Skip to content

Commit cbe966e

Browse files
committed
fix: update comments to clarify test environment usage and remove unused state.js file
1 parent 43b56f0 commit cbe966e

8 files changed

Lines changed: 90 additions & 66 deletions

File tree

atequiz/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// XXX: このファイルは mahjong/index.js (CJS) require('../atequiz/index') でロードするために存在するスタブ。
1+
// XXX: このファイルは mahjong/index.js (CJS) がテスト環境で require('../atequiz/index') でロードするために存在するスタブ。
22
// mahjong/index.js は CJS 形式のため Vite のモジュール解決をバイパスし、Node の CJS ローダーが
33
// .ts 拡張子を解決できないので、atequiz/index.ts の代わりにこの .js スタブが必要になっている。
44
// プロジェクトの ESM 化(または mahjong/index.js の TypeScript 化)完了後は必ずこのファイルを削除すること。(#846)

deploy/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// XXX: このファイルは mahjong/index.js (CJS) require('../deploy/index') でロードするために存在するスタブ。
1+
// XXX: このファイルは mahjong/index.js (CJS) がテスト環境で require('../deploy/index') でロードするために存在するスタブ。
22
// mahjong/index.js は CJS 形式のため Vite のモジュール解決をバイパスし、Node の CJS ローダーが
33
// .ts 拡張子を解決できないので、deploy/index.ts の代わりにこの .js スタブが必要になっている。
44
// プロジェクトの ESM 化(または mahjong/index.js の TypeScript 化)完了後は必ずこのファイルを削除すること。(#846)

lib/logger.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// XXX: このファイルは hangman/index.js・summary/index.js・summary/summary_writer.js (CJS) が
2-
// require('../lib/logger') でロードするために存在するスタブ。
2+
// テスト環境で require('../lib/logger') でロードするために存在するスタブ。
33
// これらのファイルは CJS 形式のため Vite のモジュール解決をバイパスし、Node の CJS ローダーが
44
// .ts 拡張子を解決できないので、lib/logger.ts の代わりにこの .js スタブが必要になっている。
55
// プロジェクトの ESM 化(または各 CJS ファイルの TypeScript 化)完了後は必ずこのファイルを削除すること。(#846)

lib/slackMock.ts

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,28 @@ import last from 'lodash/last.js';
44
import type {SlackInterface} from './slack';
55
import {createMessageAdapter} from '@slack/interactive-messages';
66
import type {BlockAction} from '@slack/bolt';
7-
import {vi, type MockInstance} from 'vitest';
7+
import {vi, type Mock} from 'vitest';
88

99
// https://vitest.dev/api/mock.html
1010
const mockMethodCalls = [
11+
'getMockImplementation',
12+
'getMockName',
13+
'mockClear',
14+
'mockName',
1115
'mockImplementation',
1216
'mockImplementationOnce',
13-
'mockReturnThis',
14-
'mockReturnValue',
15-
'mockReturnValueOnce',
16-
'mockResolvedValue',
17-
'mockResolvedValueOnce',
17+
'withImplementation',
1818
'mockRejectedValue',
1919
'mockRejectedValueOnce',
20-
'mockRestore',
21-
'mockClear',
2220
'mockReset',
23-
'mockName',
21+
'mockRestore',
22+
'mockResolvedValue',
23+
'mockResolvedValueOnce',
24+
'mockReturnThis',
25+
'mockReturnValue',
26+
'mockReturnValueOnce',
27+
'mockThrow',
28+
'mockThrowOnce',
2429
] as const;
2530

2631
const isMockMethodCall = (name: string): name is (typeof mockMethodCalls)[number] => (
@@ -33,15 +38,16 @@ interface MockWebClient extends Record<string, MockWebClient> {
3338

3439
const createWebClient = (
3540
fallbackFn: (stack: string[], ...args: any[]) => Promise<any>,
36-
registeredMocks: Map<string, MockInstance>,
41+
registeredMocks: Map<string, Mock>,
3742
) => {
3843
const handler = (stack: string[]): MockWebClient => {
3944
return new Proxy(
4045
(...args: any[]) => {
4146
const path = stack.join('.');
4247
const methodName = last(stack);
43-
if (registeredMocks.has(path)) {
44-
return (registeredMocks.get(path) as unknown as (...args: any[]) => any)(...args);
48+
const registeredMock = registeredMocks.get(path);
49+
if (registeredMock !== undefined) {
50+
return registeredMock(...args);
4551
}
4652
if (isMockMethodCall(methodName)) {
4753
const mock = vi.fn();
@@ -139,7 +145,7 @@ export default class SlackMock extends EventEmitter implements SlackInterface {
139145
fakeTimestamp = '1234567890.123456';
140146

141147
readonly eventClient: MockTeamEventClient;
142-
readonly registeredMocks: Map<string, MockInstance>;
148+
readonly registeredMocks: Map<string, Mock>;
143149
readonly webClient: WebClient;
144150
readonly messageClient: ReturnType<typeof createMessageAdapter> & MockMessageClient;
145151

lib/slackUtils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// XXX: このファイルは anime/index.js・hangman/index.js (CJS) require('../lib/slackUtils') で
1+
// XXX: このファイルは anime/index.js・hangman/index.js (CJS) がテスト環境で require('../lib/slackUtils') で
22
// ロードするために存在するスタブ。
33
// これらのファイルは CJS 形式のため Vite のモジュール解決をバイパスし、Node の CJS ローダーが
44
// .ts 拡張子を解決できないので、lib/slackUtils.ts の代わりにこの .js スタブが必要になっている。

lib/state.js

Lines changed: 0 additions & 13 deletions
This file was deleted.

lyrics/index.test.ts

Lines changed: 66 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,28 @@ import lyrics from './index';
22
import Slack from '../lib/slackMock';
33
import axios from 'axios';
44
import type {AxiosResponse} from 'axios';
5-
import { stripIndent } from 'common-tags';
5+
import { stripIndent, oneLineTrim } from 'common-tags';
66

7-
vi.mock('scrape-it', async (importOriginal) => {
8-
const actual = await importOriginal<typeof import('scrape-it')>();
9-
const {scrapeHTML} = actual;
10-
const searchHtml = [
11-
'<html><body><dl id="search_list">',
12-
'<dt><span><a href="/song/159792/">とまどい→レシピ</a></span>',
13-
'<a>みかくにんぐッ!</a>(作詞:<a>Junky</a>/作曲:<a>Junky</a>)</dt>',
14-
'<dd></dd></dl></body></html>',
15-
].join('');
16-
const songHtml = [
17-
'<html><head><link rel="canonical" href="https://www.uta-net.com/song/159792/"></head>',
18-
'<body><div id="main"><div class="row"><div><div><div><div>',
19-
'<h2>とまどい→レシピ</h2>',
20-
'<h3><a><span itemprop="byArtist name">みかくにんぐッ!</span></a></h3>',
21-
'</div><div></div><div><p class="detail">',
22-
'作詞:<a href="/lyricist/7740/" itemprop="lyricist">Junky</a><br>',
23-
'作曲:<a href="/composer/9401/" itemprop="composer">Junky</a><br>',
24-
'</p></div></div></div></div></div>',
25-
'<div id="kashi"><div><div id="kashi_area">',
26-
'略<br><br>',
27-
'朝目が覚めたらもう昨日みたいな日常はなくて<br>',
28-
'「ホントあぁもう...えっとどうしよう」<br>',
29-
'ため息混じりに練るお菓子と妄想のレシピの中に<br>',
30-
'恋心入っちゃった<br><br>',
31-
'略</div></div></div></div></body></html>',
32-
].join('');
33-
return {
34-
default: vi.fn(async (url: any, opts: any) => {
35-
if (String(url).includes('index_search')) return {data: scrapeHTML(searchHtml, opts)};
36-
if (String(url).includes('/song/')) return {data: scrapeHTML(songHtml, opts)};
37-
return {data: {}};
38-
}),
39-
scrapeHTML,
7+
vi.mock('axios');
8+
9+
// scrape-itはCJSのrequire経由でaxiosを呼ぶため、ESMモックが届かない。
10+
// そのためscrape-itをモックし、内部でモック済みaxiosを使って同じURLルーティングを通す。
11+
vi.mock('scrape-it', async () => {
12+
const {load} = await vi.importActual<typeof import('cheerio')>('cheerio');
13+
const {default: axiosFn} = await import('axios');
14+
const scrapeItCoreModule = await vi.importActual<any>('scrape-it-core');
15+
const scrapeHTML: ($: any, opts: any) => any =
16+
typeof scrapeItCoreModule === 'function' ? scrapeItCoreModule : scrapeItCoreModule.default;
17+
18+
const scrapeIt = async <T>(url: string, opts: object): Promise<{data: T}> => {
19+
const res = await axiosFn(url) as {data: string};
20+
const $ = load(res.data);
21+
return {data: scrapeHTML($, opts) as T};
4022
};
23+
(scrapeIt as any).scrapeHTML = scrapeHTML;
24+
25+
return {default: scrapeIt};
4126
});
42-
vi.mock('axios');
4327

4428
let slack: Slack = null;
4529

@@ -51,8 +35,55 @@ beforeEach(async () => {
5135

5236
describe('lyrics', () => {
5337
it('responds to @lyrics query', async () => {
38+
const searchHtml = oneLineTrim`
39+
<html><body><dl id="search_list">
40+
<dt>
41+
<span><a href="/song/159792/">とまどい→レシピ</a></span>
42+
<a>みかくにんぐッ!</a> (作詞:<a>Junky</a>/作曲:<a>Junky</a>)
43+
</dt>
44+
<dd></dd>
45+
</dl></body></html>`;
46+
const songHtml = oneLineTrim`
47+
<html><head>
48+
<link rel="canonical" href="https://www.uta-net.com/song/159792/">
49+
</head><body><div id="main">
50+
<div class="row"><div><div><div>
51+
<div>
52+
<h2>とまどい→レシピ</h2>
53+
<h3><a><span itemprop="byArtist name">みかくにんぐッ!</span></a></h3>
54+
</div>
55+
<div></div>
56+
<div>
57+
<p>未確認で進行形 オープニング</p>
58+
<p class="detail">
59+
作詞:<a href="/lyricist/7740/" itemprop="lyricist">Junky</a><br>
60+
作曲:<a href="/composer/9401/" itemprop="composer">Junky</a><br>
61+
発売日:2014/02/19<br> この曲の表示回数:106,837回
62+
</p>
63+
</div>
64+
</div></div></div></div>
65+
<div id="kashi"><div><div id="kashi_area">
66+
67+
<br><br>
68+
朝目が覚めたらもう昨日みたいな日常はなくて
69+
<br>
70+
「ホントあぁもう...えっとどうしよう」
71+
<br>
72+
ため息混じりに練るお菓子と妄想のレシピの中に
73+
<br>
74+
恋心入っちゃった
75+
<br><br>
76+
77+
</div></div></div>
78+
</div></body></html>`;
5479
const mockAxios = vi.mocked(axios);
5580
mockAxios.mockImplementation(async (url: string) => {
81+
if (url.includes('index_search')) {
82+
return {data: searchHtml} as AxiosResponse;
83+
}
84+
if (url.includes('song')) {
85+
return {data: songHtml} as AxiosResponse;
86+
}
5687
if (url.includes('itunes')) {
5788
return {data: {
5889
resultCount: 1,

prime/primes.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// XXX: このファイルは prime/index.js (CJS) require('./primes') でロードするために存在する。
1+
// XXX: このファイルは prime/index.js (CJS) がテスト環境で require('./primes') でロードするために存在する。
22
// prime/index.js は CJS 形式のため Vite のモジュール解決をバイパスし、Node の CJS ローダーが
33
// .ts 拡張子を解決できないので、primes.ts の代わりにこの .js ファイルが必要になっている。
44
// プロジェクトの ESM 化(または prime/index.js の TypeScript 化)完了後は必ずこのファイルを削除すること。(#846)

0 commit comments

Comments
 (0)