Skip to content

Commit 4224f3b

Browse files
committed
feat: integration test
1 parent eccc055 commit 4224f3b

5 files changed

Lines changed: 258 additions & 9 deletions

File tree

.github/workflows/test.yml

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,34 @@ jobs:
6262
with:
6363
node-version: '24.x'
6464
- run: npm ci
65-
- run: npm run test:lint
65+
- run: npm run test:lint
66+
67+
integration:
68+
runs-on: ubuntu-latest
69+
needs: build
70+
steps:
71+
- uses: actions/checkout@v4
72+
- uses: actions/download-artifact@v4
73+
with:
74+
name: dist
75+
path: ./dist
76+
- uses: actions/setup-node@v4
77+
with:
78+
node-version: '24.x'
79+
- run: npm ci
80+
- run: npx playwright install --with-deps
81+
- run: npm run test:integration
82+
env:
83+
CI: true
84+
RETRIES: 0
85+
WORKERS: 1
86+
- if: always()
87+
uses: actions/upload-artifact@v4
88+
with:
89+
name: test-results
90+
path: integration/test-results
91+
- if: always()
92+
uses: actions/upload-artifact@v4
93+
with:
94+
name: playwright-report
95+
path: integration/playwright-report

.husky/pre-push

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
npm run build
33
npm run test:types
44
npm run test:lint
5-
npm run test:tu
5+
npm run test:tu
6+
npm run test:integration

