644 lines
22 KiB
JavaScript
644 lines
22 KiB
JavaScript
/**
|
|
* Epic 3: Scene-Aware Camera Automation (Scene Presets) - Tests E2E
|
|
*
|
|
* FR-15: GM can save named Scene Preset from current Visibility Matrix
|
|
* FR-16: GM can load Scene Preset at any time
|
|
* FR-17: Scene Preset auto-applies on Scene activation
|
|
* FR-18: Disable auto-apply per-scene or globally
|
|
* FR-19: Preset import/export as JSON
|
|
*/
|
|
|
|
import { test, expect } from '@playwright/test';
|
|
import {
|
|
waitForFoundryReady,
|
|
waitForVVMModule,
|
|
openDirectorsBoard,
|
|
clickFoundryButton,
|
|
saveScenePreset,
|
|
loadScenePreset,
|
|
waitForNotification,
|
|
} from '../utils/foundry-helpers';
|
|
|
|
const TEST_PRESET_NAME = 'TestPreset';
|
|
const TEST_PRESET_NAME_2 = 'TestPreset2';
|
|
|
|
test.describe('Epic 3: Scene-Aware Camera Automation', () => {
|
|
test.setTimeout(120000);
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.goto('https://localhost:31000', {
|
|
waitUntil: 'domcontentloaded',
|
|
timeout: 30000,
|
|
});
|
|
|
|
await waitForFoundryReady(page);
|
|
await waitForVVMModule(page);
|
|
|
|
const isGM = await page.evaluate(() => game.user?.isGM || false);
|
|
if (!isGM) {
|
|
test.skip(true, 'Test requires GM user');
|
|
}
|
|
|
|
// Nettoyer les presets de test
|
|
await cleanupTestPresets(page);
|
|
});
|
|
|
|
test.afterEach(async ({ page }) => {
|
|
// Nettoyer après chaque test
|
|
await cleanupTestPresets(page);
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Nettoie les presets de test
|
|
*/
|
|
async function cleanupTestPresets(page) {
|
|
await openDirectorsBoard(page);
|
|
|
|
// Liste des presets à supprimer
|
|
const presetsToDelete = [TEST_PRESET_NAME, TEST_PRESET_NAME_2];
|
|
|
|
for (const presetName of presetsToDelete) {
|
|
try {
|
|
// Ouvrir la liste des presets
|
|
await clickFoundryButton(page, 'button:has-text("Load Preset")');
|
|
await page.waitForSelector('.sp-preset-list', { state: 'visible', timeout: 3000 });
|
|
|
|
// Trouver et supprimer le preset
|
|
const presetItem = page.locator(`.sp-preset-item:has-text("${presetName}")`);
|
|
if (await presetItem.count() > 0) {
|
|
await presetItem.hover();
|
|
await clickFoundryButton(page, '.sp-preset-delete-button');
|
|
await clickFoundryButton(page, 'button:has-text("Confirm")');
|
|
await page.waitForTimeout(500);
|
|
}
|
|
} catch (error) {
|
|
console.warn(`Could not delete preset ${presetName}:`, error.message);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// FR-15: Save named Scene Preset
|
|
// ============================================================================
|
|
test.describe('FR-15: Save Scene Preset', () => {
|
|
test('GM can save current Visibility Matrix as named preset', async ({ page }) => {
|
|
await openDirectorsBoard(page);
|
|
|
|
// Sauvegarder le preset
|
|
await saveScenePreset(page, TEST_PRESET_NAME);
|
|
|
|
// Vérifier la notification
|
|
await waitForNotification(page, `Saved preset: ${TEST_PRESET_NAME}`, 5000);
|
|
});
|
|
|
|
test('Preset name must be unique per world', async ({ page }) => {
|
|
await openDirectorsBoard(page);
|
|
|
|
// Sauvegarder le premier preset
|
|
await saveScenePreset(page, TEST_PRESET_NAME);
|
|
|
|
// Essayer de sauvegarder avec le même nom
|
|
await page.locator('button:has-text("Save Preset")').click();
|
|
await page.waitForSelector('.sp-save-preset-dialog', { state: 'visible' });
|
|
await page.locator('.sp-save-preset-dialog input[name="presetName"]').fill(TEST_PRESET_NAME);
|
|
|
|
// Devrait montrer une erreur ou ne pas permettre le doublon
|
|
// Selon l'implémentation, soit:
|
|
// 1. Le bouton Save est désactivé
|
|
// 2. Une erreur apparaît
|
|
const saveButton = page.locator('.sp-save-preset-dialog button:has-text("Save"):disabled');
|
|
|
|
if (await saveButton.count() > 0) {
|
|
await expect(saveButton).toBeVisible({ timeout: 3000 });
|
|
} else {
|
|
// Sinon, vérifier qu'une erreur apparaît
|
|
const error = page.locator('.sp-error-message');
|
|
await expect(error).toBeVisible({ timeout: 3000 });
|
|
}
|
|
});
|
|
|
|
test('Preset captures full current Visibility Matrix', async ({ page }) => {
|
|
await openDirectorsBoard(page);
|
|
|
|
// Configurer un état spécifique : cacher Player1, montrer Player2
|
|
await clickFoundryButton(page, '.sp-participant-card:has-text("Player1")');
|
|
await page.waitForTimeout(500);
|
|
|
|
// Sauvegarder
|
|
await saveScenePreset(page, TEST_PRESET_NAME);
|
|
|
|
// Vérifier que le preset contient la matrice
|
|
const presetData = await page.evaluate((presetName) => {
|
|
const module = game.modules.get('scrying-pool');
|
|
if (module && module.api?.scenePresetManager) {
|
|
const preset = module.api.scenePresetManager.getPreset(presetName);
|
|
return preset?.matrix;
|
|
}
|
|
return null;
|
|
}, TEST_PRESET_NAME);
|
|
|
|
expect(presetData).toBeTruthy();
|
|
expect(presetData).toHaveProperty('_version');
|
|
expect(presetData).toHaveProperty('matrix');
|
|
});
|
|
|
|
test('Preset names are editable', async ({ page }) => {
|
|
await openDirectorsBoard(page);
|
|
|
|
await clickFoundryButton(page, 'button:has-text("Save Preset")');
|
|
await page.waitForSelector('.sp-save-preset-dialog', { state: 'visible' });
|
|
|
|
const input = page.locator('.sp-save-preset-dialog input[name="presetName"]');
|
|
await input.fill(TEST_PRESET_NAME);
|
|
await expect(input).toHaveValue(TEST_PRESET_NAME);
|
|
|
|
// Modifier le nom
|
|
await input.fill(TEST_PRESET_NAME_2);
|
|
await expect(input).toHaveValue(TEST_PRESET_NAME_2);
|
|
});
|
|
|
|
test('Up to 50 presets per world can be saved', async ({ page }) => {
|
|
await openDirectorsBoard(page);
|
|
|
|
// Sauvegarder plusieurs presets
|
|
const presetCount = 10;
|
|
for (let i = 0; i < presetCount; i++) {
|
|
const name = `Preset${i}`;
|
|
await page.locator('button:has-text("Save Preset")').click();
|
|
await page.waitForSelector('.sp-save-preset-dialog', { state: 'visible' });
|
|
await page.locator('.sp-save-preset-dialog input[name="presetName"]').fill(name);
|
|
await clickFoundryButton(page, '.sp-save-preset-dialog button:has-text("Save")');
|
|
await waitForNotification(page, `Saved preset: ${name}`, 3000);
|
|
}
|
|
|
|
// Vérifier que tous les presets sont dans la liste
|
|
await clickFoundryButton(page, 'button:has-text("Load Preset")');
|
|
await page.waitForSelector('.sp-preset-list', { state: 'visible' });
|
|
|
|
const presetItems = page.locator('.sp-preset-item');
|
|
expect(await presetItems.count()).toBeGreaterThanOrEqual(presetCount);
|
|
|
|
// Nettoyer
|
|
await cleanupTestPresets(page);
|
|
});
|
|
});
|
|
|
|
// ============================================================================
|
|
// FR-16: Load Scene Preset
|
|
// ============================================================================
|
|
test.describe('FR-16: Load Scene Preset', () => {
|
|
test('GM can load a preset at any time', async ({ page }) => {
|
|
await openDirectorsBoard(page);
|
|
|
|
// Sauvegarder un preset
|
|
await saveScenePreset(page, TEST_PRESET_NAME);
|
|
|
|
// Changer manuellement l'état
|
|
await clickFoundryButton(page, '.sp-participant-card:has-text("Player1")');
|
|
await page.waitForTimeout(500);
|
|
|
|
// Charger le preset
|
|
await loadScenePreset(page, TEST_PRESET_NAME);
|
|
|
|
// Vérifier que l'état est revenu à celui du preset
|
|
const card = page.locator('.sp-participant-card:has-text("Player1")');
|
|
const state = await card.locator('.sp-state-badge').textContent();
|
|
|
|
// Le preset sauvé avait Player1 visible (par défaut)
|
|
expect(state).toContain('Active');
|
|
});
|
|
|
|
test('Loading preset overrides current Visibility Matrix', async ({ page }) => {
|
|
await openDirectorsBoard(page);
|
|
|
|
// Cacher tous les participants
|
|
await clickFoundryButton(page, 'button:has-text("Hide All")');
|
|
|
|
// Sauvegarder cet état
|
|
await saveScenePreset(page, TEST_PRESET_NAME);
|
|
|
|
// Montrer tous
|
|
await clickFoundryButton(page, 'button:has-text("Show All")');
|
|
|
|
// Charger le preset "tous cachés"
|
|
await loadScenePreset(page, TEST_PRESET_NAME);
|
|
|
|
// Vérifier que tous sont cachés
|
|
const cards = page.locator('.sp-participant-card');
|
|
const count = await cards.count();
|
|
|
|
for (let i = 0; i < count; i++) {
|
|
const card = cards.nth(i);
|
|
const state = await card.locator('.sp-state-badge').textContent();
|
|
expect(state).toContain('Hidden');
|
|
}
|
|
});
|
|
|
|
test('All clients receive state within 500ms', async ({ page }) => {
|
|
// Sauvegarder un preset
|
|
await openDirectorsBoard(page);
|
|
await saveScenePreset(page, TEST_PRESET_NAME);
|
|
|
|
// Changer l'état
|
|
await clickFoundryButton(page, '.sp-participant-card:has-text("Player1")');
|
|
await page.waitForTimeout(500);
|
|
|
|
const startTime = Date.now();
|
|
|
|
// Charger le preset
|
|
await loadScenePreset(page, TEST_PRESET_NAME);
|
|
|
|
const endTime = Date.now();
|
|
const elapsed = endTime - startTime;
|
|
|
|
// Vérifier que le changement s'est propagé rapidement
|
|
const card = page.locator('.sp-participant-card:has-text("Player1")');
|
|
const state = await card.locator('.sp-state-badge').textContent();
|
|
expect(state).toContain('Active');
|
|
|
|
// Note: En mode single-player test, on ne peut pas vérifier multi-clients
|
|
// Mais le temps devrait être < 500ms
|
|
expect(elapsed).toBeLessThan(500);
|
|
});
|
|
|
|
test('Loading generates notification "GM applied preset: [Preset Name]"', async ({ page }) => {
|
|
await openDirectorsBoard(page);
|
|
await saveScenePreset(page, TEST_PRESET_NAME);
|
|
|
|
// Changer l'état
|
|
await clickFoundryButton(page, '.sp-participant-card:has-text("Player1")');
|
|
|
|
// Charger le preset
|
|
await loadScenePreset(page, TEST_PRESET_NAME);
|
|
|
|
// Vérifier la notification
|
|
await waitForNotification(page, `GM applied preset: ${TEST_PRESET_NAME}`, 5000);
|
|
});
|
|
});
|
|
|
|
// ============================================================================
|
|
// FR-17: Scene Preset Auto-Apply
|
|
// ============================================================================
|
|
test.describe('FR-17: Scene Auto-Apply', () => {
|
|
test('Scene Preset auto-applies on Scene activation', async ({ page }) => {
|
|
await openDirectorsBoard(page);
|
|
|
|
// Sauvegarder un preset
|
|
await saveScenePreset(page, TEST_PRESET_NAME);
|
|
|
|
// Associer le preset à la scène actuelle
|
|
await page.evaluate((presetName) => {
|
|
const module = game.modules.get('scrying-pool');
|
|
if (module && module.api?.scenePresetManager) {
|
|
const currentScene = game.scenes?.active;
|
|
if (currentScene) {
|
|
module.api.scenePresetManager.setScenePreset(
|
|
currentScene.id,
|
|
presetName
|
|
);
|
|
}
|
|
}
|
|
}, TEST_PRESET_NAME);
|
|
|
|
// Changer manuellement l'état
|
|
await clickFoundryButton(page, '.sp-participant-card:has-text("Player1")');
|
|
await page.waitForTimeout(500);
|
|
|
|
// Recharger la scène (simuler le changement de scène)
|
|
await page.evaluate(() => {
|
|
const currentScene = game.scenes?.active;
|
|
if (currentScene) {
|
|
currentScene.activate();
|
|
}
|
|
});
|
|
|
|
// Attendre l'auto-apply
|
|
await page.waitForTimeout(1000);
|
|
|
|
// Vérifier que l'état est revenu à celui du preset
|
|
const card = page.locator('.sp-participant-card:has-text("Player1")');
|
|
const state = await card.locator('.sp-state-badge').textContent();
|
|
expect(state).toContain('Active');
|
|
});
|
|
|
|
test('Auto-apply has configurable pre-delay', async ({ page }) => {
|
|
// 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('scrying-pool');
|
|
if (module && module.api?.scenePresetManager) {
|
|
return module.api.scenePresetManager.autoApplyDelay;
|
|
}
|
|
return 0;
|
|
});
|
|
|
|
// Devrait être un nombre (ms)
|
|
expect(typeof delay).toBe('number');
|
|
expect(delay).toBeGreaterThanOrEqual(0);
|
|
expect(delay).toBeLessThanOrEqual(5000);
|
|
});
|
|
|
|
test('All clients receive "Scene changed: camera layout updated" notification', async ({ page }) => {
|
|
// Sauvegarder et associer un preset
|
|
await openDirectorsBoard(page);
|
|
await saveScenePreset(page, TEST_PRESET_NAME);
|
|
|
|
await page.evaluate((presetName) => {
|
|
const module = game.modules.get('scrying-pool');
|
|
if (module && module.api?.scenePresetManager) {
|
|
const currentScene = game.scenes?.active;
|
|
if (currentScene) {
|
|
module.api.scenePresetManager.setScenePreset(
|
|
currentScene.id,
|
|
presetName
|
|
);
|
|
}
|
|
}
|
|
}, TEST_PRESET_NAME);
|
|
|
|
// Changer manuellement l'état
|
|
await clickFoundryButton(page, '.sp-participant-card:has-text("Player1")');
|
|
|
|
// Recharger la scène
|
|
await page.evaluate(() => {
|
|
const currentScene = game.scenes?.active;
|
|
if (currentScene) {
|
|
currentScene.activate();
|
|
}
|
|
});
|
|
|
|
// Attendre la notification
|
|
// Note: En mode single-player, la notification pourrait ne pas apparaître
|
|
// car c'est le même utilisateur
|
|
try {
|
|
await waitForNotification(page, 'Scene changed: camera layout updated', 5000);
|
|
} catch (error) {
|
|
console.warn('Notification may not appear in single-player mode:', error.message);
|
|
}
|
|
});
|
|
});
|
|
|
|
// ============================================================================
|
|
// FR-18: Disable Auto-Apply
|
|
// ============================================================================
|
|
test.describe('FR-18: Disable Auto-Apply', () => {
|
|
test('Auto-apply can be disabled per-scene', async ({ page }) => {
|
|
await openDirectorsBoard(page);
|
|
await saveScenePreset(page, TEST_PRESET_NAME);
|
|
|
|
// Désactiver l'auto-apply pour la scène actuelle
|
|
await page.evaluate((presetName) => {
|
|
const module = game.modules.get('scrying-pool');
|
|
if (module && module.api?.scenePresetManager) {
|
|
const currentScene = game.scenes?.active;
|
|
if (currentScene) {
|
|
module.api.scenePresetManager.setScenePreset(
|
|
currentScene.id,
|
|
presetName,
|
|
{ autoApply: false }
|
|
);
|
|
}
|
|
}
|
|
}, TEST_PRESET_NAME);
|
|
|
|
// Changer manuellement l'état
|
|
await clickFoundryButton(page, '.sp-participant-card:has-text("Player1")');
|
|
await page.waitForTimeout(500);
|
|
|
|
// Recharger la scène
|
|
await page.evaluate(() => {
|
|
const currentScene = game.scenes?.active;
|
|
if (currentScene) {
|
|
currentScene.activate();
|
|
}
|
|
});
|
|
|
|
// Attendre et vérifier que l'état N'A PAS changé
|
|
await page.waitForTimeout(1500);
|
|
|
|
const card = page.locator('.sp-participant-card:has-text("Player1")');
|
|
const state = await card.locator('.sp-state-badge').textContent();
|
|
|
|
// Devrait être toujours caché (car auto-apply est désactivé)
|
|
expect(state).toContain('Hidden');
|
|
});
|
|
|
|
test('Auto-apply can be disabled globally', async ({ page }) => {
|
|
// Désactiver l'auto-apply globalement
|
|
await page.evaluate(() => {
|
|
const module = game.modules.get('scrying-pool');
|
|
if (module && module.api?.scenePresetManager) {
|
|
module.api.scenePresetManager.setAutoApplyEnabled(false);
|
|
}
|
|
});
|
|
|
|
await openDirectorsBoard(page);
|
|
await saveScenePreset(page, TEST_PRESET_NAME);
|
|
|
|
await page.evaluate((presetName) => {
|
|
const module = game.modules.get('scrying-pool');
|
|
if (module && module.api?.scenePresetManager) {
|
|
const currentScene = game.scenes?.active;
|
|
if (currentScene) {
|
|
module.api.scenePresetManager.setScenePreset(
|
|
currentScene.id,
|
|
presetName,
|
|
{ autoApply: true } // Même si activé par scène, le global prend le dessus
|
|
);
|
|
}
|
|
}
|
|
}, TEST_PRESET_NAME);
|
|
|
|
// Changer l'état
|
|
await clickFoundryButton(page, '.sp-participant-card:has-text("Player1")');
|
|
await page.waitForTimeout(500);
|
|
|
|
// Recharger la scène
|
|
await page.evaluate(() => {
|
|
const currentScene = game.scenes?.active;
|
|
if (currentScene) {
|
|
currentScene.activate();
|
|
}
|
|
});
|
|
|
|
await page.waitForTimeout(1500);
|
|
|
|
const card = page.locator('.sp-participant-card:has-text("Player1")');
|
|
const state = await card.locator('.sp-state-badge').textContent();
|
|
|
|
// Devrait être toujours caché (car auto-apply global est désactivé)
|
|
expect(state).toContain('Hidden');
|
|
|
|
// Réactiver l'auto-apply global
|
|
await page.evaluate(() => {
|
|
const module = game.modules.get('scrying-pool');
|
|
if (module && module.api?.scenePresetManager) {
|
|
module.api.scenePresetManager.setAutoApplyEnabled(true);
|
|
}
|
|
});
|
|
});
|
|
|
|
test('Director\'s Board always provides manual override', async ({ page }) => {
|
|
// Désactiver l'auto-apply
|
|
await page.evaluate(() => {
|
|
const module = game.modules.get('scrying-pool');
|
|
if (module && module.api?.scenePresetManager) {
|
|
module.api.scenePresetManager.setAutoApplyEnabled(false);
|
|
}
|
|
});
|
|
|
|
await openDirectorsBoard(page);
|
|
|
|
// Sauvegarder un preset
|
|
await saveScenePreset(page, TEST_PRESET_NAME);
|
|
|
|
// Changer manuellement l'état
|
|
await clickFoundryButton(page, '.sp-participant-card:has-text("Player1")');
|
|
|
|
// Le bouton Load Preset devrait toujours être disponible
|
|
const loadButton = page.locator('button:has-text("Load Preset")');
|
|
await expect(loadButton).toBeEnabled({ timeout: 5000 });
|
|
|
|
// Charger manuellement
|
|
await loadScenePreset(page, TEST_PRESET_NAME);
|
|
|
|
// Devrait fonctionner même avec auto-apply désactivé
|
|
const card = page.locator('.sp-participant-card:has-text("Player1")');
|
|
const state = await card.locator('.sp-state-badge').textContent();
|
|
expect(state).toContain('Active');
|
|
|
|
// Réactiver
|
|
await page.evaluate(() => {
|
|
const module = game.modules.get('scrying-pool');
|
|
if (module && module.api?.scenePresetManager) {
|
|
module.api.scenePresetManager.setAutoApplyEnabled(true);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
// ============================================================================
|
|
// FR-19: Preset Import/Export
|
|
// ============================================================================
|
|
test.describe('FR-19: Preset Import/Export', () => {
|
|
test('Preset export downloads all presets as JSON', async ({ page }) => {
|
|
await openDirectorsBoard(page);
|
|
|
|
// Sauvegarder quelques presets
|
|
await saveScenePreset(page, 'ExportTest1');
|
|
await saveScenePreset(page, 'ExportTest2');
|
|
|
|
// Ouvrir le menu d'export
|
|
await clickFoundryButton(page, 'button:has-text("Export")');
|
|
await page.waitForSelector('.sp-export-dialog', { state: 'visible' });
|
|
|
|
// Cliquer sur Export
|
|
const downloadPromise = page.waitForEvent('download');
|
|
await clickFoundryButton(page, '.sp-export-dialog button:has-text("Export")');
|
|
|
|
const download = await downloadPromise;
|
|
|
|
// Vérifier que le fichier est JSON
|
|
expect(download.url()).toMatch(/\.json$/i);
|
|
|
|
// Vérifier que le nom contient les presets
|
|
expect(download.url()).toContain('presets');
|
|
|
|
// Nettoyer
|
|
await cleanupTestPresets(page);
|
|
});
|
|
|
|
test('Exported JSON is human-readable', async ({ page }) => {
|
|
await openDirectorsBoard(page);
|
|
await saveScenePreset(page, 'ReadableTest');
|
|
|
|
await clickFoundryButton(page, 'button:has-text("Export")');
|
|
await page.waitForSelector('.sp-export-dialog', { state: 'visible' });
|
|
|
|
// Capturer le contenu JSON
|
|
const jsonContent = await page.evaluate(() => {
|
|
const module = game.modules.get('scrying-pool');
|
|
if (module && module.api?.scenePresetManager) {
|
|
return JSON.stringify(module.api.scenePresetManager.getAllPresets(), null, 2);
|
|
}
|
|
return null;
|
|
});
|
|
|
|
expect(jsonContent).toBeTruthy();
|
|
|
|
// Vérifier que c'est du JSON valide
|
|
const parsed = JSON.parse(jsonContent);
|
|
expect(parsed).toBeTruthy();
|
|
expect(parsed).toHaveProperty('ExportTest');
|
|
|
|
// Nettoyer
|
|
await cleanupTestPresets(page);
|
|
});
|
|
|
|
test('Preset import reads JSON and merges or replaces', async ({ page }) => {
|
|
await openDirectorsBoard(page);
|
|
|
|
// Sauvegarder un preset existant
|
|
await saveScenePreset(page, 'ExistingPreset');
|
|
|
|
// Créer un JSON d'import
|
|
const importData = {
|
|
NewPreset1: {
|
|
_version: 1,
|
|
matrix: { player1: 'hidden', player2: 'hidden' }
|
|
},
|
|
NewPreset2: {
|
|
_version: 1,
|
|
matrix: { player1: 'active', player2: 'active' }
|
|
}
|
|
};
|
|
|
|
// Importer via l'API
|
|
await page.evaluate((data) => {
|
|
const module = game.modules.get('scrying-pool');
|
|
if (module && module.api?.scenePresetManager) {
|
|
module.api.scenePresetManager.importPresets(data, { merge: true });
|
|
}
|
|
}, importData);
|
|
|
|
// Vérifier que les nouveaux presets existent
|
|
const presetNames = await page.evaluate(() => {
|
|
const module = game.modules.get('scrying-pool');
|
|
if (module && module.api?.scenePresetManager) {
|
|
return Object.keys(module.api.scenePresetManager.getAllPresets());
|
|
}
|
|
return [];
|
|
});
|
|
|
|
expect(presetNames).toContain('ExistingPreset');
|
|
expect(presetNames).toContain('NewPreset1');
|
|
expect(presetNames).toContain('NewPreset2');
|
|
|
|
// Nettoyer
|
|
await cleanupTestPresets(page);
|
|
});
|
|
|
|
test('Invalid JSON shows error', async ({ page }) => {
|
|
await openDirectorsBoard(page);
|
|
|
|
// Essayer d'importer du JSON invalide
|
|
const result = await page.evaluate(() => {
|
|
const module = game.modules.get('scrying-pool');
|
|
if (module && module.api?.scenePresetManager) {
|
|
try {
|
|
module.api.scenePresetManager.importPresets('invalid json', { merge: true });
|
|
return { success: true };
|
|
} catch (e) {
|
|
return { success: false, error: e.message };
|
|
}
|
|
}
|
|
return { success: false, error: 'Module not found' };
|
|
});
|
|
|
|
// Devrait échouer
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toBeTruthy();
|
|
});
|
|
});
|