fix: mount /apps and docker socket in PR workflow build-and-deploy-ci job #41

Merged
david merged 33 commits from fix/switch-to-npm-ci into main 2026-05-20 19:51:36 +00:00
6 changed files with 97 additions and 25 deletions
Showing only changes of commit 005cf7293d - Show all commits
+1 -2
View File
@@ -17,8 +17,7 @@ module.exports = {
// Format options
format: [
process.env.CI ? 'progress' : 'progress-bar',
'pretty:cucumber-pretty'
process.env.CI ? 'progress' : ['pretty', 'html:cucumber-report.html']
],
// Output directory for reports
+3 -3
View File
@@ -253,13 +253,13 @@ test.describe('Elo Rating Updates', () => {
// Wait for page to load and tournaments to be fetched
await page.waitForLoadState('domcontentloaded');
await page.waitForTimeout(2000);
await page.waitForTimeout(500);
// Wait for tournament dropdown to be ready
await page.waitForSelector('select#tournament', { timeout: 5000 });
await page.waitForSelector('select#tournament', { timeout: 3000 });
// Wait a bit for tournaments to load
await page.waitForTimeout(2000);
await page.waitForTimeout(500);
// Select the tournament manually
const tournamentSelect = await page.locator('select#tournament');
+8 -5
View File
@@ -89,7 +89,7 @@ test.describe.serial('Epic 4: Tournament Creation', () => {
await page.click('button[type="submit"]');
// Wait for redirect to admin or player profile (indicates successful login)
await page.waitForURL(/\/(admin|players)/, { timeout: 10000 });
await page.waitForURL(/\/(admin|players)/, { timeout: 5000 });
// Navigate to new tournament page
await page.goto('/admin/tournaments/new');
@@ -106,20 +106,23 @@ test.describe.serial('Epic 4: Tournament Creation', () => {
await page.click('button[type="submit"]');
// Wait for redirect to admin or player profile (indicates successful login)
await page.waitForURL(/\/(admin|players)/, { timeout: 10000 });
await page.waitForURL(/\/(admin|players)/, { timeout: 5000 });
await page.goto('/admin/tournaments/new');
// Wait for step 1 form to load
await page.waitForSelector('input[name="name"]', { timeout: 10000 });
await page.waitForSelector('input[name="name"]', { timeout: 5000 });
// Check for required fields on Step 1
await expect(page.locator('input[name="name"]')).toBeVisible();
await expect(page.locator('select[name="format"]')).toBeVisible();
// Fill in the required name field first so Next actually advances
await page.fill('input[name="name"]', 'Test Tournament');
// Step through to Step 2 to check for submit button (only appears after clicking Next)
await page.click('button:has-text("Next")');
await page.waitForSelector('button[type="submit"]', { timeout: 10000 });
await page.waitForSelector('button[type="submit"]', { timeout: 5000 });
await expect(page.locator('button[type="submit"]')).toBeVisible();
});
@@ -131,7 +134,7 @@ test.describe.serial('Epic 4: Tournament Creation', () => {
await page.click('button[type="submit"]');
// Wait for redirect to admin or player profile (indicates successful login)
await page.waitForURL(/\/(admin|players)/, { timeout: 10000 });
await page.waitForURL(/\/(admin|players)/, { timeout: 5000 });
// Navigate to new tournament page
await page.goto('/admin/tournaments/new');
+5 -5
View File
@@ -133,7 +133,7 @@ test.describe.serial('Issue #7: Schedule Tab', () => {
await page.fill('input[name="email"]', testEmail);
await page.fill('input[name="password"]', testPassword);
await page.click('button[type="submit"]');
await page.waitForURL(/\/(admin|players)/, { timeout: 10000 });
await page.waitForURL(/\/(admin|players)/, { timeout: 5000 });
// Navigate to tournament detail
await page.goto(`/admin/tournaments/${tournamentId}`);
@@ -149,7 +149,7 @@ test.describe.serial('Issue #7: Schedule Tab', () => {
await page.fill('input[name="email"]', testEmail);
await page.fill('input[name="password"]', testPassword);
await page.click('button[type="submit"]');
await page.waitForURL(/\/(admin|players)/, { timeout: 10000 });
await page.waitForURL(/\/(admin|players)/, { timeout: 5000 });
// Navigate to schedule page
await page.goto(`/admin/tournaments/${tournamentId}/schedule`);
@@ -166,7 +166,7 @@ test.describe.serial('Issue #7: Schedule Tab', () => {
await page.fill('input[name="email"]', testEmail);
await page.fill('input[name="password"]', testPassword);
await page.click('button[type="submit"]');
await page.waitForURL(/\/(admin|players)/, { timeout: 10000 });
await page.waitForURL(/\/(admin|players)/, { timeout: 5000 });
// Navigate to schedule page
await page.goto(`/admin/tournaments/${tournamentId}/schedule`);
@@ -196,7 +196,7 @@ test.describe.serial('Issue #7: Schedule Tab', () => {
await page.fill('input[name="email"]', testEmail);
await page.fill('input[name="password"]', testPassword);
await page.click('button[type="submit"]');
await page.waitForURL(/\/(admin|players)/, { timeout: 10000 });
await page.waitForURL(/\/(admin|players)/, { timeout: 5000 });
// Navigate to schedule page
await page.goto(`/admin/tournaments/${tournamentId}/schedule`);
@@ -218,7 +218,7 @@ test.describe.serial('Issue #7: Schedule Tab', () => {
await page.fill('input[name="email"]', testEmail);
await page.fill('input[name="password"]', testPassword);
await page.click('button[type="submit"]');
await page.waitForURL(/\/(admin|players)/, { timeout: 10000 });
await page.waitForURL(/\/(admin|players)/, { timeout: 5000 });
// Call the schedule API
const response = await page.request.get(
+5 -5
View File
@@ -82,7 +82,7 @@ test.describe.serial('Issue #22: Team Configuration', () => {
await page.fill('input[name="email"]', testEmail);
await page.fill('input[name="password"]', testPassword);
await page.click('button[type="submit"]');
await page.waitForURL(/\/(admin|players)/, { timeout: 10000 });
await page.waitForURL(/\/(admin|players)/, { timeout: 5000 });
// Navigate to tournament creation
await page.goto('/admin/tournaments/new');
@@ -105,7 +105,7 @@ test.describe.serial('Issue #22: Team Configuration', () => {
await page.fill('input[name="email"]', testEmail);
await page.fill('input[name="password"]', testPassword);
await page.click('button[type="submit"]');
await page.waitForURL(/\/(admin|players)/, { timeout: 10000 });
await page.waitForURL(/\/(admin|players)/, { timeout: 5000 });
// Navigate to tournament creation
await page.goto('/admin/tournaments/new');
@@ -127,7 +127,7 @@ test.describe.serial('Issue #22: Team Configuration', () => {
const playerName4 = `Player ${Date.now() + 3}`;
// Create first player - wait for search input to appear first
await page.waitForSelector('input[placeholder*="Search"]', { timeout: 10000 });
await page.waitForSelector('input[placeholder*="Search"]', { timeout: 5000 });
await page.fill('input[placeholder*="Search"]', playerName1);
await page.waitForTimeout(500);
await page.click(`text=+ Create "${playerName1}" as new player`);
@@ -181,7 +181,7 @@ test.describe.serial('Issue #22: Team Configuration', () => {
await page.fill('input[name="email"]', testEmail);
await page.fill('input[name="password"]', testPassword);
await page.click('button[type="submit"]');
await page.waitForURL(/\/(admin|players)/, { timeout: 10000 });
await page.waitForURL(/\/(admin|players)/, { timeout: 5000 });
// Navigate to tournament creation
await page.goto('/admin/tournaments/new');
@@ -259,7 +259,7 @@ test.describe.serial('Issue #22: Team Configuration', () => {
await page.fill('input[name="email"]', testEmail);
await page.fill('input[name="password"]', testPassword);
await page.click('button[type="submit"]');
await page.waitForURL(/\/(admin|players)/, { timeout: 10000 });
await page.waitForURL(/\/(admin|players)/, { timeout: 5000 });
// Navigate to edit tournament page
await page.goto(`/admin/tournaments/${tournamentId}/edit`);
+74 -4
View File
@@ -11,11 +11,54 @@
import { test, expect } from '@playwright/test';
import { prisma } from '@/lib/prisma';
const BASE_URL = process.env.CI ? 'https://euchre-ci.notsosm.art' : 'http://localhost:3000';
function getTestCredentials() {
const timestamp = Date.now();
return {
email: `allowties-admin-${timestamp}@example.com`,
password: 'AdminPassword123!',
name: `AllowTies Admin ${timestamp}`,
};
}
test.describe('Tournament Edit - allowTies functionality', () => {
let tournamentId: number;
let testEmail: string;
let testPassword: string;
test.beforeAll(async () => {
// Create admin user via API
const credentials = getTestCredentials();
testEmail = credentials.email;
testPassword = credentials.password;
const response = await fetch(`${BASE_URL}/api/auth/sign-up/email`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Origin: BASE_URL,
},
body: JSON.stringify({
email: testEmail,
password: testPassword,
name: credentials.name,
}),
});
console.log('allowTies test user creation response:', response.status);
// Update user to club_admin role
const user = await prisma.user.findUnique({
where: { email: testEmail },
});
if (user) {
await prisma.user.update({
where: { id: user.id },
data: { role: 'club_admin' },
});
}
// Create a test tournament for editing
const tournament = await prisma.event.create({
data: {
@@ -25,6 +68,7 @@ test.describe('Tournament Edit - allowTies functionality', () => {
status: 'planned',
allowTies: false,
targetScore: 5,
ownerId: user?.id,
createdAt: new Date(),
updatedAt: new Date(),
},
@@ -37,16 +81,28 @@ test.describe('Tournament Edit - allowTies functionality', () => {
if (tournamentId) {
await prisma.event.delete({
where: { id: tournamentId },
});
}).catch(() => {});
}
// Clean up user
const user = await prisma.user.findUnique({ where: { email: testEmail } });
if (user) {
await prisma.user.delete({ where: { id: user.id } });
}
});
test('should display allowTies checkbox on edit form @chromium-admin', async ({ page }) => {
// Login first
await page.goto('/auth/login');
await page.fill('input[name="email"]', testEmail);
await page.fill('input[name="password"]', testPassword);
await page.click('button[type="submit"]');
await page.waitForURL(/\/(admin|players)/, { timeout: 5000 });
// Navigate to tournament edit page
await page.goto(`/admin/tournaments/${tournamentId}/edit`);
// Wait for form to load - edit page shows "Edit Tournament" heading
await expect(page.locator('text=Edit Tournament')).toBeVisible();
await expect(page.locator('text=Edit Tournament')).toBeVisible({ timeout: 5000 });
// Check that allowTies checkbox exists
const allowTiesCheckbox = page.locator('input[name="allowTies"]');
@@ -55,11 +111,18 @@ test.describe('Tournament Edit - allowTies functionality', () => {
});
test('should save allowTies when toggled to true @chromium-admin', async ({ page }) => {
// Login first
await page.goto('/auth/login');
await page.fill('input[name="email"]', testEmail);
await page.fill('input[name="password"]', testPassword);
await page.click('button[type="submit"]');
await page.waitForURL(/\/(admin|players)/, { timeout: 5000 });
// Navigate to tournament edit page
await page.goto(`/admin/tournaments/${tournamentId}/edit`);
// Wait for form to load
await expect(page.locator('text=Edit Tournament')).toBeVisible();
await expect(page.locator('text=Edit Tournament')).toBeVisible({ timeout: 5000 });
// Toggle allowTies checkbox
const allowTiesCheckbox = page.locator('input[name="allowTies"]');
@@ -87,11 +150,18 @@ test.describe('Tournament Edit - allowTies functionality', () => {
data: { allowTies: true },
});
// Login first
await page.goto('/auth/login');
await page.fill('input[name="email"]', testEmail);
await page.fill('input[name="password"]', testPassword);
await page.click('button[type="submit"]');
await page.waitForURL(/\/(admin|players)/, { timeout: 5000 });
// Navigate to tournament edit page
await page.goto(`/admin/tournaments/${tournamentId}/edit`);
// Wait for form to load
await expect(page.locator('text=Edit Tournament')).toBeVisible();
await expect(page.locator('text=Edit Tournament')).toBeVisible({ timeout: 5000 });
// Verify checkbox is checked
const allowTiesCheckbox = page.locator('input[name="allowTies"]');