Skip to content

Commit 7eabef4

Browse files
PlayWright Test
1 parent 4fce8c0 commit 7eabef4

11 files changed

Lines changed: 2930 additions & 457 deletions

File tree

backend/package-lock.json

Lines changed: 1469 additions & 389 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
"zod": "^4.3.6"
1414
},
1515
"scripts": {
16+
"dev": "ts-node-dev --respawn src/index.ts",
17+
"start": "node dist/index.js",
18+
"build": "tsc",
1619
"lint": "eslint 'src/**/*.ts'"
1720
},
1821
"devDependencies": {

backend/src/index.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,8 @@ import { validateEnv } from "./validateEnv";
55
import { randomUUID } from "crypto";
66
import { z } from "zod";
77
import path from "path";
8-
import { fileURLToPath } from "url";
98
import { config, walletIntegrationReady } from "./config";
109

11-
const __filename = fileURLToPath(import.meta.url);
12-
const __dirname = path.dirname(__filename);
1310
import {
1411
addPledge,
1512
calculateProgress,
@@ -26,10 +23,8 @@ import {
2623
listCampaignPledges,
2724
listCampaigns,
2825
type ListCampaignsOptions,
29-
softDeleteCampaign,
3026
reconcileOnChainPledge,
3127
refundContributor,
32-
updateCampaign,
3328
} from "./services/campaignStore";
3429
import { checkDbHealth } from "./services/db";
3530
import { getCampaignHistory } from "./services/eventHistory";
@@ -46,7 +41,6 @@ import {
4641
parsePledgeListPaginationQuery,
4742
reconcilePledgePayloadSchema,
4843
refundPayloadSchema,
49-
updateCampaignPayloadSchema,
5044
zodIssuesToErrorMessage,
5145
zodIssuesToValidationIssues,
5246
} from "./validation/schemas";
@@ -66,7 +60,6 @@ const RATE_LIMIT_MAX_REQUESTS = 120;
6660
const WRITE_RATE_LIMIT_MAX_REQUESTS = 40;
6761
const CAMPAIGN_DETAIL_PLEDGE_PREVIEW_LIMIT = 5;
6862

69-
7063
app.use(
7164
cors({
7265
origin: (origin, callback) => {
@@ -606,4 +599,4 @@ function startServer() {
606599

607600
if (require.main === module) {
608601
startServer();
609-
}
602+
}

backend/src/services/campaignStore.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,7 @@ export function createCampaign(input: CampaignInput): CampaignRecord {
591591
title: input.title.trim(),
592592
description: input.description.trim(),
593593
acceptedTokens,
594+
assetCode: acceptedTokens[0] || "",
594595
targetAmount: round(input.targetAmount),
595596
pledgedAmount: 0,
596597
deadline: input.deadline,

e2e/campaign-lifecycle.spec.ts

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@ import { DashboardPage } from './dashboard';
33

44
test.describe('Campaign Lifecycle', () => {
55
test.beforeEach(async ({ page }) => {
6-
// Mock Freighter API
76
await page.addInitScript(() => {
87
(window as any).freighter = {
98
isConnected: () => Promise.resolve(true),
10-
requestAccess: () => Promise.resolve("GBAF7Y6PJY6PY6PY6PY6PY6PY6PY6PY6PY6PY6PY6PY6PY6PY6PY6PY"),
9+
requestAccess: () => Promise.resolve("GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"),
1110
getNetworkDetails: () => Promise.resolve({
1211
networkPassphrase: "Test SDF Network ; September 2015",
1312
sorobanRpcUrl: "https://soroban-testnet.stellar.org:443"
@@ -19,47 +18,45 @@ test.describe('Campaign Lifecycle', () => {
1918

2019
test('should complete a full campaign lifecycle (Create -> Pledge -> Funded -> Claim)', async ({ page }) => {
2120
const dashboard = new DashboardPage(page);
22-
const campaignTitle = `E2E Campaign ${Date.now()}`;
23-
const creator = "GBAF7Y6PJY6PY6PY6PY6PY6PY6PY6PY6PY6PY6PY6PY6PY6PY6PY6PY";
21+
const campaignTitle = `E2E Test Campaign ${Date.now()}`;
22+
const creator = "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
2423

2524
await dashboard.goto();
2625

27-
// 1. Create Campaign with a very short deadline
2826
await test.step('Create Campaign', async () => {
2927
await dashboard.creatorInput.fill(creator);
3028
await dashboard.titleInput.fill(campaignTitle);
31-
await dashboard.descriptionInput.fill('This is a test campaign created by Playwright E2E test suite.');
29+
await dashboard.descriptionInput.fill('Playwright E2E full lifecycle test campaign.');
3230
await dashboard.targetAmountInput.fill('100');
33-
await dashboard.deadlineHoursInput.fill('0.001'); // ~3.6 seconds
31+
await dashboard.deadlineHoursInput.fill('0.001');
32+
3433
await dashboard.createButton.click();
3534
await expect(page.locator(`text=${campaignTitle}`)).toBeVisible();
3635
});
3736

38-
// 2. Select the campaign
3937
await test.step('Select Campaign', async () => {
4038
await dashboard.selectCampaign(campaignTitle);
4139
await expect(page.locator('.detail-panel h2')).toHaveText(campaignTitle);
4240
});
4341

44-
// 3. Connect Wallet
42+
// Connect Wallet
4543
await test.step('Connect Wallet', async () => {
4644
await dashboard.connectWallet();
4745
});
4846

49-
// 4. Submit Pledge (Completes Funding)
5047
await test.step('Submit Pledge', async () => {
5148
await dashboard.pledge('100');
5249
await expect(page.locator('.detail-stat:has-text("Remaining") strong')).toHaveText('0');
50+
await expect(page.locator('text=Funded')).toBeVisible();
5351
});
5452

55-
// 5. Wait for deadline and Claim
5653
await test.step('Wait for Deadline and Claim', async () => {
57-
// Wait for the deadline to pass
58-
await page.waitForTimeout(5000);
54+
await page.waitForTimeout(4000);
5955

60-
// Re-select to refresh status or just try to claim
6156
await dashboard.claim();
57+
6258
await expect(page.locator('text=Campaign claimed successfully')).toBeVisible();
59+
await expect(page.locator('.detail-stat:has-text("Status")')).toContainText('Claimed');
6360
});
6461
});
65-
});
62+
});

e2e/dashboard.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ export class DashboardPage {
3333
await this.page.goto('/');
3434
}
3535

36-
async createCampaign(creator: string, title: string, description: string, target: string) {
36+
async createCampaign(creator: string, title: string, description: string, target: string, deadlineHours: string = '24') {
3737
await this.creatorInput.fill(creator);
3838
await this.titleInput.fill(title);
3939
await this.descriptionInput.fill(description);
4040
await this.targetAmountInput.fill(target);
41-
await this.deadlineHoursInput.fill('24');
41+
await this.deadlineHoursInput.fill(deadlineHours);
4242
await this.createButton.click();
4343

4444
// Wait for the new campaign to appear in the table
@@ -57,12 +57,11 @@ export class DashboardPage {
5757
async pledge(amount: string) {
5858
await this.pledgeAmountInput.fill(amount);
5959
await this.addPledgeButton.click();
60-
await expect(this.page.locator('text=Pledge recorded in the local goal vault')).toBeVisible();
60+
await expect(this.page.locator('text=Pledge recorded')).toBeVisible();
6161
}
6262

6363
async claim() {
6464
await this.claimVaultButton.click();
65-
// Wait for claimed status
6665
await expect(this.page.locator('text=Campaign claimed successfully')).toBeVisible();
6766
}
68-
}
67+
}

0 commit comments

Comments
 (0)