Skip to content

LAU-27: add integration tests for auth and workspace resolvers#23

Merged
dkarasiewicz merged 5 commits intomainfrom
feature/lau-27-add-integration-test-for-main-assistant-flow
Jan 24, 2026
Merged

LAU-27: add integration tests for auth and workspace resolvers#23
dkarasiewicz merged 5 commits intomainfrom
feature/lau-27-add-integration-test-for-main-assistant-flow

Conversation

@dkarasiewicz
Copy link
Owner

Summary

Added basic integration test.

Related issue(s)

  • Fixes / Relates to: LAU-27

Type of change

  • Bugfix
  • New feature
  • Documentation
  • Refactor
  • Tests
  • Other (please describe):

Component

  • Core application (BSL 1.1)
  • SDK / client library (MIT)
  • Documentation

Description

n/a

How to test

n/a

Checklist

  • I added tests that cover my changes (if applicable)
  • I ran linting and type checks locally
  • I updated relevant documentation / README
  • I added or updated changelog/release notes (if required)
  • I followed the collaboration guidelines: ./CONTRIBUTING.md
  • I understand my contribution is licensed under BSL 1.1 (core) or MIT (SDKs)

Screenshots (if UI)

Release notes

Short note for changelog/release (one line).

Copilot AI review requested due to automatic review settings January 23, 2026 19:50
@dkarasiewicz dkarasiewicz self-assigned this Jan 23, 2026
@linear
Copy link

linear bot commented Jan 23, 2026

@vercel
Copy link

vercel bot commented Jan 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
v0-landing-page-copy Ready Ready Preview, Comment Jan 24, 2026 1:12am

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds integration tests for authentication and workspace GraphQL resolvers and REST endpoints. The tests use supertest for HTTP assertions and mock modules to isolate external dependencies like Redis, EventBus, and Analytics.

Changes:

  • Added supertest as a dev dependency for HTTP integration testing
  • Created mock modules for testing infrastructure (DB, Redis, EventBus, Config, Analytics, Common, Auth)
  • Added comprehensive integration tests for auth controller (OTP send/verify, current user)
  • Added comprehensive integration tests for workspace resolver (getWorkspace, inviteWorkspaceMember, getInvite, redeemInvite)
  • Removed placeholder e2e test and cleaned up global setup/teardown files

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
package.json Added supertest dependency for HTTP integration testing
pnpm-lock.yaml Lock file updates for supertest and its transitive dependencies
apps/core-e2e/src/support/redis.module.mock.ts Mock Redis PubSub provider for testing
apps/core-e2e/src/support/eventbus.module.mock.ts Mock EventBus service for testing
apps/core-e2e/src/support/db.module.mock.ts Mock database connection using real Postgres for integration tests
apps/core-e2e/src/support/config.module.mock.ts Mock ConfigService that returns default values
apps/core-e2e/src/support/common.module.mock.ts Mock common module with validation pipe, auth guard, and interceptor
apps/core-e2e/src/support/auth.guard.mock.ts Mock auth guard that extracts user from Bearer token
apps/core-e2e/src/support/analytics.module.mock.ts Mock analytics client for testing
apps/core-e2e/src/support/global-setup.ts Removed server wait logic from global setup
apps/core-e2e/src/support/global-teardown.ts Removed port cleanup from global teardown
apps/core-e2e/src/core/auth.controller.spec.ts Integration tests for auth endpoints (sendOtp, verifyOtp, currentUser)
apps/core-e2e/src/core/workspace.resolver.spec.ts Integration tests for workspace GraphQL operations
apps/core-e2e/src/core/core.spec.ts Removed placeholder test file
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 17 changed files in this pull request and generated 12 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +115 to +117
afterAll(async () => {
await db.$client.end();
await app.close();
Copy link

Copilot AI Jan 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The database connection pool is closed in afterAll, but if any async operations are still running when the connection pool is closed, they could fail silently or cause errors. Consider using a more graceful shutdown pattern that ensures all pending operations complete before closing the connection.

Copilot uses AI. Check for mistakes.
},
},
});

Copy link

Copilot AI Jan 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the redeemInvite test, this test doesn't verify that the invitation was created successfully before attempting to retrieve it. The token value could be undefined. Consider adding an assertion after line 255 to verify createInviteRes.status and createInviteRes.body.data.inviteWorkspaceMember exist.

Suggested change
expect(createInviteRes.status).toBe(200);
expect(createInviteRes.body).toBeDefined();
expect(createInviteRes.body.data).toBeDefined();
expect(createInviteRes.body.data.inviteWorkspaceMember).toBeDefined();

Copilot uses AI. Check for mistakes.
Comment on lines +109 to +112
await db.$client.query('TRUNCATE TABLE "WorkspaceInvite" CASCADE;');
await db.$client.query('TRUNCATE TABLE "WorkspaceMembership" CASCADE;');
await db.$client.query('TRUNCATE TABLE "Workspace" CASCADE;');
await db.$client.query('TRUNCATE TABLE "User" CASCADE;');
Copy link

Copilot AI Jan 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Database cleanup is done using raw SQL TRUNCATE queries with CASCADE. While functional, this approach bypasses Drizzle ORM's type safety and could become inconsistent if table names change. Consider using Drizzle's delete API for type-safe cleanup or documenting why raw SQL is necessary here.

