Skip to content

Commit 46b98b9

Browse files
committed
feat(jest): add unit tests
1 parent b58d346 commit 46b98b9

11 files changed

+186
-55
lines changed

jest.config.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module.exports = {
2+
preset: 'ts-jest',
3+
transform: { '^.+\\.ts?$': 'ts-jest' },
4+
testEnvironment: 'node',
5+
testRegex: '/tests/.*\\.(test|spec)?\\.(ts|tsx)$',
6+
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
7+
roots: ['<rootDir>/src'],
8+
moduleNameMapper: {
9+
'@/(.*)': '<rootDir>/src/$1'
10+
}
11+
}

package.json

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"dev": "wrangler dev src/index.ts --env=local",
66
"build": "wrangler build src/index.ts",
77
"deploy": "wrangler deploy --minify src/index.ts",
8+
"test": "jest",
89
"prettier": "prettier . --write"
910
},
1011
"dependencies": {
@@ -14,8 +15,11 @@
1415
},
1516
"devDependencies": {
1617
"@cloudflare/workers-types": "^4.20230914.0",
18+
"@types/jest": "^29.5.12",
1719
"@types/react": "^18.2.46",
20+
"jest": "^29.7.0",
1821
"prettier": "3.2.5",
22+
"ts-jest": "^29.1.3",
1923
"wrangler": "^3.21.0"
2024
},
2125
"homepage": "https://tnktok.com"

src/index.ts

+25-26
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,24 @@ const app = new Hono()
1111

1212
app.get('/test/:videoId', async (c) => {
1313
const { videoId } = c.req.param()
14-
const awemeId = await scrapeVideoData(videoId)
1514

16-
if (awemeId instanceof Error) {
17-
return new Response((awemeId as Error).message, { status: 500 })
18-
}
15+
try {
16+
const videoData = await scrapeVideoData(videoId)
1917

20-
return new Response(JSON.stringify(awemeId), {
21-
status: 200,
22-
headers: {
23-
'Content-Type': 'application/json; charset=utf-8'
24-
}
25-
})
18+
return new Response(JSON.stringify(videoData), {
19+
status: 200,
20+
headers: {
21+
'Content-Type': 'application/json; charset=utf-8'
22+
}
23+
})
24+
} catch (e) {
25+
return new Response((e as Error).message, {
26+
status: 500,
27+
headers: {
28+
'Content-Type': 'text/plain; charset=utf-8'
29+
}
30+
})
31+
}
2632
})
2733

2834
app.get('/', (c) => {
@@ -59,7 +65,7 @@ async function handleVideo(c: any): Promise<Response> {
5965
id = awemeId
6066
} catch (e) {
6167
const responseContent = await ErrorResponse((e as Error).message)
62-
return returnHTMLResponse(responseContent, 201)
68+
return returnHTMLResponse(responseContent, 500)
6369
}
6470
}
6571

@@ -68,7 +74,7 @@ async function handleVideo(c: any): Promise<Response> {
6874

6975
if (videoInfo instanceof Error) {
7076
const responseContent = await ErrorResponse((videoInfo as Error).message)
71-
return returnHTMLResponse(responseContent, 201)
77+
return returnHTMLResponse(responseContent, 500)
7278
}
7379

7480
const url = new URL(c.req.url)
@@ -99,9 +105,8 @@ async function handleVideo(c: any): Promise<Response> {
99105
return returnHTMLResponse(responseContent)
100106
}
101107
} catch (e) {
102-
console.log(e)
103108
const responseContent = await ErrorResponse((e as Error).message)
104-
return returnHTMLResponse(responseContent, 201)
109+
return returnHTMLResponse(responseContent, 500)
105110
}
106111
}
107112

@@ -116,21 +121,13 @@ app.get('/generate/alternate', (c) => {
116121
})
117122
})
118123

