Repository: cloudflare/wildebeest
File: backend/test/activitypub/follow.spec.ts (TypeScript)

Code before:
import type { JWK } from 'wildebeest/backend/src/webpush/jwk'
import * as ap_followers_page from 'wildebeest/functions/ap/users/[id]/followers/page'
import * as ap_following_page from 'wildebeest/functions/ap/users/[id]/following/page'
import * as ap_followers from 'wildebeest/functions/ap/users/[id]/followers'
import * as ap_following from 'wildebeest/functions/ap/users/[id]/following'
import { addFollowing, acceptFollowing } from 'wildebeest/backend/src/mastodon/follow'
import { strict as assert } from 'node:assert/strict'
import { makeDB } from '../utils'
import { createPerson } from 'wildebeest/backend/src/activitypub/actors'

const userKEK = 'test_kek10'
const domain = 'cloudflare.com'
const adminEmail = 'admin@example.com'
const vapidKeys = {} as JWK

describe('ActivityPub', () => {
	describe('Follow', () => {
		let receivedActivity: any = null

		beforeEach(() => {
			receivedActivity = null

			globalThis.fetch = async (input: any) => {
				if (input.url === `https://${domain}/ap/users/sven2/inbox`) {
					assert.equal(input.method, 'POST')
					const data = await (input as Response).json()
					receivedActivity = data
					console.log({ receivedActivity })
					return new Response('')
				}

				throw new Error('unexpected request to ' + input.url)
			}
		})

		test('Receive follow with Accept reply', async () => {
			const db = await makeDB()
			const actor = await createPerson(domain, db, userKEK, 'sven@cloudflare.com')
			const actor2 = await createPerson(domain, db, userKEK, 'sven2@cloudflare.com')

			const activity = {
				'@context': 'https://www.w3.org/ns/activitystreams',
				type: 'Follow',
				actor: actor2.id.toString(),
				object: actor.id.toString(),
			}

			await activityHandler.handle(domain, activity, db, userKEK, adminEmail, vapidKeys)

			const row = await db
				.prepare(`SELECT target_actor_id, state FROM actor_following WHERE actor_id=?`)

Review comment (suggestion):
`input` is actually a `Request` not `Response` 😱 

But I think the correct fix here is to give the function being defined a proper type:

```
			globalThis.fetch = async (input: RequestInfo) => {
				const request = new Request(input)
				if (request.url === `https://${domain}/ap/users/sven2/inbox`) {
					assert.equal(request.method, 'POST')
					const data = await request.json()
					receivedActivity = data
					console.log({ receivedActivity })
					return new Response('')
				}

				throw new Error('unexpected request to ' + request.url)
			}
```

Code after:
import type { JWK } from 'wildebeest/backend/src/webpush/jwk'
import * as ap_followers_page from 'wildebeest/functions/ap/users/[id]/followers/page'
import * as ap_following_page from 'wildebeest/functions/ap/users/[id]/following/page'
import * as ap_followers from 'wildebeest/functions/ap/users/[id]/followers'
import * as ap_following from 'wildebeest/functions/ap/users/[id]/following'
import { addFollowing, acceptFollowing } from 'wildebeest/backend/src/mastodon/follow'
import { strict as assert } from 'node:assert/strict'
import { makeDB } from '../utils'
import { createPerson } from 'wildebeest/backend/src/activitypub/actors'

const userKEK = 'test_kek10'
const domain = 'cloudflare.com'
const adminEmail = 'admin@example.com'
const vapidKeys = {} as JWK

describe('ActivityPub', () => {
	describe('Follow', () => {
		let receivedActivity: any = null

		beforeEach(() => {
			receivedActivity = null

			globalThis.fetch = async (input: RequestInfo) => {
				const request = new Request(input)
				if (request.url === `https://${domain}/ap/users/sven2/inbox`) {
					assert.equal(request.method, 'POST')
					const data = await request.json()
					receivedActivity = data
					console.log({ receivedActivity })
					return new Response('')
				}

				throw new Error('unexpected request to ' + request.url)
			}
		})

		test('Receive follow with Accept reply', async () => {
			const db = await makeDB()
			const actor = await createPerson(domain, db, userKEK, 'sven@cloudflare.com')
			const actor2 = await createPerson(domain, db, userKEK, 'sven2@cloudflare.com')

			const activity = {
				'@context': 'https://www.w3.org/ns/activitystreams',
				type: 'Follow',
				actor: actor2.id.toString(),
				object: actor.id.toString(),
			}

			await activityHandler.handle(domain, activity, db, userKEK, adminEmail, vapidKeys)

			const row = await db