From cd5615d3549e7b46d670b863e77e66a32de80da9 Mon Sep 17 00:00:00 2001
From: tamaina <tamaina@hotmail.co.jp>
Date: Sat, 18 Feb 2023 14:11:45 +0000
Subject: [PATCH 1/2] fix lint

---
 packages/sw/src/scripts/create-notification.ts | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/packages/sw/src/scripts/create-notification.ts b/packages/sw/src/scripts/create-notification.ts
index 14f96816a3..da92b37d19 100644
--- a/packages/sw/src/scripts/create-notification.ts
+++ b/packages/sw/src/scripts/create-notification.ts
@@ -14,7 +14,7 @@ const closeNotificationsByTags = async (tags: string[]) => {
 	for (const n of (await Promise.all(tags.map(tag => globalThis.registration.getNotifications({ tag })))).flat()) {
 		n.close();
 	}
-}
+};
 
 const iconUrl = (name: badgeNames) => `/static-assets/tabler-badges/${name}.png`;
 /* How to add a new badge:
@@ -183,11 +183,10 @@ async function composeNotification(data: pushNotificationDataMap[keyof pushNotif
 				}
 
 				case 'pollEnded':
-					const tag = `poll:${data.body.note.id}`;
 					return [t('_notification.pollEnded'), {
 						body: data.body.note.text || '',
 						badge: iconUrl('chart-arrows'),
-						tag,
+						tag: `poll:${data.body.note.id}`,
 						data,
 					}];
 
@@ -228,12 +227,11 @@ async function composeNotification(data: pushNotificationDataMap[keyof pushNotif
 					return null;
 			}
 		case 'unreadAntennaNote':
-			const tag = `antenna:${data.body.antenna.id}`;
 			return [t('_notification.unreadAntennaNote', { name: data.body.antenna.name }), {
 				body: `${getUserName(data.body.note.user)}: ${data.body.note.text ?? ''}`,
 				icon: data.body.note.user.avatarUrl,
 				badge: iconUrl('antenna'),
-				tag,
+				tag: `antenna:${data.body.antenna.id}`,
 				data,
 				renotify: true,
 			}];

From 2aa73fdf6c91f6f1ec01c5d50d046f2e6e970faf Mon Sep 17 00:00:00 2001
From: Kagami Sascha Rosylight <saschanaz@outlook.com>
Date: Sun, 19 Feb 2023 07:27:14 +0100
Subject: [PATCH 2/2] test(backend): restore AP unit tests (#9987)

---
 packages/backend/test/misc/mock-resolver.ts   | 34 ++++++++++++-
 .../test/{tests => unit}/activitypub.ts       | 49 +++++++++++++------
 2 files changed, 66 insertions(+), 17 deletions(-)
 rename packages/backend/test/{tests => unit}/activitypub.ts (56%)

diff --git a/packages/backend/test/misc/mock-resolver.ts b/packages/backend/test/misc/mock-resolver.ts
index 9efed267ea..6b31e68616 100644
--- a/packages/backend/test/misc/mock-resolver.ts
+++ b/packages/backend/test/misc/mock-resolver.ts
@@ -1,5 +1,16 @@
-import Resolver from '../../src/activitypub/resolver.js';
-import { IObject } from '../../src/activitypub/type.js';
+import type { Config } from '@/config.js';
+import type { ApDbResolverService } from '@/core/activitypub/ApDbResolverService.js';
+import type { ApRendererService } from '@/core/activitypub/ApRendererService.js';
+import type { ApRequestService } from '@/core/activitypub/ApRequestService.js';
+import { Resolver } from '@/core/activitypub/ApResolverService.js';
+import type { IObject } from '@/core/activitypub/type.js';
+import type { HttpRequestService } from '@/core/HttpRequestService.js';
+import type { InstanceActorService } from '@/core/InstanceActorService.js';
+import type { LoggerService } from '@/core/LoggerService.js';
+import type { MetaService } from '@/core/MetaService.js';
+import type { UtilityService } from '@/core/UtilityService.js';
+import { bindThis } from '@/decorators.js';
+import type { NoteReactionsRepository, NotesRepository, PollsRepository, UsersRepository } from '@/models/index.js';
 
 type MockResponse = {
 	type: string;
@@ -8,6 +19,25 @@ type MockResponse = {
 
 export class MockResolver extends Resolver {
 	private _rs = new Map<string, MockResponse>();
+
+	constructor(loggerService: LoggerService) {
+		super(
+			{} as Config,
+			{} as UsersRepository,
+			{} as NotesRepository,
+			{} as PollsRepository,
+			{} as NoteReactionsRepository,
+			{} as UtilityService,
+			{} as InstanceActorService,
+			{} as MetaService,
+			{} as ApRequestService,
+			{} as HttpRequestService,
+			{} as ApRendererService,
+			{} as ApDbResolverService,
+			loggerService,
+		);
+	}
+
 	public async _register(uri: string, content: string | Record<string, any>, type = 'application/activity+json') {
 		this._rs.set(uri, {
 			type,
diff --git a/packages/backend/test/tests/activitypub.ts b/packages/backend/test/unit/activitypub.ts
similarity index 56%
rename from packages/backend/test/tests/activitypub.ts
rename to packages/backend/test/unit/activitypub.ts
index 19fb5d90d7..3d0032507e 100644
--- a/packages/backend/test/tests/activitypub.ts
+++ b/packages/backend/test/unit/activitypub.ts
@@ -2,8 +2,39 @@ process.env.NODE_ENV = 'test';
 
 import * as assert from 'assert';
 import rndstr from 'rndstr';
+import { Test } from '@nestjs/testing';
+import { jest } from '@jest/globals';
+
+import { ApNoteService } from '@/core/activitypub/models/ApNoteService.js';
+import { ApPersonService } from '@/core/activitypub/models/ApPersonService.js';
+import { GlobalModule } from '@/GlobalModule.js';
+import { CoreModule } from '@/core/CoreModule.js';
+import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
+import { LoggerService } from '@/core/LoggerService.js';
+import { MockResolver } from '../misc/mock-resolver.js';
 
 describe('ActivityPub', () => {
+	let noteService: ApNoteService;
+	let personService: ApPersonService;
+	let resolver: MockResolver;
+
+	beforeEach(async () => {
+		const app = await Test.createTestingModule({
+			imports: [GlobalModule, CoreModule],
+		}).compile();
+
+		await app.init();
+		app.enableShutdownHooks();
+
+		noteService = app.get<ApNoteService>(ApNoteService);
+		personService = app.get<ApPersonService>(ApPersonService);
+		resolver = new MockResolver(await app.resolve<LoggerService>(LoggerService));
+
+		// Prevent ApPersonService from fetching instance, as it causes Jest import-after-test error
+		const federatedInstanceService = app.get<FederatedInstanceService>(FederatedInstanceService);
+		jest.spyOn(federatedInstanceService, 'fetch').mockImplementation(() => new Promise(() => {}));
+	});
+
 	describe('Parse minimum object', () => {
 		const host = 'https://host1.test';
 		const preferredUsername = `${rndstr('A-Z', 4)}${rndstr('a-z', 4)}`;
@@ -28,13 +59,9 @@ describe('ActivityPub', () => {
 		};
 
 		test('Minimum Actor', async () => {
-			const { MockResolver } = await import('../misc/mock-resolver.js');
-			const { createPerson } = await import('../../src/activitypub/models/person.js');
-
-			const resolver = new MockResolver();
 			resolver._register(actor.id, actor);
 
-			const user = await createPerson(actor.id, resolver);
+			const user = await personService.createPerson(actor.id, resolver);
 
 			assert.deepStrictEqual(user.uri, actor.id);
 			assert.deepStrictEqual(user.username, actor.preferredUsername);
@@ -42,14 +69,10 @@ describe('ActivityPub', () => {
 		});
 
 		test('Minimum Note', async () => {
-			const { MockResolver } = await import('../misc/mock-resolver.js');
-			const { createNote } = await import('../../src/activitypub/models/note.js');
-
-			const resolver = new MockResolver();
 			resolver._register(actor.id, actor);
 			resolver._register(post.id, post);
 
-			const note = await createNote(post.id, resolver, true);
+			const note = await noteService.createNote(post.id, resolver, true);
 
 			assert.deepStrictEqual(note?.uri, post.id);
 			assert.deepStrictEqual(note.visibility, 'public');
@@ -75,13 +98,9 @@ describe('ActivityPub', () => {
 		};
 
 		test('Actor', async () => {
-			const { MockResolver } = await import('../misc/mock-resolver.js');
-			const { createPerson } = await import('../../src/activitypub/models/person.js');
-
-			const resolver = new MockResolver();
 			resolver._register(actor.id, actor);
 
-			const user = await createPerson(actor.id, resolver);
+			const user = await personService.createPerson(actor.id, resolver);
 
 			assert.deepStrictEqual(user.name, actor.name.substr(0, 128));
 		});