Merge pull request 'fix(test): persist API key + anchor rights selector + idempotent createUser' (#19) from claude/sandbox-provision-run into main
This commit was merged in pull request #19.
This commit is contained in:
@@ -68,6 +68,11 @@ async function createUser(
|
|||||||
const { page, dolibarrAddress, imgFolderPath } = globalCtx;
|
const { page, dolibarrAddress, imgFolderPath } = globalCtx;
|
||||||
await login.doAdminLogin(globalCtx);
|
await login.doAdminLogin(globalCtx);
|
||||||
|
|
||||||
|
// Idempotent: if the login already exists (e.g. a re-run), return its id rather
|
||||||
|
// than submitting a duplicate create (which Dolibarr rejects).
|
||||||
|
const existingId = await findUserId(globalCtx, userLogin);
|
||||||
|
if (existingId !== undefined) return existingId;
|
||||||
|
|
||||||
await page.goto(`${dolibarrAddress}/user/card.php?action=create&mode=create`);
|
await page.goto(`${dolibarrAddress}/user/card.php?action=create&mode=create`);
|
||||||
|
|
||||||
// Fill text inputs (login, lastname, password) without submitting yet.
|
// Fill text inputs (login, lastname, password) without submitting yet.
|
||||||
@@ -128,6 +133,30 @@ async function readUserIdFromPage(page: Page): Promise<number | undefined> {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Find an existing user's numeric id by login via the user list, so createUser is
|
||||||
|
idempotent across re-runs. Matches the table row containing the login, then reads
|
||||||
|
the id from that row's user-card link.
|
||||||
|
*/
|
||||||
|
async function findUserId(
|
||||||
|
globalCtx: UserCtx,
|
||||||
|
userLogin: string,
|
||||||
|
): Promise<number | undefined> {
|
||||||
|
const { page, dolibarrAddress } = globalCtx;
|
||||||
|
await page.goto(
|
||||||
|
`${dolibarrAddress}/user/list.php?search_login=${encodeURIComponent(userLogin)}`,
|
||||||
|
);
|
||||||
|
await page.waitForLoadState("domcontentloaded");
|
||||||
|
const cardLink = page
|
||||||
|
.locator("tr", { hasText: userLogin })
|
||||||
|
.locator('a[href*="/user/card.php?id="]')
|
||||||
|
.first();
|
||||||
|
if (await cardLink.count() === 0) return undefined;
|
||||||
|
const href = (await cardLink.getAttribute("href")) ?? "";
|
||||||
|
const m = href.match(/[?&]id=(\d+)/);
|
||||||
|
return m ? Number(m[1]) : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Grant a set of rights to a user on /user/perms.php?id=<userId>.
|
Grant a set of rights to a user on /user/perms.php?id=<userId>.
|
||||||
|
|
||||||
@@ -150,10 +179,11 @@ async function assignRights(
|
|||||||
// which would otherwise stale the locators.
|
// which would otherwise stale the locators.
|
||||||
await page.goto(`${dolibarrAddress}/user/perms.php?id=${userId}`);
|
await page.goto(`${dolibarrAddress}/user/perms.php?id=${userId}`);
|
||||||
|
|
||||||
// GUESS: the grant control is an <a> linking to action=addrights&rights=<id>.
|
// The grant control is an <a> linking to action=addrights&rights=<id>. The
|
||||||
// We match on the href substring to avoid depending on row layout / icons.
|
// trailing "&" anchors the id so rights=12 does NOT substring-match rights=121
|
||||||
|
// / rights=1232 etc. (Dolibarr hrefs are ...&rights=<id>&confirm=yes...).
|
||||||
const addLink = page.locator(
|
const addLink = page.locator(
|
||||||
`a[href*="action=addrights"][href*="rights=${rightId}"]`,
|
`a[href*="action=addrights"][href*="rights=${rightId}&"]`,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (await addLink.count() === 0) {
|
if (await addLink.count() === 0) {
|
||||||
@@ -245,6 +275,18 @@ async function generateApiKey(
|
|||||||
`id=${userId}.`,
|
`id=${userId}.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Persist: the generate control only fills the field client-side. Submit the
|
||||||
|
// edit form so Dolibarr saves api_key to the DB — otherwise it stays NULL and
|
||||||
|
// the generated key never authenticates.
|
||||||
|
const saveBtn = page.locator('input[name="save"], button[name="save"]');
|
||||||
|
if (await saveBtn.count() > 0) {
|
||||||
|
await saveBtn.first().click();
|
||||||
|
} else {
|
||||||
|
await page.click(':nth-match(input[type="submit"], 1)');
|
||||||
|
}
|
||||||
|
await page.waitForLoadState("domcontentloaded");
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user