Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,090 changes: 2,310 additions & 780 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions packages/devtools/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
projects: [
'<rootDir>/frigg-cli/jest.config.js',
'<rootDir>/infrastructure/jest.config.js',
],
};
204 changes: 204 additions & 0 deletions packages/e2e/__tests__/edge-cases/error-scenarios.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
const request = require('supertest');
const { TestServer } = require('../helpers/test-server');
const { createFixture } = require('../helpers/fixtures');

describe('Error Scenarios', () => {
let server;
let app;
let fixture;

beforeAll(async () => {
server = new TestServer();
await server.start();
app = server.getApp();
});

afterAll(async () => {
await server.stop();
});

beforeEach(() => {
fixture = createFixture(app);
});

describe('Authentication Errors', () => {
it('should return 401 for missing authorization header', async () => {
const res = await request(app).get('/api/integrations');
expect(res.status).toBe(401);
});

it('should return 401 for invalid token format', async () => {
const res = await request(app)
.get('/api/integrations')
.set('Authorization', 'InvalidFormat');
expect(res.status).toBe(401);
});

it('should return 401 for nonexistent user token', async () => {
const res = await request(app)
.get('/api/integrations')
.set('Authorization', 'Bearer nonexistent-user-id');
expect(res.status).toBe(401);
});
});

describe('Authorization Errors', () => {
it('should reject unknown entity type', async () => {
const { userId, token } = await fixture.createUser();

Check warning on line 47 in packages/e2e/__tests__/edge-cases/error-scenarios.test.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this useless assignment to variable "token".

See more on https://sonarcloud.io/project/issues?id=friggframework_frigg&issues=AZ09D4kqmfd6IM4TE-iX&open=AZ09D4kqmfd6IM4TE-iX&pullRequest=565

Check warning on line 47 in packages/e2e/__tests__/edge-cases/error-scenarios.test.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the declaration of the unused 'token' variable.

See more on https://sonarcloud.io/project/issues?id=friggframework_frigg&issues=AZ09D4kqmfd6IM4TE-iW&open=AZ09D4kqmfd6IM4TE-iW&pullRequest=565

const res = await request(app)
.get('/api/authorize')
.query({ entityType: 'unknown-entity-type' })
.set('Authorization', `Bearer ${userId}`);

expect(res.status).toBe(400);
});

it('should reject authorization without entity type', async () => {
const { userId, token } = await fixture.createUser();

Check warning on line 58 in packages/e2e/__tests__/edge-cases/error-scenarios.test.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the declaration of the unused 'token' variable.

See more on https://sonarcloud.io/project/issues?id=friggframework_frigg&issues=AZ09D4kqmfd6IM4TE-iY&open=AZ09D4kqmfd6IM4TE-iY&pullRequest=565

Check warning on line 58 in packages/e2e/__tests__/edge-cases/error-scenarios.test.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this useless assignment to variable "token".

See more on https://sonarcloud.io/project/issues?id=friggframework_frigg&issues=AZ09D4kqmfd6IM4TE-iZ&open=AZ09D4kqmfd6IM4TE-iZ&pullRequest=565

const res = await request(app)
.get('/api/authorize')
.set('Authorization', `Bearer ${userId}`);

expect(res.status).toBe(400);
});
});

describe('Integration Errors', () => {
it('should reject creating integration without entities', async () => {
const { token } = await fixture.createUser();

const res = await request(app)
.post('/api/integrations')
.set('Authorization', `Bearer ${token}`)
.send({
entities: [],
config: { type: 'oauth-integration' },
});

expect(res.status).toBe(400);
});

it('should reject creating integration with nonexistent entity', async () => {
const { token } = await fixture.createUser();

const res = await request(app)
.post('/api/integrations')
.set('Authorization', `Bearer ${token}`)
.send({
entities: ['nonexistent-entity-id'],
config: { type: 'oauth-integration' },
});

expect(res.status).toBe(400);
});

it('should reject creating integration without config type', async () => {
const { userId, token } = await fixture.createUser();
const { entityId } = await fixture.createOAuthEntity(userId);

const res = await request(app)
.post('/api/integrations')
.set('Authorization', `Bearer ${token}`)
.send({
entities: [entityId],
config: {},
});

expect(res.status).toBe(400);
});
});

describe('Resource Not Found', () => {
it('should return 404 for nonexistent integration', async () => {
const { token } = await fixture.createUser();

const res = await request(app)
.get('/api/integrations/507f1f77bcf86cd799439011')
.set('Authorization', `Bearer ${token}`);

expect(res.status).toBe(404);
});

it('should return 404 for nonexistent entity', async () => {
const { token } = await fixture.createUser();

const res = await request(app)
.get('/api/entities/507f1f77bcf86cd799439011')
.set('Authorization', `Bearer ${token}`);

expect(res.status).toBe(404);
});
});

describe('Malformed Requests', () => {
it('should handle malformed JSON body gracefully', async () => {
const { token } = await fixture.createUser();

const res = await request(app)
.post('/api/integrations')
.set('Authorization', `Bearer ${token}`)
.set('Content-Type', 'application/json')
.send('{invalid json}');

expect(res.status).toBe(400);
});

it('should handle empty body gracefully', async () => {
const { userId, token } = await fixture.createUser();
const { entityId } = await fixture.createOAuthEntity(userId);

const res = await request(app)
.patch(`/api/integrations/${entityId}`)
.set('Authorization', `Bearer ${token}`)
.send({});

expect([200, 400]).toContain(res.status);
});
});

describe('Concurrent Operations', () => {
it('should handle concurrent entity creation', async () => {
const { userId, token } = await fixture.createUser();

Check warning on line 163 in packages/e2e/__tests__/edge-cases/error-scenarios.test.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this useless assignment to variable "userId".

See more on https://sonarcloud.io/project/issues?id=friggframework_frigg&issues=AZ09D4kqmfd6IM4TE-ib&open=AZ09D4kqmfd6IM4TE-ib&pullRequest=565

Check warning on line 163 in packages/e2e/__tests__/edge-cases/error-scenarios.test.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the declaration of the unused 'userId' variable.

See more on https://sonarcloud.io/project/issues?id=friggframework_frigg&issues=AZ09D4kqmfd6IM4TE-ia&open=AZ09D4kqmfd6IM4TE-ia&pullRequest=565

const promises = Array(5).fill(null).map(() =>

Check warning on line 165 in packages/e2e/__tests__/edge-cases/error-scenarios.test.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use `new Array()` instead of `Array()`.

See more on https://sonarcloud.io/project/issues?id=friggframework_frigg&issues=AZ09D4kqmfd6IM4TE-ic&open=AZ09D4kqmfd6IM4TE-ic&pullRequest=565
request(app)
.post('/api/authorize')
.set('Authorization', `Bearer ${token}`)
.send({
entityType: 'oauth2-mock',
data: { code: `code-${Date.now()}-${Math.random()}` },
})
);

const results = await Promise.all(promises);
results.forEach((res) => {
expect(res.status).toBe(200);
});
});

it('should handle concurrent integration creation', async () => {
const { userId, token } = await fixture.createUser();

const entities = await Promise.all(
Array(3).fill(null).map(() => fixture.createOAuthEntity(userId))

Check warning on line 185 in packages/e2e/__tests__/edge-cases/error-scenarios.test.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use `new Array()` instead of `Array()`.

See more on https://sonarcloud.io/project/issues?id=friggframework_frigg&issues=AZ09D4kqmfd6IM4TE-ie&open=AZ09D4kqmfd6IM4TE-ie&pullRequest=565
);

const promises = entities.map(({ entityId }) =>
request(app)
.post('/api/integrations')
.set('Authorization', `Bearer ${token}`)
.send({
entities: [entityId],
config: { type: 'oauth-integration' },
})
);

const results = await Promise.all(promises);
results.forEach((res) => {
expect(res.status).toBe(201);
});
});
});
});
143 changes: 143 additions & 0 deletions packages/e2e/__tests__/edge-cases/user-scenarios.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
const request = require('supertest');
const { TestServer } = require('../helpers/test-server');
const { createFixture } = require('../helpers/fixtures');

