diff --git a/apps/server/package.json b/apps/server/package.json index cabff6df..03cb57bf 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -169,23 +169,7 @@ "rootDir": "src", "testRegex": ".*\\.spec\\.ts$", "testPathIgnorePatterns": [ - "/node_modules/", - "/core/auth/auth.controller.spec.ts", - "/core/auth/services/auth.service.spec.ts", - "/core/auth/services/token.service.spec.ts", - "/core/comment/comment.service.spec.ts", - "/core/group/group.controller.spec.ts", - "/core/group/services/group.service.spec.ts", - "/core/page/page.controller.spec.ts", - "/core/page/services/page.service.spec.ts", - "/core/search/search.controller.spec.ts", - "/core/search/search.service.spec.ts", - "/core/space/services/space.service.spec.ts", - "/core/space/space.controller.spec.ts", - "/core/user/user.controller.spec.ts", - "/core/workspace/services/workspace.service.spec.ts", - "/integrations/environment/environment.service.spec.ts", - "/integrations/storage/storage.service.spec.ts" + "/node_modules/" ], "transform": { "happy-dom.+\\.js$": [ @@ -206,7 +190,7 @@ "^.+\\.(t|j)sx?$": "ts-jest" }, "transformIgnorePatterns": [ - "/node_modules/(?!(\\.pnpm/)?(nanoid|uuid|image-dimensions|marked|happy-dom)(@|/))" + "/node_modules/(?!(\\.pnpm/)?(nanoid|uuid|image-dimensions|marked|happy-dom|lib0)(@|/))" ], "collectCoverageFrom": [ "**/*.(t|j)s" diff --git a/apps/server/src/core/ai-chat/public-share-chat.spec.ts b/apps/server/src/core/ai-chat/public-share-chat.spec.ts index 2be6a5f4..6cc9039a 100644 --- a/apps/server/src/core/ai-chat/public-share-chat.spec.ts +++ b/apps/server/src/core/ai-chat/public-share-chat.spec.ts @@ -477,11 +477,10 @@ describe('PublicShareWorkspaceLimiter (cluster-wide sliding-window per-workspace expect(await limiter.tryConsume('ws-1')).toBe(true); }); - it('FAILS OPEN (returns true) when the Redis eval rejects', async () => { - // The per-workspace cap is a COST backstop, not an access boundary: the - // funnel access gates and the per-IP throttle still apply. A transient - // Redis failure must therefore ADMIT the call (true) rather than 500/429, - // so a Redis blip cannot take the public-share assistant fully offline. + it('FAILS CLOSED (returns false) when the Redis eval rejects', async () => { + // FAIL CLOSED (#62): if Redis is down we cannot prove the workspace is under + // its cap, so DENY (the controller 429s) rather than admit an unmetered, + // billable anonymous call. The feature is optional, so denial is harmless. const failingRedis = { eval: () => Promise.reject(new Error('redis down')), } as unknown as import('ioredis').Redis; @@ -495,7 +494,7 @@ describe('PublicShareWorkspaceLimiter (cluster-wide sliding-window per-workspace const errSpy = jest .spyOn(Logger.prototype, 'error') .mockImplementation(() => undefined); - expect(await limiter.tryConsume('ws-1')).toBe(true); + expect(await limiter.tryConsume('ws-1')).toBe(false); expect(errSpy).toHaveBeenCalled(); // the failure MUST be logged, not swallowed errSpy.mockRestore(); }); diff --git a/apps/server/src/core/auth/auth.controller.spec.ts b/apps/server/src/core/auth/auth.controller.spec.ts index 27a31e61..4746f249 100644 --- a/apps/server/src/core/auth/auth.controller.spec.ts +++ b/apps/server/src/core/auth/auth.controller.spec.ts @@ -1,15 +1,19 @@ -import { Test, TestingModule } from '@nestjs/testing'; import { AuthController } from './auth.controller'; +// Direct instantiation with stub deps. The Test.createTestingModule form failed +// to resolve the injected dependency tokens (e.g. AUDIT_SERVICE) at compile(), +// and this smoke test only needs the controller to construct. describe('AuthController', () => { let controller: AuthController; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [AuthController], - }).compile(); - - controller = module.get(AuthController); + beforeEach(() => { + controller = new AuthController( + {} as any, // authService + {} as any, // sessionService + {} as any, // environmentService + {} as any, // moduleRef + {} as any, // auditService + ); }); it('should be defined', () => { diff --git a/apps/server/src/core/auth/services/auth.service.spec.ts b/apps/server/src/core/auth/services/auth.service.spec.ts index 800ab662..797431cb 100644 --- a/apps/server/src/core/auth/services/auth.service.spec.ts +++ b/apps/server/src/core/auth/services/auth.service.spec.ts @@ -1,15 +1,25 @@ -import { Test, TestingModule } from '@nestjs/testing'; import { AuthService } from './auth.service'; +// Direct instantiation with stub deps. The Test.createTestingModule form failed +// to resolve the @InjectKysely() connection token (and AUDIT_SERVICE) at +// compile(); this smoke test only needs the service to construct. describe('AuthService', () => { let service: AuthService; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [AuthService], - }).compile(); - - service = module.get(AuthService); + beforeEach(() => { + service = new AuthService( + {} as any, // signupService + {} as any, // tokenService + {} as any, // sessionService + {} as any, // userSessionRepo + {} as any, // userRepo + {} as any, // userTokenRepo + {} as any, // mailService + {} as any, // domainService + {} as any, // environmentService + {} as any, // db + {} as any, // auditService + ); }); it('should be defined', () => { diff --git a/apps/server/src/core/auth/services/token.service.spec.ts b/apps/server/src/core/auth/services/token.service.spec.ts index a5f5d655..b298ebd3 100644 --- a/apps/server/src/core/auth/services/token.service.spec.ts +++ b/apps/server/src/core/auth/services/token.service.spec.ts @@ -1,15 +1,14 @@ -import { Test, TestingModule } from '@nestjs/testing'; import { TokenService } from './token.service'; +// Direct instantiation with stub deps, mirroring the rest of these unit specs. describe('TokenService', () => { let service: TokenService; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [TokenService], - }).compile(); - - service = module.get(TokenService); + beforeEach(() => { + service = new TokenService( + {} as any, // jwtService + {} as any, // environmentService + ); }); it('should be defined', () => { diff --git a/apps/server/src/core/comment/comment.service.spec.ts b/apps/server/src/core/comment/comment.service.spec.ts index 0f57aec2..9384a2b8 100644 --- a/apps/server/src/core/comment/comment.service.spec.ts +++ b/apps/server/src/core/comment/comment.service.spec.ts @@ -1,15 +1,20 @@ -import { Test, TestingModule } from '@nestjs/testing'; import { CommentService } from './comment.service'; +// Direct instantiation with stub deps. The Test.createTestingModule form failed +// to resolve the @InjectQueue() tokens at compile(), and this smoke test only +// needs the service to construct. describe('CommentService', () => { let service: CommentService; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [CommentService], - }).compile(); - - service = module.get(CommentService); + beforeEach(() => { + service = new CommentService( + {} as any, // commentRepo + {} as any, // pageRepo + {} as any, // wsService + {} as any, // collaborationGateway + {} as any, // generalQueue + {} as any, // notificationQueue + ); }); it('should be defined', () => { diff --git a/apps/server/src/core/group/group.controller.spec.ts b/apps/server/src/core/group/group.controller.spec.ts index 0a68f0cd..663b70cc 100644 --- a/apps/server/src/core/group/group.controller.spec.ts +++ b/apps/server/src/core/group/group.controller.spec.ts @@ -1,17 +1,15 @@ -import { Test, TestingModule } from '@nestjs/testing'; import { GroupController } from './group.controller'; -import { GroupService } from './services/group.service'; +// Direct instantiation with stub deps, mirroring the rest of these unit specs. describe('GroupController', () => { let controller: GroupController; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [GroupController], - providers: [GroupService], - }).compile(); - - controller = module.get(GroupController); + beforeEach(() => { + controller = new GroupController( + {} as any, // groupService + {} as any, // groupUserService + {} as any, // workspaceAbility + ); }); it('should be defined', () => { diff --git a/apps/server/src/core/group/services/group.service.spec.ts b/apps/server/src/core/group/services/group.service.spec.ts index 495dd796..579a29d2 100644 --- a/apps/server/src/core/group/services/group.service.spec.ts +++ b/apps/server/src/core/group/services/group.service.spec.ts @@ -1,15 +1,22 @@ -import { Test, TestingModule } from '@nestjs/testing'; import { GroupService } from './group.service'; +// Direct instantiation with stub deps. The Test.createTestingModule form failed +// to resolve the @InjectKysely() connection token (and AUDIT_SERVICE) at +// compile(); this smoke test only needs the service to construct. describe('GroupService', () => { let service: GroupService; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [GroupService], - }).compile(); - - service = module.get(GroupService); + beforeEach(() => { + service = new GroupService( + {} as any, // groupRepo + {} as any, // groupUserRepo + {} as any, // spaceMemberRepo + {} as any, // groupUserService + {} as any, // watcherRepo + {} as any, // favoriteRepo + {} as any, // db + {} as any, // auditService + ); }); it('should be defined', () => { diff --git a/apps/server/src/core/page/page.controller.spec.ts b/apps/server/src/core/page/page.controller.spec.ts index b59a02c1..e369d51e 100644 --- a/apps/server/src/core/page/page.controller.spec.ts +++ b/apps/server/src/core/page/page.controller.spec.ts @@ -1,17 +1,23 @@ -import { Test, TestingModule } from '@nestjs/testing'; import { PageController } from './page.controller'; -import { PageService } from './services/page.service'; +// Direct instantiation with stub deps. The Test.createTestingModule form failed +// to resolve PageService's injected tokens at compile(), and this smoke test only +// needs the controller to construct. describe('PageController', () => { let controller: PageController; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [PageController], - providers: [PageService], - }).compile(); - - controller = module.get(PageController); + beforeEach(() => { + controller = new PageController( + {} as any, // pageService + {} as any, // pageRepo + {} as any, // workspaceRepo + {} as any, // pageHistoryService + {} as any, // spaceAbility + {} as any, // pageAccessService + {} as any, // backlinkService + {} as any, // labelService + {} as any, // auditService + ); }); it('should be defined', () => { diff --git a/apps/server/src/core/page/services/page.service.spec.ts b/apps/server/src/core/page/services/page.service.spec.ts index 7cadcb7f..c0d7dbc9 100644 --- a/apps/server/src/core/page/services/page.service.spec.ts +++ b/apps/server/src/core/page/services/page.service.spec.ts @@ -1,15 +1,27 @@ -import { Test, TestingModule } from '@nestjs/testing'; import { PageService } from './page.service'; +// Direct instantiation with stub deps. The Test.createTestingModule form failed +// to resolve the @InjectKysely()/@InjectQueue() tokens at compile(), and this +// smoke test only needs the service to construct. describe('PageService', () => { let service: PageService; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [PageService], - }).compile(); - - service = module.get(PageService); + beforeEach(() => { + service = new PageService( + {} as any, // pageRepo + {} as any, // pagePermissionRepo + {} as any, // attachmentRepo + {} as any, // db + {} as any, // storageService + {} as any, // attachmentQueue + {} as any, // aiQueue + {} as any, // generalQueue + {} as any, // eventEmitter + {} as any, // collaborationGateway + {} as any, // watcherService + {} as any, // transclusionService + {} as any, // workspaceRepo + ); }); it('should be defined', () => { diff --git a/apps/server/src/core/space/services/space.service.spec.ts b/apps/server/src/core/space/services/space.service.spec.ts index f97afbed..befdf06c 100644 --- a/apps/server/src/core/space/services/space.service.spec.ts +++ b/apps/server/src/core/space/services/space.service.spec.ts @@ -1,15 +1,22 @@ -import { Test, TestingModule } from '@nestjs/testing'; import { SpaceService } from './space.service'; +// Direct instantiation with stub deps. The Test.createTestingModule form failed +// to resolve the @InjectKysely()/@InjectQueue()/AUDIT_SERVICE tokens at compile(); +// this smoke test only needs the service to construct. describe('SpaceService', () => { let service: SpaceService; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [SpaceService], - }).compile(); - - service = module.get(SpaceService); + beforeEach(() => { + service = new SpaceService( + {} as any, // spaceRepo + {} as any, // spaceMemberService + {} as any, // shareRepo + {} as any, // workspaceRepo + {} as any, // licenseCheckService + {} as any, // db + {} as any, // attachmentQueue + {} as any, // auditService + ); }); it('should be defined', () => { diff --git a/apps/server/src/core/space/space.controller.spec.ts b/apps/server/src/core/space/space.controller.spec.ts index 4e7b9f87..4e11a012 100644 --- a/apps/server/src/core/space/space.controller.spec.ts +++ b/apps/server/src/core/space/space.controller.spec.ts @@ -1,17 +1,17 @@ -import { Test, TestingModule } from '@nestjs/testing'; import { SpaceController } from './space.controller'; -import { SpaceService } from './services/space.service'; +// Direct instantiation with stub deps, mirroring the rest of these unit specs. describe('SpaceController', () => { let controller: SpaceController; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [SpaceController], - providers: [SpaceService], - }).compile(); - - controller = module.get(SpaceController); + beforeEach(() => { + controller = new SpaceController( + {} as any, // spaceService + {} as any, // spaceMemberService + {} as any, // spaceMemberRepo + {} as any, // spaceAbility + {} as any, // workspaceAbility + ); }); it('should be defined', () => { diff --git a/apps/server/src/core/user/user.controller.spec.ts b/apps/server/src/core/user/user.controller.spec.ts index 1f38440d..cb0429ab 100644 --- a/apps/server/src/core/user/user.controller.spec.ts +++ b/apps/server/src/core/user/user.controller.spec.ts @@ -1,17 +1,14 @@ -import { Test, TestingModule } from '@nestjs/testing'; import { UserController } from './user.controller'; -import { UserService } from './user.service'; +// Direct instantiation with stub deps, mirroring the rest of these unit specs. describe('UserController', () => { let controller: UserController; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - controllers: [UserController], - providers: [UserService], - }).compile(); - - controller = module.get(UserController); + beforeEach(() => { + controller = new UserController( + {} as any, // userService + {} as any, // workspaceRepo + ); }); it('should be defined', () => { diff --git a/apps/server/src/core/workspace/services/workspace.service.spec.ts b/apps/server/src/core/workspace/services/workspace.service.spec.ts index 0f544349..bd35e296 100644 --- a/apps/server/src/core/workspace/services/workspace.service.spec.ts +++ b/apps/server/src/core/workspace/services/workspace.service.spec.ts @@ -1,15 +1,32 @@ -import { Test, TestingModule } from '@nestjs/testing'; import { WorkspaceService } from './workspace.service'; +// Direct instantiation with stub deps. The Test.createTestingModule form failed +// to resolve the @InjectKysely()/@InjectQueue()/AUDIT_SERVICE tokens at compile(); +// this smoke test only needs the service to construct. describe('WorkspaceService', () => { let service: WorkspaceService; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [WorkspaceService], - }).compile(); - - service = module.get(WorkspaceService); + beforeEach(() => { + service = new WorkspaceService( + {} as any, // workspaceRepo + {} as any, // spaceService + {} as any, // spaceMemberService + {} as any, // groupRepo + {} as any, // groupUserRepo + {} as any, // userRepo + {} as any, // environmentService + {} as any, // domainService + {} as any, // licenseCheckService + {} as any, // shareRepo + {} as any, // watcherRepo + {} as any, // favoriteRepo + {} as any, // db + {} as any, // attachmentQueue + {} as any, // billingQueue + {} as any, // aiQueue + {} as any, // auditService + {} as any, // userSessionRepo + ); }); it('should be defined', () => { diff --git a/apps/server/src/integrations/environment/environment.service.spec.ts b/apps/server/src/integrations/environment/environment.service.spec.ts index cd2ad4bb..efef25b0 100644 --- a/apps/server/src/integrations/environment/environment.service.spec.ts +++ b/apps/server/src/integrations/environment/environment.service.spec.ts @@ -1,15 +1,14 @@ -import { Test, TestingModule } from '@nestjs/testing'; import { EnvironmentService } from './environment.service'; +// Direct instantiation with a stub ConfigService, mirroring the rest of these +// unit specs. describe('EnvironmentService', () => { let service: EnvironmentService; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [EnvironmentService], - }).compile(); - - service = module.get(EnvironmentService); + beforeEach(() => { + service = new EnvironmentService( + {} as any, // configService + ); }); it('should be defined', () => { diff --git a/apps/server/src/integrations/storage/storage.service.spec.ts b/apps/server/src/integrations/storage/storage.service.spec.ts index 0b277788..79db48c0 100644 --- a/apps/server/src/integrations/storage/storage.service.spec.ts +++ b/apps/server/src/integrations/storage/storage.service.spec.ts @@ -1,15 +1,15 @@ -import { Test, TestingModule } from '@nestjs/testing'; import { StorageService } from './storage.service'; +// Direct instantiation with a stub driver. The Test.createTestingModule form +// failed to resolve the STORAGE_DRIVER_TOKEN at compile(); this smoke test only +// needs the service to construct. describe('StorageService', () => { let service: StorageService; - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [StorageService], - }).compile(); - - service = module.get(StorageService); + beforeEach(() => { + service = new StorageService( + {} as any, // storageDriver + ); }); it('should be defined', () => {