Initial commit: TravelHub multi-tenant flight booking platform
Angular + Go + PostgreSQL sample with strict per-tenant isolation. - Backend: Go API (basic auth, tenant-scoped repository layer, pgx pool) - Frontend: Angular 22 SPA (search, checkout, bookings, dashboard) - Database: schema, seed data and demo bookings migrations - Tests: 311 across Go (integration), Angular (unit) and Playwright (e2e), plus a generated evidence report with PDF export - Security: whitebox VAPT report under security/ Secrets (.env, tokens, DB credentials) are git-ignored. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import { expect, test as base } from '@playwright/test';
|
||||
|
||||
import { Account } from './accounts';
|
||||
import { Evidence } from './evidence';
|
||||
import { BookingDetailPage, BookingsPage } from '../pages/bookings.page';
|
||||
import { CheckoutPage } from '../pages/checkout.page';
|
||||
import { DashboardPage } from '../pages/dashboard.page';
|
||||
import { LoginPage } from '../pages/login.page';
|
||||
import { SearchPage } from '../pages/search.page';
|
||||
import { ShellPage } from '../pages/shell.page';
|
||||
|
||||
interface Fixtures {
|
||||
login: LoginPage;
|
||||
shell: ShellPage;
|
||||
search: SearchPage;
|
||||
checkout: CheckoutPage;
|
||||
bookings: BookingsPage;
|
||||
bookingDetail: BookingDetailPage;
|
||||
dashboard: DashboardPage;
|
||||
|
||||
/** Signs in and lands on the dashboard. */
|
||||
signInAs: (account: Account) => Promise<void>;
|
||||
|
||||
/** Records screenshots and observed data for the run report. */
|
||||
evidence: Evidence;
|
||||
|
||||
/** Console and uncaught errors seen during the test; asserted empty at the end. */
|
||||
consoleErrors: string[];
|
||||
}
|
||||
|
||||
export const test = base.extend<Fixtures>({
|
||||
login: async ({ page }, use) => use(new LoginPage(page)),
|
||||
shell: async ({ page }, use) => use(new ShellPage(page)),
|
||||
search: async ({ page }, use) => use(new SearchPage(page)),
|
||||
checkout: async ({ page }, use) => use(new CheckoutPage(page)),
|
||||
bookings: async ({ page }, use) => use(new BookingsPage(page)),
|
||||
bookingDetail: async ({ page }, use) => use(new BookingDetailPage(page)),
|
||||
dashboard: async ({ page }, use) => use(new DashboardPage(page)),
|
||||
|
||||
signInAs: async ({ login }, use) => {
|
||||
await use(async (account: Account) => {
|
||||
await login.signIn(account);
|
||||
});
|
||||
},
|
||||
|
||||
evidence: async ({ page }, use, testInfo) => {
|
||||
await use(new Evidence(page, testInfo));
|
||||
},
|
||||
|
||||
// Every test also asserts the browser console stayed quiet. A stack trace in
|
||||
// the console is a real defect even when the assertions happen to pass.
|
||||
consoleErrors: [
|
||||
async ({ page }, use) => {
|
||||
const errors: string[] = [];
|
||||
|
||||
page.on('console', (message) => {
|
||||
if (message.type() !== 'error') {
|
||||
return;
|
||||
}
|
||||
// The browser logs this for any non-2xx response, including the 401s
|
||||
// and 404s these tests deliberately provoke. It says nothing about
|
||||
// whether the application handled them, so it is not a defect signal.
|
||||
if (message.text().startsWith('Failed to load resource:')) {
|
||||
return;
|
||||
}
|
||||
errors.push(`console.error: ${message.text()}`);
|
||||
});
|
||||
page.on('pageerror', (error) => {
|
||||
errors.push(`uncaught: ${error.message}`);
|
||||
});
|
||||
|
||||
await use(errors);
|
||||
|
||||
expect(errors, 'the browser console should be clean').toEqual([]);
|
||||
},
|
||||
{ auto: true },
|
||||
],
|
||||
});
|
||||
|
||||
export { expect } from '@playwright/test';
|
||||
|
||||
/**
|
||||
* A surname unique to this test run, so a booking can be found again in a list
|
||||
* that other tests and the seed data also write to.
|
||||
*/
|
||||
export function uniqueSurname(prefix = 'E2E'): string {
|
||||
return `${prefix}${Date.now().toString(36).toUpperCase()}`;
|
||||
}
|
||||
Reference in New Issue
Block a user