Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions suites/playwright/suite.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
image: ghcr.io/agynio/e2e/playwright:v1.59.1-noble
workdir: /opt/app/data
select: |
suite_tags=("svc_console" "svc_gateway" "svc_threads" "svc_identity" "smoke")

if [ -z "${TAGS:-}" ]; then
echo "playwright"
exit 0
fi

for tag in ${TAGS}; do
if [ "$tag" = "svc_console" ] || [ "$tag" = "smoke" ]; then
echo "$tag"
exit 0
fi
for suite_tag in "${suite_tags[@]}"; do
if [ "$tag" = "$suite_tag" ]; then
echo "$tag"
exit 0
fi
done
done
run: |
set -euo pipefail
Expand Down
47 changes: 47 additions & 0 deletions suites/playwright/test/e2e/organization-threads-smoke.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { test, expect } from './fixtures';
import {
createOrganization,
createThread,
createUser,
getMe,
sendThreadMessage,
setSelectedOrganization,
} from './console-api';

test.describe('organization-threads-smoke', {
tag: ['@svc_console', '@svc_gateway', '@svc_threads', '@svc_identity', '@smoke'],
}, () => {
test('threads list loads with data', async ({ page }) => {
const organizationId = await createOrganization(page, `e2e-org-threads-smoke-${Date.now()}`);
await setSelectedOrganization(page, organizationId);
const me = await getMe(page);
const identityId = me.user?.meta?.id;
if (!identityId) {
throw new Error('GetMe response missing identity id for threads smoke test.');
}

const participantId = await createUser(page, {
email: `e2e-thread-smoke-${Date.now()}@agyn.test`,
nickname: 'thread-smoke',
});

const threadId = await createThread(page, { organizationId, participantIds: [participantId] });
await sendThreadMessage(page, { threadId, senderId: identityId, body: 'Smoke thread message.' });

const threadsLoaded = page.waitForResponse(
(resp) => resp.url().includes('ListOrganizationThreads'),
{ timeout: 20000 },
);

await page.goto(`/organizations/${organizationId}/threads`);
const threadsResponse = await threadsLoaded;
expect(threadsResponse.status()).toBe(200);
await expect(page.getByTestId('organization-threads-table')).toBeVisible({ timeout: 20000 });
const rows = page.getByTestId('organization-thread-row');
const matchingRow = rows.filter({ hasText: threadId });
await expect(matchingRow).toBeVisible({ timeout: 20000 });
await expect(page.getByTestId('organization-threads-empty')).toHaveCount(0, { timeout: 20000 });
await expect(page.getByText('Failed to load threads.')).toHaveCount(0);
await expect(page.getByText('You do not have permission to view threads.')).toHaveCount(0);
});
});
2 changes: 1 addition & 1 deletion suites/playwright/test/e2e/organization-threads.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
setSelectedOrganization,
} from './console-api';

test.describe('organization-threads', { tag: ['@svc_console'] }, () => {
test.describe('organization-threads', { tag: ['@svc_console', '@svc_gateway', '@svc_threads', '@svc_identity'] }, () => {
test('org threads list and detail pagination', async ({ page }) => {
const organizationId = await createOrganization(page, `e2e-org-threads-${Date.now()}`);
await setSelectedOrganization(page, organizationId);
Expand Down
29 changes: 29 additions & 0 deletions suites/playwright/test/e2e/workloads-layout.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { test, expect } from './fixtures';
import { createOrganization, setSelectedOrganization } from './console-api';

test.describe('workloads-layout', { tag: ['@svc_console', '@svc_gateway', '@smoke'] }, () => {
test('workloads header lays out across columns', async ({ page }) => {
const organizationId = await createOrganization(page, `e2e-workloads-layout-${Date.now()}`);
await setSelectedOrganization(page, organizationId);

await page.goto(`/organizations/${organizationId}/activity/workloads`);
const header = page.getByTestId('organization-workloads-header');
await expect(header).toBeVisible({ timeout: 15000 });
await header.scrollIntoViewIfNeeded();

const agentHeader = header.getByRole('button', { name: 'Agent' });
const statusHeader = header.getByRole('button', { name: 'Status' });
await expect(agentHeader).toBeVisible();
await expect(statusHeader).toBeVisible();

const agentBox = await agentHeader.boundingBox();
const statusBox = await statusHeader.boundingBox();
if (!agentBox || !statusBox) {
throw new Error('Workloads header bounding boxes missing.');
}

const rowOffset = Math.abs(agentBox.y - statusBox.y);
expect(rowOffset).toBeLessThan(24);
expect(statusBox.x).toBeGreaterThan(agentBox.x + 120);
});
});
Loading