Skip to content

Commit d4c279b

Browse files
committed
Fill hub/fetch_with_retry failing test cases
1 parent cfda442 commit d4c279b

File tree

2 files changed

+116
-46
lines changed

2 files changed

+116
-46
lines changed

src/lib/fetch_with_retry.test.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import assert from 'node:assert';
22
import test from 'node:test';
3-
import { Response, MockAgent, setGlobalDispatcher } from 'undici';
3+
import { Response, MockAgent, setGlobalDispatcher, Agent } from 'undici';
44
import { fetchWithRetry } from './fetch_with_retry.js';
55

66
await test('fetchWithRetry should fetch successfully', async () => {
@@ -45,4 +45,21 @@ await test('fetchWithRetry should respect retries option', async () => {
4545

4646
// Restore undici dispatcher
4747
await mockAgent.close();
48+
setGlobalDispatcher(new Agent());
49+
});
50+
51+
await test('fetchWithRetry should raise exception when network is disconnected', async () => {
52+
// Set up undici MockAgent
53+
const mockAgent = new MockAgent();
54+
setGlobalDispatcher(mockAgent);
55+
mockAgent.disableNetConnect();
56+
57+
await assert.rejects(
58+
fetchWithRetry('https://example.com/'),
59+
new TypeError('fetch failed')
60+
);
61+
62+
// Restore undici dispatcher
63+
await mockAgent.close();
64+
setGlobalDispatcher(new Agent());
4865
});

src/lib/hub.test.ts

Lines changed: 98 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,114 @@
1+
import path from 'node:path';
2+
import fs from 'node:fs';
13
import assert from 'node:assert';
2-
import test from 'node:test';
3-
// TODO: エラー用のモック作成
4-
// import { MockAgent, setGlobalDispatcher } from 'undici';
4+
import { describe, test, beforeEach } from 'node:test';
5+
import { MockAgent, setGlobalDispatcher, Agent } from 'undici';
56

67
import * as hub from './hub.js';
78

8-
await test.describe('hub', async () => {
9+
const CACHE_HUB_DIR = path.join(import.meta.dirname, '..', '..', 'cache', 'hub');
910

10-
await test('getHubItemsByQuery should find existing data', async () => {
11-
const res = await hub.getHubItemsByQuery('香川県高松市', '市区町村レベル', '香川県', 'title');
12-
assert.ok(res.numberMatched > 0);
13-
assert.ok(res.features.length >= res.numberMatched);
11+
await describe('hub', async () => {
12+
beforeEach(() => {
13+
if (fs.existsSync(CACHE_HUB_DIR)) {
14+
try {
15+
fs.rmSync(CACHE_HUB_DIR, { recursive: true });
16+
} catch (err) {
17+
console.error('Error cleaning up cache directory:', err);
18+
}
19+
}
1420
});
1521

16-
await test('getHubItemsByQuery should not find non-existing data', async () => {
17-
const res = await hub.getHubItemsByQuery('香川県高松市', '全国レベル', '香川県');
18-
assert.ok(res.numberMatched === 0);
19-
assert.ok(res.features.length === 0);
20-
});
22+
await test.describe('getHubItemsByQuery', async () => {
23+
await test('getHubItemsByQuery should find existing data', async () => {
24+
const res = await hub.getHubItemsByQuery('香川県高松市', '市区町村レベル', '香川県', 'title');
25+
assert.ok(res.numberMatched > 0);
26+
assert.ok(res.features.length >= res.numberMatched);
27+
});
28+
29+
await test('getHubItemsByQuery should not find non-existing data', async () => {
30+
const res = await hub.getHubItemsByQuery('香川県高松市', '全国レベル', '香川県');
31+
assert.ok(res.numberMatched === 0);
32+
assert.ok(res.features.length === 0);
33+
});
34+
35+
await test('getHubItemsByQuery should handle hub handled error', async () => {
36+
const mockAgent = new MockAgent();
37+
setGlobalDispatcher(mockAgent);
38+
39+
const mockPool = mockAgent.get('https://dataset.address-br.digital.go.jp');
40+
mockPool.intercept({
41+
path: '/api/search/v1/collections/all/items?filter=((group IN (864dfb9be4ef483d864e886fa25e1c94)))%20AND%20((categories%20IN%20(%2Fcategories%2F%E5%B8%82%E5%8C%BA%E7%94%BA%E6%9D%91%E3%83%AC%E3%83%99%E3%83%AB%2F%E9%A6%99%E5%B7%9D%E7%9C%8C)))&limit=12&q=%E9%A6%99%E5%B7%9D%E7%9C%8C%E9%AB%98%E6%9D%BE%E5%B8%82',
42+
method: 'GET',
43+
}).reply(
44+
404, {
45+
message: "Cannot GET /api/search/v1/collections/all/items",
46+
error: "Not Found",
47+
statusCode: 404
48+
}, {
49+
headers: { 'content-type': 'application/geo+json' }
50+
}
51+
);
2152

22-
// TODO: エラー用のモック作成
23-
/*
24-
await test('getHubItemsByQuery should handle fetch error', async () => {
25-
// Set up undici MockAgent
26-
const mockAgent = new MockAgent();
27-
setGlobalDispatcher(mockAgent);
28-
29-
const mockPool = mockAgent.get('https://dataset.address-br.digital.go.jp');
30-
mockPool.intercept({ path: '/api/search/v1/collections/all/items', method: 'GET' })
31-
.reply(404, {
32-
message: "Cannot GET /api/search/v1/collections/all/items",
33-
error: "Not Found",
34-
statusCode: 404
35-
}
53+
await assert.rejects(
54+
hub.getHubItemsByQuery('香川県高松市', '市区町村レベル', '香川県'),
55+
new Error('HUB API returned an error: {"message":"Cannot GET /api/search/v1/collections/all/items","error":"Not Found","statusCode":404}')
3656
);
3757

38-
await assert.rejects(
39-
hub.getHubItemsByQuery('香川県高松市', '市区町村レベル', '香川県'),
40-
/HUB API returned an error: 404 Not Found/
41-
);
58+
await mockAgent.close();
59+
setGlobalDispatcher(new Agent());
60+
});
4261

43-
// Restore undici dispatcher
44-
await mockAgent.close();
45-
});
46-
*/
62+
await test('getHubItemsByQuery should handle hub unhandled error', async () => {
63+
const mockAgent = new MockAgent();
64+
setGlobalDispatcher(mockAgent);
65+
66+
const mockPool = mockAgent.get('https://dataset.address-br.digital.go.jp');
67+
mockPool.intercept({
68+
path: '/api/search/v1/collections/all/items?filter=((group IN (864dfb9be4ef483d864e886fa25e1c94)))%20AND%20((categories%20IN%20(%2Fcategories%2F%E5%B8%82%E5%8C%BA%E7%94%BA%E6%9D%91%E3%83%AC%E3%83%99%E3%83%AB%2F%E9%A6%99%E5%B7%9D%E7%9C%8C)))&limit=12&q=%E9%A6%99%E5%B7%9D%E7%9C%8C%E9%AB%98%E6%9D%BE%E5%B8%82',
69+
method: 'GET',
70+
}).reply(
71+
404,
72+
"Not Found"
73+
);
74+
75+
await assert.rejects(
76+
hub.getHubItemsByQuery('香川県高松市', '市区町村レベル', '香川県'),
77+
new Error('HUB API returned an error: 404 Not Found')
78+
);
79+
80+
await mockAgent.close();
81+
setGlobalDispatcher(new Agent());
82+
});
83+
84+
await test('getHubItemsByQuery should handle fetch error when network is disconnected', async () => {
85+
const mockAgent = new MockAgent();
86+
setGlobalDispatcher(mockAgent);
87+
mockAgent.disableNetConnect();
88+
89+
await assert.rejects(
90+
hub.getHubItemsByQuery('香川県高松市', '市区町村レベル', '香川県'),
91+
new TypeError('fetch failed')
92+
);
4793

48-
await test('getHubItemById should find existing data', async () => {
49-
const res = await hub.getHubItemById('45bcb60e4dc747b58def5493ab829825');
50-
assert.strictEqual(res.properties.title, '全国 都道府県マスター');
51-
assert.strictEqual(res.properties.id, '45bcb60e4dc747b58def5493ab829825');
94+
await mockAgent.close();
95+
setGlobalDispatcher(new Agent());
96+
});
5297
});
5398

54-
await test('getHubItemById should raise exception for non-existing data', async () => {
55-
await assert.rejects(
56-
hub.getHubItemById('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'),
57-
/HUB API returned an error: {"message":"Cannot find item with recordId xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx in collection All","error":"Not Found","statusCode":404}/
58-
);
99+
await test.describe('getHubItemById', async () => {
100+
await test('getHubItemById should find existing data', async () => {
101+
const res = await hub.getHubItemById('45bcb60e4dc747b58def5493ab829825');
102+
assert.strictEqual(res.properties.title, '全国 都道府県マスター');
103+
assert.strictEqual(res.properties.id, '45bcb60e4dc747b58def5493ab829825');
104+
});
105+
106+
await test('getHubItemById should raise exception for non-existing data', async () => {
107+
await assert.rejects(
108+
hub.getHubItemById('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'),
109+
new Error('HUB API returned an error: {"message":"Cannot find item with recordId xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx in collection All","error":"Not Found","statusCode":404}')
110+
);
111+
});
59112
});
60113

61114
await test.describe('downloadAndExtract', async () => {
@@ -76,7 +129,7 @@ await test.describe('hub', async () => {
76129
const res = hub.downloadAndExtract<Record<string, string>>('https://data.address-br.digital.go.jp/mt_town/city/mt_town_cityXXXXXX.csv.zip');
77130
await assert.rejects(
78131
res.next(),
79-
/HTTP 404: Not Found/
132+
new Error('HTTP 404: Not Found')
80133
);
81134
});
82135
});

0 commit comments

Comments
 (0)