mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-01-23 02:36:05 +00:00
SuperSync page object improvements: - Add networkidle wait before interacting with sync dialog - Add explicit mat-dialog-container wait before form interaction - Add toBeAttached() assertions for element stability - Use toPass() with progressive backoff for dropdown interactions - Dismiss existing dropdown overlays before retrying - Add blur() calls in password change dialog for Angular validation - Add try-catch for fresh client dialog race condition Task detail tests: - Add blur() after time input fill to ensure Angular registers the change before clicking Save These changes fix intermittent failures when running E2E tests with multiple workers in parallel.
303 lines
8.3 KiB
TypeScript
303 lines
8.3 KiB
TypeScript
import { expect } from '@playwright/test';
|
|
import {
|
|
getTaskElement,
|
|
getDoneTaskElement,
|
|
getSubtaskElement,
|
|
getDoneSubtaskElement,
|
|
getUndoneSubtaskElement,
|
|
getTaskCount,
|
|
getTaskTitles,
|
|
hasTaskOnClient,
|
|
type SimulatedE2EClient,
|
|
} from './supersync-helpers';
|
|
|
|
/**
|
|
* Assertion helpers for SuperSync E2E tests.
|
|
*
|
|
* These provide reusable, readable assertions for common sync test patterns.
|
|
*/
|
|
|
|
// ============================================================================
|
|
// Task Visibility Assertions
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Assert a task is visible on a client.
|
|
*
|
|
* @param client - The simulated E2E client
|
|
* @param taskName - The task name to check
|
|
* @param timeout - Optional timeout in ms (default: 10000)
|
|
*/
|
|
export const expectTaskVisible = async (
|
|
client: SimulatedE2EClient,
|
|
taskName: string,
|
|
timeout = 10000,
|
|
): Promise<void> => {
|
|
const task = getTaskElement(client, taskName);
|
|
await expect(task).toBeVisible({ timeout });
|
|
};
|
|
|
|
/**
|
|
* Assert a task is NOT visible on a client.
|
|
*
|
|
* @param client - The simulated E2E client
|
|
* @param taskName - The task name to check
|
|
* @param timeout - Optional timeout in ms (default: 10000)
|
|
*/
|
|
export const expectTaskNotVisible = async (
|
|
client: SimulatedE2EClient,
|
|
taskName: string,
|
|
timeout = 10000,
|
|
): Promise<void> => {
|
|
const task = getTaskElement(client, taskName);
|
|
await expect(task).not.toBeVisible({ timeout });
|
|
};
|
|
|
|
/**
|
|
* Assert a task is done (visible with done state).
|
|
*
|
|
* @param client - The simulated E2E client
|
|
* @param taskName - The task name to check
|
|
* @param timeout - Optional timeout in ms (default: 10000)
|
|
*/
|
|
export const expectTaskDone = async (
|
|
client: SimulatedE2EClient,
|
|
taskName: string,
|
|
timeout = 10000,
|
|
): Promise<void> => {
|
|
const task = getDoneTaskElement(client, taskName);
|
|
await expect(task).toBeVisible({ timeout });
|
|
};
|
|
|
|
/**
|
|
* Assert a subtask is visible.
|
|
*
|
|
* @param client - The simulated E2E client
|
|
* @param taskName - The subtask name to check
|
|
* @param timeout - Optional timeout in ms (default: 10000)
|
|
*/
|
|
export const expectSubtaskVisible = async (
|
|
client: SimulatedE2EClient,
|
|
taskName: string,
|
|
timeout = 10000,
|
|
): Promise<void> => {
|
|
const task = getSubtaskElement(client, taskName);
|
|
await expect(task).toBeVisible({ timeout });
|
|
};
|
|
|
|
/**
|
|
* Assert a subtask is done.
|
|
*
|
|
* @param client - The simulated E2E client
|
|
* @param taskName - The subtask name to check
|
|
* @param timeout - Optional timeout in ms (default: 5000)
|
|
*/
|
|
export const expectSubtaskDone = async (
|
|
client: SimulatedE2EClient,
|
|
taskName: string,
|
|
timeout = 5000,
|
|
): Promise<void> => {
|
|
const task = getDoneSubtaskElement(client, taskName);
|
|
await expect(task).toBeVisible({ timeout });
|
|
};
|
|
|
|
/**
|
|
* Assert a subtask is NOT done.
|
|
*
|
|
* @param client - The simulated E2E client
|
|
* @param taskName - The subtask name to check
|
|
* @param timeout - Optional timeout in ms (default: 5000)
|
|
*/
|
|
export const expectSubtaskNotDone = async (
|
|
client: SimulatedE2EClient,
|
|
taskName: string,
|
|
timeout = 5000,
|
|
): Promise<void> => {
|
|
const task = getUndoneSubtaskElement(client, taskName);
|
|
await expect(task).toBeVisible({ timeout });
|
|
};
|
|
|
|
// ============================================================================
|
|
// Multi-Client Assertions
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Assert a task exists on all provided clients.
|
|
*
|
|
* @param clients - Array of simulated E2E clients
|
|
* @param taskName - The task name to check
|
|
* @param timeout - Optional timeout in ms (default: 10000)
|
|
*/
|
|
export const expectTaskOnAllClients = async (
|
|
clients: SimulatedE2EClient[],
|
|
taskName: string,
|
|
timeout = 10000,
|
|
): Promise<void> => {
|
|
await Promise.all(
|
|
clients.map((client) => expectTaskVisible(client, taskName, timeout)),
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Assert a task does NOT exist on any of the provided clients.
|
|
*
|
|
* @param clients - Array of simulated E2E clients
|
|
* @param taskName - The task name to check
|
|
* @param timeout - Optional timeout in ms (default: 10000)
|
|
*/
|
|
export const expectTaskNotOnAnyClient = async (
|
|
clients: SimulatedE2EClient[],
|
|
taskName: string,
|
|
timeout = 10000,
|
|
): Promise<void> => {
|
|
await Promise.all(
|
|
clients.map((client) => expectTaskNotVisible(client, taskName, timeout)),
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Assert a task is done on all provided clients.
|
|
*
|
|
* @param clients - Array of simulated E2E clients
|
|
* @param taskName - The task name to check
|
|
* @param timeout - Optional timeout in ms (default: 10000)
|
|
*/
|
|
export const expectTaskDoneOnAllClients = async (
|
|
clients: SimulatedE2EClient[],
|
|
taskName: string,
|
|
timeout = 10000,
|
|
): Promise<void> => {
|
|
await Promise.all(clients.map((client) => expectTaskDone(client, taskName, timeout)));
|
|
};
|
|
|
|
/**
|
|
* Assert task count is equal across all clients.
|
|
*
|
|
* @param clients - Array of simulated E2E clients
|
|
*/
|
|
export const expectEqualTaskCount = async (
|
|
clients: SimulatedE2EClient[],
|
|
): Promise<void> => {
|
|
const counts = await Promise.all(clients.map((client) => getTaskCount(client)));
|
|
const firstCount = counts[0];
|
|
for (let i = 1; i < counts.length; i++) {
|
|
expect(counts[i]).toBe(firstCount);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Assert task count is a specific value on a client.
|
|
*
|
|
* @param client - The simulated E2E client
|
|
* @param expectedCount - The expected task count
|
|
*/
|
|
export const expectTaskCount = (
|
|
client: SimulatedE2EClient,
|
|
expectedCount: number,
|
|
): Promise<void> => {
|
|
return getTaskCount(client).then((count) => {
|
|
expect(count).toBe(expectedCount);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Assert task order matches across clients.
|
|
*
|
|
* @param clientA - First client
|
|
* @param clientB - Second client
|
|
*/
|
|
export const expectTaskOrderMatches = async (
|
|
clientA: SimulatedE2EClient,
|
|
clientB: SimulatedE2EClient,
|
|
): Promise<void> => {
|
|
const orderA = await getTaskTitles(clientA);
|
|
const orderB = await getTaskTitles(clientB);
|
|
expect(orderA).toEqual(orderB);
|
|
};
|
|
|
|
/**
|
|
* Assert all clients have the same task order.
|
|
*
|
|
* @param clients - Array of simulated E2E clients
|
|
*/
|
|
export const expectSameTaskOrder = async (
|
|
clients: SimulatedE2EClient[],
|
|
): Promise<void> => {
|
|
if (clients.length < 2) return;
|
|
|
|
const orders = await Promise.all(clients.map((client) => getTaskTitles(client)));
|
|
const firstOrder = orders[0];
|
|
for (let i = 1; i < orders.length; i++) {
|
|
expect(orders[i]).toEqual(firstOrder);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Assert a task exists on a client (boolean check).
|
|
*
|
|
* @param client - The simulated E2E client
|
|
* @param taskName - The task name to check
|
|
* @param exists - Whether the task should exist (default: true)
|
|
*/
|
|
export const expectTaskExists = async (
|
|
client: SimulatedE2EClient,
|
|
taskName: string,
|
|
exists = true,
|
|
): Promise<void> => {
|
|
const hasIt = await hasTaskOnClient(client, taskName);
|
|
expect(hasIt).toBe(exists);
|
|
};
|
|
|
|
// ============================================================================
|
|
// Consistency Assertions
|
|
// ============================================================================
|
|
|
|
/**
|
|
* Assert all clients have consistent state (same task count and tasks visible).
|
|
*
|
|
* @param clients - Array of simulated E2E clients
|
|
* @param taskNames - Array of task names that should exist on all clients
|
|
*/
|
|
export const expectConsistentState = async (
|
|
clients: SimulatedE2EClient[],
|
|
taskNames: string[],
|
|
): Promise<void> => {
|
|
await expectEqualTaskCount(clients);
|
|
for (const taskName of taskNames) {
|
|
await expectTaskOnAllClients(clients, taskName);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Assert time tracking indicator is visible on a task.
|
|
*
|
|
* @param client - The simulated E2E client
|
|
* @param taskName - The task name
|
|
* @param timeout - Optional timeout in ms (default: 5000)
|
|
*/
|
|
export const expectTimeTrackingActive = async (
|
|
client: SimulatedE2EClient,
|
|
taskName: string,
|
|
timeout = 5000,
|
|
): Promise<void> => {
|
|
const task = getTaskElement(client, taskName);
|
|
const indicator = task.locator('.play-icon-indicator');
|
|
await expect(indicator).toBeVisible({ timeout });
|
|
};
|
|
|
|
/**
|
|
* Assert time tracking indicator is NOT visible on a task.
|
|
*
|
|
* @param client - The simulated E2E client
|
|
* @param taskName - The task name
|
|
* @param timeout - Optional timeout in ms (default: 5000)
|
|
*/
|
|
export const expectTimeTrackingInactive = async (
|
|
client: SimulatedE2EClient,
|
|
taskName: string,
|
|
timeout = 5000,
|
|
): Promise<void> => {
|
|
const task = getTaskElement(client, taskName);
|
|
const indicator = task.locator('.play-icon-indicator');
|
|
await expect(indicator).not.toBeVisible({ timeout });
|
|
};
|