super-productivity/e2e/tests/plugins/plugin-iframe.spec.ts
2025-09-09 23:47:34 +02:00

166 lines
5.6 KiB
TypeScript

import { expect, test } from '../../fixtures/test.fixture';
import { cssSelectors } from '../../constants/selectors';
import {
enablePluginWithVerification,
getCITimeoutMultiplier,
logPluginState,
waitForPluginAssets,
waitForPluginInMenu,
waitForPluginManagementInit,
} from '../../helpers/plugin-test.helpers';
const { SIDENAV, SETTINGS_BTN } = cssSelectors;
// Plugin-related selectors
const PLUGIN_NAV_ITEMS = `${SIDENAV} nav-item button`;
const PLUGIN_IFRAME = 'plugin-index iframe';
const PLUGIN_MANAGEMENT = 'plugin-management';
const PLUGIN_SECTION = '.plugin-section';
const SETTINGS_PAGE = '.page-settings';
const COLLAPSIBLE_EXPANDED = '.plugin-section collapsible.isExpanded';
test.describe.serial('Plugin Iframe', () => {
test.beforeEach(async ({ page, workViewPage }) => {
// Increase timeout for CI environment
const timeoutMultiplier = getCITimeoutMultiplier();
test.setTimeout(30000 * timeoutMultiplier); // Reduced from 60s to 30s base
// First, ensure plugin assets are available
const assetsAvailable = await waitForPluginAssets(page);
if (!assetsAvailable) {
if (process.env.CI) {
test.skip(true, 'Plugin assets not available in CI - skipping test');
return;
}
throw new Error('Plugin assets not available - cannot proceed with test');
}
await workViewPage.waitForTaskList();
await waitForPluginManagementInit(page);
// Navigate to settings
const settingsBtn = page.locator(SETTINGS_BTN);
await settingsBtn.waitFor({ state: 'visible' });
await settingsBtn.click();
// Wait for settings page to be visible
await page.waitForSelector(SETTINGS_PAGE, { state: 'visible' });
// Scroll to plugin section
const pluginSection = page.locator(PLUGIN_SECTION);
await pluginSection.scrollIntoViewIfNeeded();
// Expand collapsible if needed
const collapsible = page.locator('.plugin-section collapsible');
const collapsibleHeader = collapsible.locator('.collapsible-header');
// Check if already expanded, if not click to expand
const expandedCollapsible = page.locator(COLLAPSIBLE_EXPANDED);
if ((await expandedCollapsible.count()) === 0) {
await collapsibleHeader.click();
// Wait for the expanded class to appear
await page.waitForSelector(COLLAPSIBLE_EXPANDED, { state: 'visible' });
}
// Wait for plugin management to be visible
await page.waitForSelector(PLUGIN_MANAGEMENT, {
state: 'visible',
timeout: 10000 * timeoutMultiplier,
});
// Log current plugin state for debugging
if (process.env.CI) {
await logPluginState(page);
}
// Enable API Test Plugin with verification
const pluginEnabled = await enablePluginWithVerification(
page,
'API Test Plugin',
10000 * timeoutMultiplier, // Reduced from 15s to 10s
);
if (!pluginEnabled) {
throw new Error('Failed to enable API Test Plugin');
}
// Wait for plugin to appear in menu (navigates to work view internally)
const pluginInMenu = await waitForPluginInMenu(
page,
'API Test Plugin',
15000 * timeoutMultiplier, // Reduced from 20s to 15s
);
if (!pluginInMenu) {
// Log state for debugging
await logPluginState(page);
throw new Error('API Test Plugin not found in menu after enabling');
}
// Dismiss tour dialog if present (non-blocking)
const tourDialog = page.locator('[data-shepherd-step-id="Welcome"]');
if (await tourDialog.isVisible().catch(() => false)) {
const cancelBtn = page.locator(
'button:has-text("No thanks"), .shepherd-cancel-icon',
);
if (await cancelBtn.isVisible().catch(() => false)) {
await cancelBtn.click();
// Wait for dialog to disappear
await tourDialog.waitFor({ state: 'hidden' });
}
}
});
test('open plugin iframe view', async ({ page }) => {
// Plugin nav item should already be visible from beforeEach
const pluginMenuItem = page
.locator(PLUGIN_NAV_ITEMS)
.filter({ hasText: 'API Test Plugin' });
// Click plugin menu item
await pluginMenuItem.click();
// Wait for navigation to plugin page
await page.waitForURL(/\/plugins\/api-test-plugin\/index/);
// Wait for iframe to be visible
const iframe = page.locator(PLUGIN_IFRAME);
await iframe.waitFor({ state: 'visible' });
// Verify iframe is loaded
await expect(iframe).toBeVisible();
});
test('verify iframe loads with correct content', async ({ page }) => {
// Navigate directly to plugin page
await page.goto('/#/plugins/api-test-plugin/index');
// Wait for iframe to be visible
const iframe = page.locator(PLUGIN_IFRAME);
await iframe.waitFor({ state: 'visible' });
// Verify iframe exists and is visible
await expect(iframe).toBeVisible();
// Try to verify iframe content if possible
// Note: Cross-origin iframes may not allow content access
const frameLocator = page.frameLocator(PLUGIN_IFRAME);
try {
// Wait for iframe body to be loaded
await frameLocator.locator('body').waitFor({ state: 'visible' });
// Check for expected content if accessible
const h1 = frameLocator.locator('h1');
const hasH1 = (await h1.count()) > 0;
if (hasH1) {
await expect(h1).toContainText('API Test Plugin');
}
} catch (error) {
// If iframe content is not accessible due to cross-origin restrictions,
// at least verify the iframe element itself is present
// console.log('Note: Iframe content verification skipped (possibly cross-origin)');
await expect(iframe).toBeVisible();
}
});
});