Module cleanup and tests
CI / ci (push) Failing after 7s

This commit is contained in:
2026-05-24 23:13:45 +02:00
parent 63d83e999a
commit 5dc9b3b8d4
72 changed files with 2545 additions and 1220 deletions
+5 -5
View File
@@ -134,9 +134,9 @@ test.describe('Epic 1: Core Camera Visibility Control', () => {
// Note: Cela nécessite une implémentation spécifique ou un mock
// Pour les tests E2E, on peut utiliser l'API du module directement
await page.evaluate((userId) => {
if (game.modules.get('video-view-manager')) {
if (game.modules.get('scrying-pool')) {
// Appeler l'API interne si disponible
const controller = game.modules.get('video-view-manager').api?.controller;
const controller = game.modules.get('scrying-pool').api?.controller;
if (controller) {
controller.action('test', userId, 'self-muted');
}
@@ -219,8 +219,8 @@ test.describe('Epic 1: Core Camera Visibility Control', () => {
test('Cam-lost participants show portrait fallback', async ({ page }) => {
// Simuler la perte de caméra
await page.evaluate((userId) => {
if (game.modules.get('video-view-manager')) {
const controller = game.modules.get('video-view-manager').api?.controller;
if (game.modules.get('scrying-pool')) {
const controller = game.modules.get('scrying-pool').api?.controller;
if (controller) {
controller.action('test', userId, 'cam-lost');
}
@@ -258,7 +258,7 @@ test.describe('Epic 1: Core Camera Visibility Control', () => {
test('First encounter shows explanatory tooltip', async ({ page }) => {
// Effacer le flag de premier badge
await page.evaluate(() => {
game.user?.unsetFlag('video-view-manager', 'firstBadgeEncounter');
game.user?.unsetFlag('scrying-pool', 'firstBadgeEncounter');
});
// Recharger la page pour déclencher le first encounter
+4 -4
View File
@@ -499,8 +499,8 @@ test.describe('Epic 2: Player Notifications & Director\'s Board', () => {
await page.locator('button[aria-label="Configure Settings"]').click();
await page.waitForSelector('.app-v2.settings', { state: 'visible' });
// Sélectionner Video View Manager
await page.locator('button:has-text("Video View Manager")').click();
// Sélectionner Scrying Pool
await page.locator('button:has-text("Scrying Pool")').click();
// Trouver le paramètre de verbosité
await page.waitForSelector('.sp-notification-verbosity-select', { timeout: 5000 });
@@ -518,7 +518,7 @@ test.describe('Epic 2: Player Notifications & Director\'s Board', () => {
await page.locator('button[aria-label="Configure Settings"]').click();
await page.waitForSelector('.app-v2.settings', { state: 'visible' });
await page.locator('button:has-text("Video View Manager")').click();
await page.locator('button:has-text("Scrying Pool")').click();
await page.waitForSelector('.sp-notification-verbosity-select', { timeout: 5000 });
await page.locator('.sp-notification-verbosity-select').selectOption('GM Only');
@@ -533,7 +533,7 @@ test.describe('Epic 2: Player Notifications & Director\'s Board', () => {
await page.locator('button[aria-label="Configure Settings"]').click();
await page.waitForSelector('.app-v2.settings', { state: 'visible' });
await page.locator('button:has-text("Video View Manager")').click();
await page.locator('button:has-text("Scrying Pool")').click();
await page.waitForSelector('.sp-notification-verbosity-select', { timeout: 5000 });
await page.locator('.sp-notification-verbosity-select').selectOption('Silent');
+14 -14
View File
@@ -130,7 +130,7 @@ test.describe('FR-15: Save Scene Preset', () => {
// Vérifier que le preset contient la matrice
const presetData = await page.evaluate((presetName) => {
const module = game.modules.get('video-view-manager');
const module = game.modules.get('scrying-pool');
if (module && module.api?.scenePresetManager) {
const preset = module.api.scenePresetManager.getPreset(presetName);
return preset?.matrix;
@@ -289,7 +289,7 @@ test.describe('FR-17: Scene Auto-Apply', () => {
// Associer le preset à la scène actuelle
await page.evaluate((presetName) => {
const module = game.modules.get('video-view-manager');
const module = game.modules.get('scrying-pool');
if (module && module.api?.scenePresetManager) {
const currentScene = game.scenes?.active;
if (currentScene) {
@@ -326,7 +326,7 @@ test.describe('FR-17: Scene Auto-Apply', () => {
// Ce test vérifie que le délai est configurable
// La valeur par défaut est 0ms
const delay = await page.evaluate(() => {
const module = game.modules.get('video-view-manager');
const module = game.modules.get('scrying-pool');
if (module && module.api?.scenePresetManager) {
return module.api.scenePresetManager.autoApplyDelay;
}
@@ -345,7 +345,7 @@ test.describe('FR-17: Scene Auto-Apply', () => {
await saveScenePreset(page, TEST_PRESET_NAME);
await page.evaluate((presetName) => {
const module = game.modules.get('video-view-manager');
const module = game.modules.get('scrying-pool');
if (module && module.api?.scenePresetManager) {
const currentScene = game.scenes?.active;
if (currentScene) {
@@ -389,7 +389,7 @@ test.describe('FR-18: Disable Auto-Apply', () => {
// Désactiver l'auto-apply pour la scène actuelle
await page.evaluate((presetName) => {
const module = game.modules.get('video-view-manager');
const module = game.modules.get('scrying-pool');
if (module && module.api?.scenePresetManager) {
const currentScene = game.scenes?.active;
if (currentScene) {
@@ -427,7 +427,7 @@ test.describe('FR-18: Disable Auto-Apply', () => {
test('Auto-apply can be disabled globally', async ({ page }) => {
// Désactiver l'auto-apply globalement
await page.evaluate(() => {
const module = game.modules.get('video-view-manager');
const module = game.modules.get('scrying-pool');
if (module && module.api?.scenePresetManager) {
module.api.scenePresetManager.setAutoApplyEnabled(false);
}
@@ -437,7 +437,7 @@ test.describe('FR-18: Disable Auto-Apply', () => {
await saveScenePreset(page, TEST_PRESET_NAME);
await page.evaluate((presetName) => {
const module = game.modules.get('video-view-manager');
const module = game.modules.get('scrying-pool');
if (module && module.api?.scenePresetManager) {
const currentScene = game.scenes?.active;
if (currentScene) {
@@ -472,7 +472,7 @@ test.describe('FR-18: Disable Auto-Apply', () => {
// Réactiver l'auto-apply global
await page.evaluate(() => {
const module = game.modules.get('video-view-manager');
const module = game.modules.get('scrying-pool');
if (module && module.api?.scenePresetManager) {
module.api.scenePresetManager.setAutoApplyEnabled(true);
}
@@ -482,7 +482,7 @@ test.describe('FR-18: Disable Auto-Apply', () => {
test('Director\'s Board always provides manual override', async ({ page }) => {
// Désactiver l'auto-apply
await page.evaluate(() => {
const module = game.modules.get('video-view-manager');
const module = game.modules.get('scrying-pool');
if (module && module.api?.scenePresetManager) {
module.api.scenePresetManager.setAutoApplyEnabled(false);
}
@@ -510,7 +510,7 @@ test.describe('FR-18: Disable Auto-Apply', () => {
// Réactiver
await page.evaluate(() => {
const module = game.modules.get('video-view-manager');
const module = game.modules.get('scrying-pool');
if (module && module.api?.scenePresetManager) {
module.api.scenePresetManager.setAutoApplyEnabled(true);
}
@@ -558,7 +558,7 @@ test.describe('FR-19: Preset Import/Export', () => {
// Capturer le contenu JSON
const jsonContent = await page.evaluate(() => {
const module = game.modules.get('video-view-manager');
const module = game.modules.get('scrying-pool');
if (module && module.api?.scenePresetManager) {
return JSON.stringify(module.api.scenePresetManager.getAllPresets(), null, 2);
}
@@ -596,7 +596,7 @@ test.describe('FR-19: Preset Import/Export', () => {
// Importer via l'API
await page.evaluate((data) => {
const module = game.modules.get('video-view-manager');
const module = game.modules.get('scrying-pool');
if (module && module.api?.scenePresetManager) {
module.api.scenePresetManager.importPresets(data, { merge: true });
}
@@ -604,7 +604,7 @@ test.describe('FR-19: Preset Import/Export', () => {
// Vérifier que les nouveaux presets existent
const presetNames = await page.evaluate(() => {
const module = game.modules.get('video-view-manager');
const module = game.modules.get('scrying-pool');
if (module && module.api?.scenePresetManager) {
return Object.keys(module.api.scenePresetManager.getAllPresets());
}
@@ -624,7 +624,7 @@ test.describe('FR-19: Preset Import/Export', () => {
// Essayer d'importer du JSON invalide
const result = await page.evaluate(() => {
const module = game.modules.get('video-view-manager');
const module = game.modules.get('scrying-pool');
if (module && module.api?.scenePresetManager) {
try {
module.api.scenePresetManager.importPresets('invalid json', { merge: true });
+8 -83
View File
@@ -3,7 +3,6 @@
*
* FR-23: Player Privacy Panel accessible from module settings
* FR-24: Reaction Cam automation requires explicit opt-in
* FR-25: HP-Reactive Cam Styling requires explicit opt-in
* FR-26: Custom Portrait Fallback settable via file picker
*/
@@ -53,14 +52,11 @@ test.describe('FR-23: Player Privacy Panel Accessibility', () => {
// Vérifier que les sections existent
const reactionCamSection = page.locator('.sp-automation-item:has-text("Reaction Cam")');
const hpStylingSection = page.locator('.sp-automation-item:has-text("HP-Reactive")');
await expect(reactionCamSection).toBeVisible({ timeout: 5000 });
await expect(hpStylingSection).toBeVisible({ timeout: 5000 });
// Vérifier les toggles
const toggles = page.locator('.sp-toggle-switch');
expect(await toggles.count()).toBeGreaterThanOrEqual(2);
await expect(toggles).toHaveCount(1);
});
test('Panel shows opt-in status as ON/OFF for each automation', async ({ page }) => {
@@ -81,7 +77,7 @@ test.describe('FR-23: Player Privacy Panel Accessibility', () => {
// Les contrôles devraient être désactivés
const toggles = page.locator('.sp-toggle-switch:disabled');
await expect(toggles).toHaveCount(2); // Reaction Cam et HP-Reactive
await expect(toggles).toHaveCount(1);
});
test('Settings persist in world-level user flags', async ({ page }) => {
@@ -163,7 +159,7 @@ test.describe('FR-24: Reaction Cam Automation', () => {
// Si désactivé, le trigger ne devrait pas fonctionner
// Simuler un trigger
const triggerResult = await page.evaluate(() => {
const module = game.modules.get('video-view-manager');
const module = game.modules.get('scrying-pool');
if (module && module.api?.reactionCam) {
// Vérifier que Reaction Cam est désactivé
return module.api.reactionCam.isEnabled();
@@ -229,7 +225,7 @@ test.describe('FR-24: Reaction Cam Automation', () => {
// Simuler un trigger
const result = await page.evaluate(() => {
const module = game.modules.get('video-view-manager');
const module = game.modules.get('scrying-pool');
if (module && module.api?.reactionCam) {
// Le trigger devrait skipper ce joueur
return { skipped: true, reason: 'opted-out' };
@@ -242,77 +238,6 @@ test.describe('FR-24: Reaction Cam Automation', () => {
});
});
// ============================================================================
// FR-25: HP-Reactive Cam Styling Opt-In
// ============================================================================
test.describe('FR-25: HP-Reactive Cam Styling', () => {
test('HP-Reactive Cam Styling requires explicit opt-in (default: off)', async ({ page }) => {
await openPlayerPrivacyPanel(page, TEST_USER);
const stylingToggle = page.locator('.sp-automation-item:has-text("HP-Reactive") .sp-toggle-switch');
// Vérifier que l'état par défaut est OFF
const isChecked = await stylingToggle.evaluate(el => el.checked);
expect(isChecked).toBe(false);
});
test('HP-Reactive Styling remains disabled until explicitly enabled', async ({ page }) => {
await openPlayerPrivacyPanel(page, TEST_USER);
const stylingToggle = page.locator('.sp-automation-item:has-text("HP-Reactive") .sp-toggle-switch');
// Simuler un changement de HP
const result = await page.evaluate(() => {
const module = game.modules.get('video-view-manager');
if (module && module.api?.hpStyling) {
// Vérifier que le styling est désactivé
return module.api.hpStyling.isEnabled();
}
return false;
});
expect(result).toBe(false);
});
test('GM is not notified of individual styling opt-in statuses', async ({ page }) => {
// Activer HP-Reactive pour un joueur
await openPlayerPrivacyPanel(page, TEST_USER);
const stylingToggle = page.locator('.sp-automation-item:has-text("HP-Reactive") .sp-toggle-switch');
await stylingToggle.click();
await page.waitForTimeout(500);
// Vérifier qu'il n'y a pas de notification pour le GM
// (Contrairement à Reaction Cam qui montre un badge)
const notification = page.locator('.notification:has-text("HP-Reactive")');
// Devrait ne PAS voir de notification
expect(await notification.count()).toBe(0);
// Nettoyer
await stylingToggle.click();
});
test('Styling opt-in flag persists across sessions', async ({ page }) => {
// Activer
await openPlayerPrivacyPanel(page, TEST_USER);
const stylingToggle = page.locator('.sp-automation-item:has-text("HP-Reactive") .sp-toggle-switch');
await stylingToggle.click();
await page.waitForTimeout(500);
// Recharger
await page.reload();
await waitForFoundryReady(page);
// Vérifier
await openPlayerPrivacyPanel(page, TEST_USER);
const isChecked = await stylingToggle.evaluate(el => el.checked);
expect(isChecked).toBe(true);
// Désactiver
await stylingToggle.click();
});
});
// ============================================================================
// FR-26: Custom Portrait Fallback
// ============================================================================
@@ -388,7 +313,7 @@ test.describe('FR-26: Custom Portrait Fallback', () => {
// Via l'API, définir un portrait
await page.evaluate(() => {
const module = game.modules.get('video-view-manager');
const module = game.modules.get('scrying-pool');
if (module && module.api?.portraitFallbackHandler) {
const dataURL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==';
module.api.portraitFallbackHandler.setPortraitFallback('gamemaster', dataURL);
@@ -412,7 +337,7 @@ test.describe('FR-26: Custom Portrait Fallback', () => {
// Définir un portrait personnalisé
await page.evaluate(() => {
const module = game.modules.get('video-view-manager');
const module = game.modules.get('scrying-pool');
if (module && module.api?.portraitFallbackHandler) {
const dataURL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==';
module.api.portraitFallbackHandler.setPortraitFallback('gamemaster', dataURL);
@@ -421,7 +346,7 @@ test.describe('FR-26: Custom Portrait Fallback', () => {
// Forcer l'état never-connected pour un utilisateur
await page.evaluate(() => {
const module = game.modules.get('video-view-manager');
const module = game.modules.get('scrying-pool');
if (module && module.api?.controller) {
module.api.controller.setState('gamemaster', 'never-connected');
}
@@ -462,7 +387,7 @@ async function testPortraitUpload(page, filename, shouldSucceed) {
// Pour l'instant, on simule via l'API
const result = await page.evaluate(({ filename, shouldSucceed }) => {
const module = game.modules.get('video-view-manager');
const module = game.modules.get('scrying-pool');
if (module && module.api?.portraitFallbackHandler) {
if (shouldSucceed) {
// Fichier valide
+3 -3
View File
@@ -1,7 +1,7 @@
/**
* Module Initialization Tests - Tests E2E
*
* Vérifie que le module Video View Manager s'initialise correctement
* Vérifie que le module Scrying Pool s'initialise correctement
* dans FoundryVTT et que toutes les fonctionnalités de base sont disponibles.
*/
@@ -12,8 +12,8 @@ import {
clickFoundryButton,
} from '../utils/foundry-helpers';
const MODULE_ID = 'video-view-manager';
const MODULE_NAME = 'Video View Manager';
const MODULE_ID = 'scrying-pool';
const MODULE_NAME = 'Scrying Pool';
test.describe('Module Initialization', () => {
test.setTimeout(60000);