e2e: dispatch backup via source-group API
Per-host Run-backup is gone — the host_chrome partial still
renders the button but it's hard-disabled with a tooltip
pointing to per-source-group Run-now. The smoke test was
clicking that disabled button and waiting forever for a URL
change that would never happen.
Replace the navigation-based dispatch with two API calls:
create a source group covering the agent's /source mount,
then POST to /api/hosts/{id}/source-groups/{gid}/run. The
backup-status assertion at the end is unchanged — host record
is still the source of truth.
This commit is contained in:
@@ -107,6 +107,43 @@ export async function waitForHostStatus(
|
||||
throw new Error(`waitForHostStatus: timeout. Last seen: ${JSON.stringify(last)}`);
|
||||
}
|
||||
|
||||
export async function createSourceGroup(
|
||||
request: APIRequestContext,
|
||||
cookie: string,
|
||||
hostID: string,
|
||||
body: { name: string; includes: string[]; excludes?: string[] },
|
||||
): Promise<string> {
|
||||
const res = await request.post(`${baseURL}/api/hosts/${hostID}/source-groups`, {
|
||||
headers: { cookie, 'content-type': 'application/json' },
|
||||
data: {
|
||||
name: body.name,
|
||||
includes: body.includes,
|
||||
excludes: body.excludes ?? [],
|
||||
retention_policy: {},
|
||||
retry_max: 0,
|
||||
retry_backoff_seconds: 0,
|
||||
},
|
||||
});
|
||||
if (!res.ok()) throw new Error(`createSourceGroup: ${res.status()} ${await res.text()}`);
|
||||
const created = (await res.json()) as { id?: string; group?: { id?: string } };
|
||||
const id = created.id ?? created.group?.id;
|
||||
if (!id) throw new Error(`createSourceGroup: no id in response: ${JSON.stringify(created)}`);
|
||||
return id;
|
||||
}
|
||||
|
||||
export async function runSourceGroup(
|
||||
request: APIRequestContext,
|
||||
cookie: string,
|
||||
hostID: string,
|
||||
groupID: string,
|
||||
): Promise<void> {
|
||||
const res = await request.post(
|
||||
`${baseURL}/api/hosts/${hostID}/source-groups/${groupID}/run`,
|
||||
{ headers: { cookie } },
|
||||
);
|
||||
if (!res.ok()) throw new Error(`runSourceGroup: ${res.status()} ${await res.text()}`);
|
||||
}
|
||||
|
||||
export async function getSessionCookie(page: Page): Promise<string> {
|
||||
const cookies = await page.context().cookies();
|
||||
const c = cookies.find((c) => c.name === 'rm_session');
|
||||
|
||||
@@ -14,6 +14,8 @@ import {
|
||||
waitForPendingHostID,
|
||||
acceptPending,
|
||||
waitForHostStatus,
|
||||
createSourceGroup,
|
||||
runSourceGroup,
|
||||
getSessionCookie,
|
||||
} from './lib/server';
|
||||
|
||||
@@ -53,18 +55,19 @@ test.describe('smoke: enrol-via-announce → backup', () => {
|
||||
);
|
||||
expect(readyHost.id).toBeTruthy();
|
||||
|
||||
// Trigger a backup via the UI form-post (HX-Redirect to /jobs/{id}).
|
||||
await page.goto(`${baseURL}/hosts/${readyHost.id}`);
|
||||
await Promise.all([
|
||||
page.waitForURL(/\/jobs\//),
|
||||
page.locator('form[action$="/run-backup"] button[type="submit"]').first().click(),
|
||||
]);
|
||||
// Per-host Run-now is gone; backups are dispatched per
|
||||
// source-group now. Create one that maps to the agent's
|
||||
// /source mount, then kick it via the JSON API.
|
||||
const groupID = await createSourceGroup(request, cookie, readyHost.id, {
|
||||
name: 'default',
|
||||
includes: ['/source'],
|
||||
});
|
||||
await runSourceGroup(request, cookie, readyHost.id, groupID);
|
||||
|
||||
// Wait for the host's last_backup_status to flip to 'succeeded'.
|
||||
// The job page itself is harder to assert on (it uses
|
||||
// server-pushed updates and a reload-on-finish pattern); the
|
||||
// host record is the source of truth and is what the dashboard
|
||||
// surfaces.
|
||||
// The host record is the source of truth: it's what the
|
||||
// dashboard projects from job-completion events on the WS
|
||||
// channel.
|
||||
const finishedHost = await waitForHostStatus(
|
||||
request, cookie,
|
||||
(h) => h.id === readyHost.id && h.last_backup_status === 'succeeded',
|
||||
|
||||
Reference in New Issue
Block a user