119-
app.get(
120-
'/generate/*',
121-
cache({
122-
cacheName: 'my-app',
123-
cacheControl: 'max-age=3600'
124-
})
125-
)
126-
127124
app.get('/generate/video/:videoId', async (c) => {
128125
const { videoId } = c.req.param()
129126

130127
try {
131-
/*
132-
const data = await scrapeVideoData(videoId);
128+
const data = await scrapeVideoData(videoId)
133129

130+
/*
134131
if (!(data instanceof Error)) {
135132
if(data.video.playAddr) {
136133
return c.redirect(data.video.playAddr)
@@ -143,6 +140,7 @@ app.get('/generate/video/:videoId', async (c) => {
143140
}
144141
}
145142
*/
143+
146144
return c.redirect(`https://tikwm.com/video/media/play/${videoId}.mp4`)
147145
} catch (e) {
148146
return new Response((e as Error).message, {
@@ -158,9 +156,9 @@ app.get('/generate/image/:videoId', async (c) => {
158156
const { videoId } = c.req.param()
159157

160158
try {
161-
/*
162-
const data = await scrapeVideoData(videoId);
159+
const data = await scrapeVideoData(videoId)
163160

161+
/*
164162
if (!(data instanceof Error)) {
165163
if(data.imagePost.images.length > 0) {
166164
return c.redirect(data.imagePost.images[0].imageURL.urlList[0])
@@ -169,6 +167,7 @@ app.get('/generate/image/:videoId', async (c) => {
169167
}
170168
}
171169
*/
170+
172171
return c.redirect(`https://tikwm.com/video/cover/${videoId}.webp`)
173172
} catch (e) {
174173
return new Response((e as Error).message, {

src/services/tiktok.ts

+1-7
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ export async function grabAwemeId(videoId: string): Promise<String | Error> {
2020
}
2121

2222
export async function scrapeVideoData(awemeId: string, author?: string): Promise<ItemStruct | Error> {
23-
console.log('before', cookie.getUpdatingCookies())
24-
const res = await fetch(`https://www.tiktok.com/@${author || 'i'}"/video/${awemeId}`, {
23+
const res = await fetch(`https://www.tiktok.com/@${author || 'i'}/video/${awemeId}`, {
2524
method: 'GET',
2625
headers: {
2726
Accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
@@ -34,8 +33,6 @@ export async function scrapeVideoData(awemeId: string, author?: string): Promise
3433
}
3534
})
3635

37-
console.log('string', cookie.getCookiesAsString())
38-
console.log(res.headers)
3936
let cookies = cookieParser(res.headers.get('set-cookie')!)
4037
cookie.setCookies(cookies)
4138

@@ -47,18 +44,15 @@ export async function scrapeVideoData(awemeId: string, author?: string): Promise
4744
.split('</script>')[0]
4845
const json: WebJSONResponse = JSON.parse(resJson)
4946

50-
//console.log(Object.keys(json["__DEFAULT_SCOPE__"]));
5147
if (
5248
!json['__DEFAULT_SCOPE__']['webapp.video-detail'] ||
5349
json['__DEFAULT_SCOPE__']['webapp.video-detail'].statusCode == 10204
5450
)
5551
throw new Error('Could not find video data')
5652
const videoInfo = json['__DEFAULT_SCOPE__']['webapp.video-detail']['itemInfo']['itemStruct']
57-
//console.log(videoInfo)
5853

5954
return videoInfo
6055
} catch (err) {
61-
console.log(err)
6256
throw new Error('Could not parse video info')
6357
}
6458
}

src/services/tiktokv.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export async function getVideoInfo(awemeId: string): Promise<AwemeList | Error>
2727
cacheTtlByStatus: { '200-299': 86400, 404: 1, '500-599': 0 }
2828
}
2929
})
30-
const json: TikTokAPIResponse = await res.json()
30+
const json = (await res.json()) as TikTokAPIResponse
3131
const videoInfo: AwemeList | undefined = json.aweme_list.find((aweme) => aweme.aweme_id === awemeId)
3232

3333
if (videoInfo) {

src/templates/pages/VideoResponse.tsx

-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ export function VideoResponse(data: ItemStruct): JSX.Element {
2222
}
2323
*/
2424

25-
console.log(data)
2625
return (
2726
<>
2827
{MetaHelper(

src/tests/main.test.ts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import app from '@/index'
2+
3+
describe('GET /test/:videoId', () => {
4+
it('should return 200', async () => {
5+
const res = await app.request('/test/7332187682480590112', {
6+
method: 'GET'
7+
})
8+
9+
expect(res.status).toBe(200)
10+
})
11+
12+
it('should return 500', async () => {
13+
const res = await app.request('/test/123', {
14+
method: 'GET'
15+
})
16+
17+
expect(res.status).toBe(500)
18+
expect(await res.text()).toBe('Could not parse video info')
19+
})
20+
})

src/tests/photo.test.ts

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import app from '@/index'
2+
3+
describe('GET /@i/photo/:videoId', () => {
4+
it('should return 200', async () => {
5+
const res = await app.request('/@i/photo/7335753580093164833', {
6+
method: 'GET',
7+
headers: {
8+
'User-Agent': 'Mozilla/5.0 (compatible; Discordbot/2.0; +https://discordapp.com)'
9+
}
10+
})
11+
12+
expect(res.status).toBe(200)
13+
})
14+
15+
// no discord user agent, redirects
16+
it('should return 302', async () => {
17+
const res = await app.request('/@i/photo/7335753580093164833', {
18+
method: 'GET'
19+
})
20+
21+
expect(res.status).toBe(302)
22+
})
23+
24+
it('should return 500', async () => {
25+
const res = await app.request('/@i/photo/123', {
26+
method: 'GET',
27+
headers: {
28+
'User-Agent': 'Mozilla/5.0 (compatible; Discordbot/2.0; +https://discordapp.com)'
29+
}
30+
})
31+
32+
expect(res.status).toBe(500)
33+
expect(await res.text()).toContain('An error occurred while trying to fetch the video. Please try again later.')
34+
})
35+
})
36+
37+
describe('GET /generate/image/:videoId', () => {
38+
it('should return 302', async () => {
39+
const res = await app.request('/generate/image/7335753580093164833', {
40+
method: 'GET'
41+
})
42+
43+
expect(res.status).toBe(302)
44+
})
45+
46+
it('should return 500', async () => {
47+
const res = await app.request('/generate/image/123', {
48+
method: 'GET'
49+
})
50+
51+
expect(res.status).toBe(500)
52+
})
53+
})

src/tests/video.test.ts

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import app from '@/index'
2+
3+
describe('GET /@i/video/:videoId', () => {
4+
it('should return 200', async () => {
5+
const res = await app.request('/@pr4yforgabs/video/7332187682480590112', {
6+
method: 'GET',
7+
headers: {
8+
'User-Agent': 'Mozilla/5.0 (compatible; Discordbot/2.0; +https://discordapp.com)'
9+
}
10+
})
11+
12+
expect(res.status).toBe(200)
13+
})
14+
15+
// no discord user agent, redirects
16+
it('should return 302', async () => {
17+
const res = await app.request('/@pr4yforgabs/video/7332187682480590112', {
18+
method: 'GET'
19+
})
20+
21+
expect(res.status).toBe(302)
22+
})
23+
24+
it('should return 500', async () => {
25+
const res = await app.request('/@i/video/123', {
26+
method: 'GET',
27+
headers: {
28+
'User-Agent': 'Mozilla/5.0 (compatible; Discordbot/2.0; +https://discordapp.com)'
29+
}
30+
})
31+
32+
expect(res.status).toBe(500)
33+
expect(await res.text()).toContain('An error occurred while trying to fetch the video. Please try again later.')
34+
})
35+
})
36+
37+
describe('GET /t/:videoId', () => {
38+
it('should return 200', async () => {
39+
const res = await app.request('/t/ZPRKrbUB1', {
40+
method: 'GET',
41+
headers: {
42+
'User-Agent': 'Mozilla/5.0 (compatible; Discordbot/2.0; +https://discordapp.com)'
43+
}
44+
})
45+
46+
expect(res.status).toBe(200)
47+
})
48+
})
49+
50+
describe('GET /generate/video/:videoId', () => {
51+
it('should return 302', async () => {
52+
const res = await app.request('/generate/video/7332187682480590112', {
53+
method: 'GET'
54+
})
55+
56+
expect(res.status).toBe(302)
57+
})
58+
59+
it('should return 500', async () => {
60+
const res = await app.request('/generate/video/123', {
61+
method: 'GET'
62+
})
63+
64+
expect(res.status).toBe(500)
65+
})
66+
})

src/util/cookieHelper.ts

-18
Original file line numberDiff line numberDiff line change
@@ -24,26 +24,8 @@ export default class CookieHelper {
2424
return Object.freeze({ ...this.cookies })
2525
}
2626
getCookiesAsString() {
27-
/*
28-
this.cookies
29-
[
30-
{
31-
name: 'ttwid',
32-
value: '1|8WN5g_4UuJAXRCCDkpvHVs1VcAxDbE1YbchrWF9WLpQ|1716658463|7e41f1aa8f1a95fa8a4d5e4e56dc24eb6c05bbff5e66db010e6cd7f543a5a463',
33-
domain: '.tiktok.com',
34-
path: '/',
35-
expires: 2024-11-21T17:34:23.000Z,
36-
'httponly, tt_csrf_token': '3fBpsXXj-X7xQXEbXEchtyGe7ZxGbSzQGJHo',
37-
sameSite: 'lax',
38-
secure: true,
39-
'httponly, tt_chain_token': 'ATA0mqdlbe36/vayBw/R2g==',
40-
httpOnly: true
41-
}
42-
]
43-
*/
4427
return this.cookies
4528
.map((cookie) => {
46-
console.log(cookie)
4729
return `${cookie.name}=${cookie.value}`
4830
})
4931
.join('; ')

tsconfig.json

+5-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66
"esModuleInterop": true,
77
"strict": true,
88
"lib": ["esnext"],
9-
"types": ["@cloudflare/workers-types"],
9+
"types": ["@cloudflare/workers-types", "@types/jest"],
1010
"jsx": "react-jsx",
11-
"jsxImportSource": "hono/jsx"
11+
"jsxImportSource": "hono/jsx",
12+
"paths": {
13+
"@/*": ["./src/*"]
14+
}
1215
}
1316
}

0 commit comments

Comments
 (0)