integration/vue/pages/FormOne.vue

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,24 @@ const sameField = useMultiLayout({
3333
name: useTextInput({
3434
label: "Name",
3535
class: "grid-col-6",
36-
dataParser: DPE.string().min(3).max(20),
36+
dataParser: DPE.string()
37+
.min(3, { errorMessage: "Nom trop cours" })
38+
.max(20, { errorMessage: "Nom trop long" }),
3739
}),
3840
price: useNumberInput({
3941
label: "Price",
4042
class: "grid-col-6",
41-
dataParser: DPE.number().min(1),
43+
dataParser: DPE.number().min(1, { errorMessage: "Prix invalide" }),
4244
}),
4345
fields: useSectionLayout(
4446
useCheckLayout(
4547
useRepeatLayout(
4648
useMultiLayout({
4749
fieldName: useTextInput({
4850
label: "Nom du champ",
49-
dataParser: DPE.string().min(3).max(20),
51+
dataParser: DPE.string()
52+
.min(3, { errorMessage: "Nom de champ trop cours" })
53+
.max(20, { errorMessage: "Nom de champ trop long" }),
5054
}),
5155
fieldType: useUnionLayout(
5256
[
@@ -192,9 +196,10 @@ function submit() {
192196
</script>
193197

194198
<template>
195-
<div>
199+
<div data-testid="form-one">
196200
<Form @submit="submit">
197201
<PrimaryButton
202+
data-testid="submit-button"
198203
type="submit"
199204
label="submit"
200205
:disabled="
@@ -205,11 +210,11 @@ function submit() {
205210
</Form>
206211

207212
<div id="current-value">
208-
{{ currentValue }}
213+
{{ JSON.stringify(currentValue) }}
209214
</div>
210215

211216
<div id="checked-value">
212-
{{ checkedValue }}
217+
{{ JSON.stringify(checkedValue) }}
213218
</div>
214219
</div>
215220
</template>
Lines changed: 212 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,218 @@
1+
import { Actions, Assertions, createComponent, createPage } from "@duplojs/playwright";
12
import { testClient } from "@testClient";
23

34
testClient.describe("form one", () => {
4-
testClient("go on form page and submit form", ({ website }) => {
5+
const HumanForm = createComponent("humanForm", {
6+
getMainElement: ({ body }) => body.locator(".DFV-deep_FRM_UNI-human_MUL"),
7+
getElements: ({ mainElement }) => ({
8+
nameField: mainElement.locator("#FRM_UNI-human_MUL-name_INP"),
9+
errorNameField: mainElement.locator(".DFV-deep_FRM_UNI-human_MUL-name_INP > .DFV-grid-error"),
510

11+
priceField: mainElement.locator("#FRM_UNI-human_MUL-price_INP"),
12+
errorPriceField: mainElement.locator(".DFV-deep_FRM_UNI-human_MUL-price_INP > .DFV-grid-error"),
13+
14+
errorFields: mainElement.locator(".DFV-deep_FRM_UNI-human_MUL-fields_SEC_CHK > .DFV-grid-error"),
15+
16+
nameOfFirstField: mainElement.locator(".DFV-deep_FRM_UNI-human_MUL-fields_SEC_CHK_REP-0_MUL-fieldName_INP > input"),
17+
errorNameOfFirstField: mainElement.locator(".DFV-deep_FRM_UNI-human_MUL-fields_SEC_CHK_REP-0_MUL-fieldName_INP > .DFV-grid-error"),
18+
maxCharOfFirstField: mainElement.locator("#FRM_UNI-human_MUL-fields_SEC_CHK_REP-0_MUL-fieldType_UNI-text_CHK_MUL-max_INP"),
19+
20+
nameOfSecondField: mainElement.locator(".DFV-deep_FRM_UNI-human_MUL-fields_SEC_CHK_REP-1_MUL-fieldName_INP > input"),
21+
selectTypeOnSecondField: mainElement.locator("#select-FRM_UNI-human_MUL-fields_SEC_CHK_REP-1_MUL-fieldType_UNI"),
22+
firstLabelOnSecondField: mainElement.locator("#FRM_UNI-human_MUL-fields_SEC_CHK_REP-1_MUL-fieldType_UNI-select_SEC_REP-0_MUL-label_INP"),
23+
firstValueOnSecondField: mainElement.locator("#FRM_UNI-human_MUL-fields_SEC_CHK_REP-1_MUL-fieldType_UNI-select_SEC_REP-0_MUL-value_INP"),
24+
secondLabelOnSecondField: mainElement.locator("#FRM_UNI-human_MUL-fields_SEC_CHK_REP-1_MUL-fieldType_UNI-select_SEC_REP-1_MUL-label_INP"),
25+
secondValueOnSecondField: mainElement.locator("#FRM_UNI-human_MUL-fields_SEC_CHK_REP-1_MUL-fieldType_UNI-select_SEC_REP-1_MUL-value_INP"),
26+
27+
addFieldButton: mainElement.locator(".DFV-deep_FRM_UNI-human_MUL-fields_SEC_CHK_REP > .DFV-grid-repeat-add > button"),
28+
}),
29+
});
30+
31+
const AIAgentForm = createComponent("aIAgentForm", {
32+
getMainElement: ({ body }) => body.locator(".DFV-deep_FRM_UNI-AIAgent_STP"),
33+
getElements: ({ mainElement }) => ({
34+
nameField: mainElement.locator("#FRM_UNI-AIAgent_STP-0_MUL-name_INP"),
35+
}),
36+
});
37+
38+
const FormOnePage = createPage("formOne", {
39+
makePath: () => "form-one",
40+
getMainElement: ({ body }) => body.getByTestId("form-one"),
41+
getElements: ({ mainElement }) => ({
42+
submitButton: mainElement.getByTestId("submit-button"),
43+
selectInputTypeForm: mainElement.locator("#select-FRM_UNI"),
44+
currentValue: mainElement.locator("#current-value"),
45+
checkedValue: mainElement.locator("#checked-value"),
46+
}),
47+
components: [HumanForm, AIAgentForm],
48+
});
49+
50+
testClient("define name on human form and switch form and return on human form and see defined value on name", async({ website }) => {
51+
const page = await website.iNavigateTo(FormOnePage);
52+
53+
await Assertions.toBeVisible(page, "submitButton");
54+
await Assertions.toBeVisible(page, "selectInputTypeForm");
55+
56+
const humanForm = await page.iWantToSeeComponent("humanForm");
57+
58+
await Assertions.toContainText(page, "currentValue", JSON.stringify({
59+
kind: "human",
60+
value: {
61+
name: "",
62+
price: 0,
63+
fields: [
64+
{
65+
fieldName: "",
66+
fieldType: {
67+
kind: "text",
68+
value: {
69+
min: 5,
70+
max: 30,
71+
},
72+
},
73+
},
74+
],
75+
},
76+
}));
77+
78+
await Actions.fill(humanForm, "nameField", "superName");
79+
80+
await Actions.selectOption(page, "selectInputTypeForm", "AIAgent");
81+
82+
await Assertions.toContainText(page, "currentValue", JSON.stringify({
83+
kind: "AIAgent",
84+
value: {
85+
currentStep: 0,
86+
steps: [
87+
{
88+
name: "",
89+
price: 0,
90+
fields: [
91+
{
92+
fieldName: "",
93+
fieldType: {
94+
kind: "text",
95+
value: {
96+
min: 5,
97+
max: 30,
98+
},
99+
},
100+
},
101+
],
102+
},
103+
{
104+
route: "",
105+
routePing: "",
106+
key: "",
107+
},
108+
],
109+
},
110+
}));
111+
112+
await page.iWantToSeeComponent("aIAgentForm");
113+
114+
await Actions.selectOption(page, "selectInputTypeForm", "human");
115+
116+
await page.iWantToSeeComponent("humanForm");
117+
118+
await Assertions.toHaveValue(humanForm, "nameField", "superName");
119+
120+
await Assertions.toContainText(page, "currentValue", JSON.stringify({
121+
kind: "human",
122+
value: {
123+
name: "superName",
124+
price: 0,
125+
fields: [
126+
{
127+
fieldName: "",
128+
fieldType: {
129+
kind: "text",
130+
value: {
131+
min: 5,
132+
max: 30,
133+
},
134+
},
135+
},
136+
],
137+
},
138+
}));
139+
});
140+
141+
testClient("submit human form and see error field", async({ website }) => {
142+
const page = await website.iNavigateTo(FormOnePage);
143+
await Assertions.toContainText(page, "checkedValue", "");
144+
145+
const humanForm = await page.iWantToSeeComponent("humanForm");
146+
147+
await Actions.click(page, "submitButton");
148+
149+
await Assertions.toContainText(humanForm, "errorNameField", "Nom trop cours");
150+
await Assertions.toContainText(humanForm, "errorPriceField", "Prix invalide");
151+
await Assertions.toContainText(humanForm, "errorNameOfFirstField", "Nom de champ trop cours");
152+
await Assertions.toContainText(page, "checkedValue", "");
153+
});
154+
155+
testClient("submit human form with a text field and a select field", async({ website }) => {
156+
const page = await website.iNavigateTo(FormOnePage);
157+
158+
const humanForm = await page.iWantToSeeComponent("humanForm");
159+
160+
await Actions.fill(humanForm, "nameField", "test");
161+
await Actions.fill(humanForm, "priceField", "12");
162+
await Actions.fill(humanForm, "nameOfFirstField", "field1");
163+
await Actions.fill(humanForm, "maxCharOfFirstField", "20");
164+
165+
await Actions.click(humanForm, "addFieldButton");
166+
167+
await Actions.fill(humanForm, "nameOfSecondField", "field1");
168+
await Actions.selectOption(humanForm, "selectTypeOnSecondField", "select");
169+
await Actions.fill(humanForm, "firstLabelOnSecondField", "toto");
170+
await Actions.fill(humanForm, "firstValueOnSecondField", "yoyo");
171+
await Actions.fill(humanForm, "secondLabelOnSecondField", "tata");
172+
await Actions.fill(humanForm, "secondValueOnSecondField", "ploplo");
173+
174+
await Actions.click(page, "submitButton");
175+
176+
await Assertions.toContainText(humanForm, "errorFields", "Les noms de champ suivant sont utilisais en double : field1.");
177+
178+
await Actions.fill(humanForm, "nameOfSecondField", "field2");
179+
180+
await Actions.click(page, "submitButton");
181+
182+
await Assertions.toContainText(page, "checkedValue", JSON.stringify({
183+
kind: "human",
184+
value: {
185+
name: "test",
186+
price: 12,
187+
fields: [
188+
{
189+
fieldName: "field1",
190+
fieldType: {
191+
kind: "text",
192+
value: {
193+
min: 5,
194+
max: 20,
195+
},
196+
},
197+
},
198+
{
199+
fieldName: "field2",
200+
fieldType: {
201+
kind: "select",
202+
value: [
203+
{
204+
label: "toto",
205+
value: "yoyo",
206+
},
207+
{
208+
label: "tata",
209+
value: "ploplo",
210+
},
211+
],
212+
},
213+
},
214+
],
215+
},
216+
}));
6217
});
7218
});

integration/vue/playwright.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { defineConfig, devices } from "playwright/test";
22
import { envs } from "./envs";
3+
import { stringToMillisecond } from "@duplojs/utils";
34

45
export default defineConfig({
56
testDir: "./pages",
67
fullyParallel: true,
78
forbidOnly: envs.CI,
89
retries: envs.RETRIES,
910
workers: envs.WORKERS,
11+
timeout: stringToMillisecond("5s"),
1012
webServer: {
1113
command: "npx vite --config vite.config.js --port 1301",
1214
url: envs.BASE_URL,

0 commit comments

Comments
 (0)