Initial push of Plunk Next

This commit is contained in:
Dries Augustyns
2025-12-01 09:56:56 +01:00
parent 07cea20262
commit ff1876d580
566 changed files with 89036 additions and 28423 deletions
@@ -0,0 +1,208 @@
import {describe, it, expect, beforeEach, beforeAll} from 'vitest';
import {CampaignStatus, CampaignAudienceType} from '@plunk/db';
import {factories, getPrismaClient} from '../../../../../test/helpers';
// Note: To run these integration tests, you need to:
// 1. Have the API server running or import the app instance
// 2. For now, these tests demonstrate the pattern for integration testing
describe('Campaigns API Integration Tests', () => {
let projectId: string;
let _authToken: string;
let _apiUrl: string;
const prisma = getPrismaClient();
beforeAll(() => {
// In a real setup, you'd either:
// 1. Import the Express app instance
// 2. Or use the actual API server URL
_apiUrl = process.env.TEST_API_URL || 'http://localhost:3000';
});
beforeEach(async () => {
const {project} = await factories.createUserWithProject();
projectId = project.id;
// Generate auth token (you'd need to implement this based on your auth system)
// This is a placeholder - adjust based on your actual auth implementation
_authToken = 'test-jwt-token';
});
describe('POST /campaigns', () => {
it('should create a new campaign', async () => {
const campaignData = {
name: 'Test Campaign',
subject: 'Test Subject',
body: '<p>Test Body</p>',
from: '[email protected]',
audienceType: CampaignAudienceType.ALL,
};
// Example of how the integration test would look
// Uncomment when you have the app instance available:
/*
const response = await request(app)
.post('/campaigns')
.set('Authorization', `Bearer ${authToken}`)
.send(campaignData)
.expect(201);
expect(response.body.name).toBe('Test Campaign');
expect(response.body.status).toBe(CampaignStatus.DRAFT);
*/
// For now, just verify the factory can create the data
const campaign = await factories.createCampaign({
projectId,
...campaignData,
});
expect(campaign.name).toBe('Test Campaign');
});
it('should validate required fields', async () => {
// Test that API validates required fields
// This would fail without name, subject, etc.
const _invalidData = {
from: '[email protected]',
};
// When integrated with supertest:
/*
await request(app)
.post('/campaigns')
.set('Authorization', `Bearer ${_authToken}`)
.send(_invalidData)
.expect(400);
*/
});
});
describe('GET /campaigns', () => {
it('should list campaigns with pagination', async () => {
// Create test campaigns using bulk insert to avoid memory issues
const campaignData = Array.from({length: 25}, (_, i) => ({
projectId,
name: `Campaign ${i}`,
subject: 'Test Subject',
body: '<p>Test Body</p>',
from: '[email protected]',
status: 'DRAFT' as const,
}));
await prisma.campaign.createMany({data: campaignData});
// When integrated:
/*
const response = await request(app)
.get('/campaigns')
.query({ page: 1, pageSize: 10 })
.set('Authorization', `Bearer ${authToken}`)
.expect(200);
expect(response.body.campaigns).toHaveLength(10);
expect(response.body.total).toBe(25);
expect(response.body.totalPages).toBe(3);
*/
const campaigns = await prisma.campaign.findMany({
where: {projectId},
take: 10,
});
expect(campaigns.length).toBeLessThanOrEqual(10);
});
it('should filter campaigns by status', async () => {
await factories.createCampaign({projectId, status: CampaignStatus.DRAFT});
await factories.createCampaign({projectId, status: CampaignStatus.COMPLETED});
// When integrated:
/*
const response = await request(app)
.get('/campaigns')
.query({ status: CampaignStatus.DRAFT })
.set('Authorization', `Bearer ${authToken}`)
.expect(200);
expect(response.body.campaigns.every(c => c.status === CampaignStatus.DRAFT)).toBe(true);
*/
const draftCampaigns = await prisma.campaign.findMany({
where: {projectId, status: CampaignStatus.DRAFT},
});
expect(draftCampaigns.every(c => c.status === CampaignStatus.DRAFT)).toBe(true);
});
});
describe('PUT /campaigns/:id', () => {
it('should update a draft campaign', async () => {
const campaign = await factories.createCampaign({
projectId,
status: CampaignStatus.DRAFT,
name: 'Original Name',
});
// When integrated:
/*
const response = await request(app)
.put(`/campaigns/${campaign.id}`)
.set('Authorization', `Bearer ${authToken}`)
.send({ name: 'Updated Name' })
.expect(200);
expect(response.body.name).toBe('Updated Name');
*/
const updated = await prisma.campaign.update({
where: {id: campaign.id},
data: {name: 'Updated Name'},
});
expect(updated.name).toBe('Updated Name');
});
it('should not update a completed campaign', async () => {
const _campaign = await factories.createCampaign({
projectId,
status: CampaignStatus.COMPLETED,
});
// When integrated:
/*
await request(app)
.put(`/campaigns/${_campaign.id}`)
.set('Authorization', `Bearer ${_authToken}`)
.send({ name: 'New Name' })
.expect(400);
*/
});
});
describe('DELETE /campaigns/:id', () => {
it('should delete a draft campaign', async () => {
const campaign = await factories.createCampaign({
projectId,
status: CampaignStatus.DRAFT,
});
// When integrated:
/*
await request(app)
.delete(`/campaigns/${campaign.id}`)
.set('Authorization', `Bearer ${authToken}`)
.expect(204);
const deleted = await prisma.campaign.findUnique({ where: { id: campaign.id } });
expect(deleted).toBeNull();
*/
await prisma.campaign.delete({where: {id: campaign.id}});
const deleted = await prisma.campaign.findUnique({where: {id: campaign.id}});
expect(deleted).toBeNull();
});
});
});