describe('User Scenarios', () => {
let server;
let app;
let fixture;

beforeAll(async () => {
server = new TestServer();
await server.start();
app = server.getApp();
});

afterAll(async () => {
await server.stop();
});

beforeEach(() => {
fixture = createFixture(app);
});

describe('User Creation', () => {
it('should create a new user', async () => {
const res = await request(app)
.post('/user/create')
.send({
username: `newuser-${Date.now()}@example.com`,
password: 'securepass123',
});

expect(res.status).toBe(200);
expect(res.body).toHaveProperty('user');
expect(res.body.user).toHaveProperty('id');
});

it('should reject duplicate username', async () => {
const username = `duplicate-${Date.now()}@example.com`;

await request(app)
.post('/user/create')
.send({ username, password: 'password123' });

const res = await request(app)
.post('/user/create')
.send({ username, password: 'password456' });

expect(res.status).toBe(400);
});

it('should reject missing username', async () => {
const res = await request(app)
.post('/user/create')
.send({ password: 'password123' });

expect(res.status).toBe(400);
});

it('should reject missing password', async () => {
const res = await request(app)
.post('/user/create')
.send({ username: 'test@example.com' });

expect(res.status).toBe(400);
});
});

describe('User Login', () => {
it('should login with correct credentials', async () => {
const username = `login-${Date.now()}@example.com`;
const password = 'correctpassword';

await request(app)
.post('/user/create')
.send({ username, password });

const res = await request(app)
.post('/user/login')
.send({ username, password });

expect(res.status).toBe(200);
expect(res.body).toHaveProperty('token');
});

it('should reject incorrect password', async () => {
const username = `wrongpass-${Date.now()}@example.com`;

await request(app)
.post('/user/create')
.send({ username, password: 'correctpassword' });

const res = await request(app)
.post('/user/login')
.send({ username, password: 'wrongpassword' });

expect(res.status).toBe(401);
});

it('should reject nonexistent user', async () => {
const res = await request(app)
.post('/user/login')
.send({
username: 'nonexistent@example.com',
password: 'anypassword',
});

expect(res.status).toBe(401);
});
});

describe('User Session', () => {
it('should maintain user context across requests', async () => {
const { userId, token } = await fixture.createUser();
const { entityId } = await fixture.createOAuthEntity(userId);

const getEntitiesRes = await request(app)
.get('/api/entities')
.set('Authorization', `Bearer ${token}`);

expect(getEntitiesRes.status).toBe(200);
expect(getEntitiesRes.body.entities.some((e) => e.id === entityId)).toBe(true);
});

it('should isolate user data between users', async () => {
const { userId: user1Id, token: token1 } = await fixture.createUser();
const { token: token2 } = await fixture.createUser();

await fixture.createOAuthEntity(user1Id);

const user1Entities = await request(app)
.get('/api/entities')
.set('Authorization', `Bearer ${token1}`);

const user2Entities = await request(app)
.get('/api/entities')
.set('Authorization', `Bearer ${token2}`);

expect(user1Entities.body.entities.length).toBeGreaterThan(0);
expect(user2Entities.body.entities).toHaveLength(0);
});
});
});
Loading
Loading