Copilot uses AI. Check for mistakes.
Comment on lines +94 to +95
await db.$client.query('TRUNCATE TABLE "Otp" CASCADE;');
await db.$client.query('TRUNCATE TABLE "User" CASCADE;');
Copy link

Copilot AI Jan 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Database cleanup is done using raw SQL TRUNCATE queries with CASCADE. While functional, this approach bypasses Drizzle ORM's type safety and could become inconsistent if table names change. Consider using Drizzle's delete API for type-safe cleanup or documenting why raw SQL is necessary here.

Suggested change
await db.$client.query('TRUNCATE TABLE "Otp" CASCADE;');
await db.$client.query('TRUNCATE TABLE "User" CASCADE;');
await db.delete(otp);
await db.delete(user);

Copilot uses AI. Check for mistakes.
Comment on lines +22 to +25
const emailForOtp = 'email-otp@example.com';
let app: INestApplication;
let db: NodePgDatabase & { $client: Pool };
let verifiedUser: typeof user.$inferSelect;
Copy link

Copilot AI Jan 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable 'emailForOtp' is declared but never used in the tests. It appears to have been intended for the 'should return 401 when user does not exist' test at line 208, but 'emailForOtp' was defined instead as a test-specific value. Consider removing this unused variable.

Suggested change
const emailForOtp = 'email-otp@example.com';
let app: INestApplication;
let db: NodePgDatabase & { $client: Pool };
let verifiedUser: typeof user.$inferSelect;
let app: INestApplication;
let db: NodePgDatabase & { $client: Pool };
let verifiedUser: typeof user.$inferSelect;
let verifiedUser: typeof user.$inferSelect;

Copilot uses AI. Check for mistakes.

/* eslint-disable */
var __TEARDOWN_MESSAGE__: string;

Copy link

Copilot AI Jan 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The typo 'that that' should be corrected to 'that' in this comment.

Suggested change
// Start services that the app needs to run (e.g. database, docker-compose, etc.).

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +18
return drizzle({
connection: {
user: process.env['DB_USERNAME'] as string,
password: process.env['DB_PASS'],
database: process.env['DB_DATABASE'],
host: process.env['DB_HOST'],
port: parseInt(process.env['DB_PORT'], 10),
Copy link

Copilot AI Jan 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The database configuration uses environment variables without validation or fallback values. If these environment variables are not set, the tests will fail with unclear errors. Consider adding validation or default values for test environments to make the tests more robust.

Suggested change
return drizzle({
connection: {
user: process.env['DB_USERNAME'] as string,
password: process.env['DB_PASS'],
database: process.env['DB_DATABASE'],
host: process.env['DB_HOST'],
port: parseInt(process.env['DB_PORT'], 10),
const {
DB_USERNAME = 'postgres',
DB_PASS = 'postgres',
DB_DATABASE = 'postgres',
DB_HOST = 'localhost',
DB_PORT = '5432',
} = process.env;
const port = Number.parseInt(DB_PORT, 10);
if (Number.isNaN(port)) {
throw new Error('Invalid DB_PORT environment variable: must be a number');
}
return drizzle({
connection: {
user: DB_USERNAME as string,
password: DB_PASS,
database: DB_DATABASE,
host: DB_HOST,
port,

Copilot uses AI. Check for mistakes.
Comment on lines 36 to 40
useValue: {
verify: {
services: jest.fn().mockReturnThis(),
verifications: {
create: jest.fn(),
},
capture: jest.fn(),
},
},
Copy link

Copilot AI Jan 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ANALYTICS_CLIENT mock has an incorrect structure. It provides verify.capture but PostHog's capture method is called directly (analyticsClient.capture). The mock should be { capture: jest.fn(), alias: jest.fn() } similar to the MockAnalyticsModule implementation, not nested under a verify property.

Copilot uses AI. Check for mistakes.
Comment on lines +39 to +66
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: true,
subscriptions: {
'graphql-ws': true,
},
}),
WorkspaceModule,
MockCommonModule,
MockConfigModule,
MockDbModule,
MockRedisModule,
MockEventBusModule,
MockAnalyticsModule,
],
})
.overrideProvider(MainAuthGuard)
.useClass(MockMainAuthGuard)
.compile();

app = moduleFixture.createNestApplication();
db = app.get(DB_CONNECTION);
eventBus = app.get(EventBusService);

await app.init();
Copy link

Copilot AI Jan 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test suite shares a single database connection pool across all tests, which could lead to test interference if tests run in parallel. Jest runs tests in parallel by default. Consider either configuring Jest to run these integration tests serially (using --runInBand or --maxWorkers=1) or creating separate database connections per test to ensure proper isolation.

Copilot uses AI. Check for mistakes.
},
});

expect(redeemedInviteRes.status).toBe(200);
Copy link

Copilot AI Jan 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test verifies that the redeemed invite returns null but doesn't check for errors. If the query failed, res.body.data could also be null due to an error rather than the invite being properly deleted. Consider asserting that res.body.errors is undefined or that the response structure indicates successful query execution with no data.

Suggested change
expect(redeemedInviteRes.status).toBe(200);
expect(redeemedInviteRes.status).toBe(200);
expect(redeemedInviteRes.body.errors).toBeUndefined();

Copilot uses AI. Check for mistakes.
@dkarasiewicz dkarasiewicz merged commit ac6c6b7 into main Jan 24, 2026
4 checks passed
@dkarasiewicz dkarasiewicz deleted the feature/lau-27-add-integration-test-for-main-assistant-flow branch January 24, 2026 01:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant