work in progress with deno
This commit is contained in:
@@ -5,6 +5,7 @@ import login from "./scripts/login.ts";
|
|||||||
import companySetup, { Company } from "./scripts/admin/companySetup.ts";
|
import companySetup, { Company } from "./scripts/admin/companySetup.ts";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import displaySetup from "./scripts/admin/displaySetup.ts";
|
import displaySetup from "./scripts/admin/displaySetup.ts";
|
||||||
|
import moduleSetup from "./scripts/admin/moduleSetup.ts";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Initialisation
|
Initialisation
|
||||||
@@ -69,7 +70,10 @@ const globalCtx = {
|
|||||||
// await companySetup.setupCompany(globalCtx, company);
|
// await companySetup.setupCompany(globalCtx, company);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await displaySetup.setupDisplay(globalCtx);
|
// await displaySetup.setupDisplay(globalCtx);
|
||||||
|
await moduleSetup.configureModule(globalCtx, {moduleName: 'TIERS' ,enabled: false, onConfiguration: async () => {
|
||||||
|
await globalCtx.page.screenshot({path: 'save.png'})
|
||||||
|
}});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
test/save.png
BIN
test/save.png
Binary file not shown.
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 104 KiB |
@@ -61,7 +61,23 @@ async function setupLoginPage(
|
|||||||
]),
|
]),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function setGlobalCSS(
|
||||||
|
{ page, dolibarrAddress, imgFolderPath }: {
|
||||||
|
page: Page;
|
||||||
|
dolibarrAddress: string;
|
||||||
|
imgFolderPath: string;
|
||||||
|
}, cssStyleSheet: string) {
|
||||||
|
await page.goto(`${dolibarrAddress}/admin/ihm.php?mode=css`);
|
||||||
|
await forms.fillForm(
|
||||||
|
{page, imgFolderPath},
|
||||||
|
{cssStyleSheet},
|
||||||
|
new Map([
|
||||||
|
["cssStyleSheet","MAIN_IHM_CUSTOM_CSSaceeditorid:ace"]
|
||||||
|
]),
|
||||||
|
1,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setupDisplay(
|
async function setupDisplay(
|
||||||
@@ -73,17 +89,22 @@ async function setupDisplay(
|
|||||||
},
|
},
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await login.doAdminLogin(globalCtx);
|
await login.doAdminLogin(globalCtx);
|
||||||
await removeLoginForgottenPasswordLink(globalCtx);
|
// await removeLoginForgottenPasswordLink(globalCtx);
|
||||||
await setupLoginPage(globalCtx, {
|
// await setupLoginPage(globalCtx, {
|
||||||
removeHelpLink: true,
|
// removeHelpLink: true,
|
||||||
HTMLMessage: `
|
// HTMLMessage: `
|
||||||
<div style="text-align:center"><span style="color:#000000">Bienvenue chez </span><span style="color:#2c3e50"><em>Gabriel Radureau</em></span><br />
|
// <div style="text-align:center"><span style="color:#000000">Bienvenue chez </span><span style="color:#2c3e50"><em>Gabriel Radureau</em></span><br />
|
||||||
<span style="color:#000000"><em>l'</em></span><span style="color:#e74c3c"><em>ar</em></span><span style="color:#c0392b"><em>change</em></span><span style="color:#000000"><em> du </em></span><span style="color:#2ecc71"><em>code</em></span><br />
|
// <span style="color:#000000"><em>l'</em></span><span style="color:#e74c3c"><em>ar</em></span><span style="color:#c0392b"><em>change</em></span><span style="color:#000000"><em> du </em></span><span style="color:#2ecc71"><em>code</em></span><br />
|
||||||
<span style="color:#000000">🏹💻🪽<br />
|
// <span style="color:#000000">🏹💻🪽<br />
|
||||||
<em><span style="font-size:8px">Pariez sur le bon sagitaire</span></em></span></div>
|
// <em><span style="font-size:8px">Pariez sur le bon sagitaire</span></em></span></div>
|
||||||
`.trim(),
|
// `.trim(),
|
||||||
backgroundImage: "$IMG/loginBackground.jpeg",
|
// backgroundImage: "$IMG/loginBackground.jpeg",
|
||||||
});
|
// });
|
||||||
|
await setGlobalCSS(globalCtx, `
|
||||||
|
body {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
`.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|||||||
47
test/scripts/admin/moduleSetup.ts
Normal file
47
test/scripts/admin/moduleSetup.ts
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
|
||||||
|
// info-box
|
||||||
|
|
||||||
|
import { Page } from "playwright";
|
||||||
|
import forms from "../forms.ts";
|
||||||
|
import login from "../login.ts";
|
||||||
|
|
||||||
|
// span.info-box-title has-text /moduleName/
|
||||||
|
// span.fa-cog[title="Configuration"]
|
||||||
|
|
||||||
|
async function configureModule(
|
||||||
|
globalCtx: {
|
||||||
|
page: Page;
|
||||||
|
dolibarrAddress: string;
|
||||||
|
adminCredentials: { username: string; password: string };
|
||||||
|
},
|
||||||
|
{
|
||||||
|
moduleName,
|
||||||
|
enabled,
|
||||||
|
onConfiguration,
|
||||||
|
}: {
|
||||||
|
moduleName: string;
|
||||||
|
enabled: boolean;
|
||||||
|
onConfiguration?: CallableFunction;
|
||||||
|
}
|
||||||
|
): Promise<void> {
|
||||||
|
const {page, dolibarrAddress}= globalCtx;
|
||||||
|
await login.doAdminLogin(globalCtx);
|
||||||
|
|
||||||
|
await page.goto(`${dolibarrAddress}/admin/modules.php?mode=commonkanban`);
|
||||||
|
|
||||||
|
const moduleDiv = page.locator('.info-box', {
|
||||||
|
has: page.locator('.info-box-title',{
|
||||||
|
hasText: new RegExp('^'+moduleName+'\n?$','i')
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
await forms.toggleOnOff(moduleDiv, enabled);
|
||||||
|
if(enabled && onConfiguration!==undefined) {
|
||||||
|
await moduleDiv.locator(`span.fa-cog[title="Configuration"]`).click();
|
||||||
|
await onConfiguration();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
configureModule,
|
||||||
|
}
|
||||||
4
test/scripts/admin/modules/tiers
Normal file
4
test/scripts/admin/modules/tiers
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Divers
|
||||||
|
|
||||||
|
## Modèle de génération et contrôle des codes tiers (client ou fournisseur)
|
||||||
|
|
||||||
2971
test/scripts/admin/modules/tiers.html
Normal file
2971
test/scripts/admin/modules/tiers.html
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,17 +1,52 @@
|
|||||||
import type { Page } from "playwright";
|
import type { Locator, Page } from "playwright";
|
||||||
|
|
||||||
async function toggleOnOff({page}:{page:Page}, label: string, on: boolean) : Promise<void>{
|
/*
|
||||||
|
CKEditor - The WYSIWYG Editor https://ckeditor.com/wysiwyg-editor-open-source/
|
||||||
|
*/
|
||||||
|
async function CKEditor(
|
||||||
|
{ page }: { page: Page },
|
||||||
|
inputName: string,
|
||||||
|
value: string,
|
||||||
|
): Promise<void> {
|
||||||
|
const col = page.locator("td", {
|
||||||
|
has: page.locator(`textarea[name="${inputName}"]`),
|
||||||
|
});
|
||||||
|
// const htmlEditor = col.frameLocator('iframe').locator('body');
|
||||||
|
const rawHTMLEditor = col.locator("textarea.cke_editable");
|
||||||
|
|
||||||
const row = page.locator("tr").filter({
|
const htmlToggleBtn = col.getByRole("button").filter({ hasText: /Source/ });
|
||||||
has: page.locator("td", { hasText: label }),
|
await htmlToggleBtn.click();
|
||||||
});
|
await rawHTMLEditor.fill(value);
|
||||||
const hideBtn = row.locator(`[title="Désactivé"]`);
|
await htmlToggleBtn.click();
|
||||||
const showBtn = row.locator(`[title="Actif"]`);
|
}
|
||||||
if (!await hideBtn.isVisible() && !await showBtn.isVisible()) {
|
|
||||||
throw new Error("Show/Hide button not found");
|
/*
|
||||||
}
|
Ace - The High Performance Code Editor for the Web https://ace.c9.io/
|
||||||
if (on && await hideBtn.isVisible()) await hideBtn.click();
|
*/
|
||||||
if (!on && await showBtn.isVisible()) await showBtn.click();
|
async function ACE(
|
||||||
|
{ page }: { page: Page },
|
||||||
|
inputName: string,
|
||||||
|
value: string,
|
||||||
|
): Promise<void> {
|
||||||
|
const input = page.locator(`pre[id="${inputName}"]`).locator("textarea");
|
||||||
|
await input.focus();
|
||||||
|
const CtrlKey = Deno.build.os === 'darwin' ? 'Meta' : 'Control';
|
||||||
|
await page.keyboard.press(CtrlKey+"+A")
|
||||||
|
await page.keyboard.press("Backspace")
|
||||||
|
await input.fill(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function toggleOnOff(
|
||||||
|
containerLocator: Locator,
|
||||||
|
on: boolean,
|
||||||
|
): Promise<void> {
|
||||||
|
const hideBtn = containerLocator.locator(`[title="Désactivé"]`);
|
||||||
|
const showBtn = containerLocator.locator(`[title="Actif"], [title="Activé"]`);
|
||||||
|
if (!await hideBtn.isVisible() && !await showBtn.isVisible()) {
|
||||||
|
throw new Error("Show/Hide button not found");
|
||||||
|
}
|
||||||
|
if (on && await hideBtn.isVisible()) await hideBtn.click();
|
||||||
|
if (!on && await showBtn.isVisible()) await showBtn.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fonction générique `fillForm` pour remplir des formulaires
|
// Fonction générique `fillForm` pour remplir des formulaires
|
||||||
@@ -19,7 +54,7 @@ async function fillForm<T>(
|
|||||||
{ page, imgFolderPath }: { page: Page; imgFolderPath: string },
|
{ page, imgFolderPath }: { page: Page; imgFolderPath: string },
|
||||||
data: T,
|
data: T,
|
||||||
inputNames: Map<keyof T, string>,
|
inputNames: Map<keyof T, string>,
|
||||||
submit: number = 0,
|
submit: number = 0, // submit is a number to specify which submit buttton to use, 0 means no submit
|
||||||
) {
|
) {
|
||||||
for (const [attr, input] of inputNames) {
|
for (const [attr, input] of inputNames) {
|
||||||
const attrValue = data[attr];
|
const attrValue = data[attr];
|
||||||
@@ -43,20 +78,19 @@ async function fillForm<T>(
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "cke": { // CKEditor https://ckeditor.com/wysiwyg-editor-open-source/
|
case "cke":
|
||||||
const col = page.locator("td", {has: page.locator(`textarea[name="${inputName}"]`)});
|
CKEditor({ page }, inputName, attrValue as string);
|
||||||
const htmlEditor = col.frameLocator('iframe').locator('body');
|
break;
|
||||||
const rawHTMLEditor = col.locator('textarea.cke_editable');
|
case "ace":
|
||||||
|
await ACE({ page }, inputName, attrValue as string);
|
||||||
const htmlToggleBtn = col.getByRole("button").filter({hasText: /Source/});
|
|
||||||
await htmlToggleBtn.click();
|
|
||||||
await rawHTMLEditor.fill(attrValue as string);
|
|
||||||
await htmlToggleBtn.click();
|
|
||||||
await htmlEditor.screenshot({path: 'save.png'});
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case "toggle":
|
case "toggle":
|
||||||
await toggleOnOff({page}, inputName, Boolean(JSON.parse(attrValue as string)))
|
await toggleOnOff(
|
||||||
|
page.locator("tr").filter({
|
||||||
|
has: page.locator("td", { hasText: inputName }),
|
||||||
|
}),
|
||||||
|
Boolean(JSON.parse(attrValue as string)),
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
await page.fill(
|
await page.fill(
|
||||||
@@ -72,4 +106,7 @@ async function fillForm<T>(
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
fillForm,
|
fillForm,
|
||||||
|
toggleOnOff,
|
||||||
|
CKEditor,
|
||||||
|
ACE,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user