@shopbite-de/storefront 1.5.2 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,124 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { mountSuspended } from "@nuxt/test-utils/runtime";
3
+ import { mockNuxtImport } from "@nuxt/test-utils/runtime";
4
+ import Header from "~/components/Header.vue";
5
+ import { ref, reactive, toRefs } from "vue";
6
+
7
+ const mocks = vi.hoisted(() => ({
8
+ state: {
9
+ isLoggedIn: false,
10
+ isGuestSession: false,
11
+ user: null as any,
12
+ },
13
+ logout: vi.fn(),
14
+ }));
15
+
16
+ const reactiveState = reactive(mocks.state);
17
+
18
+ mockNuxtImport("useUser", () => () => ({
19
+ ...toRefs(reactiveState),
20
+ logout: mocks.logout,
21
+ }));
22
+
23
+ mockNuxtImport("useShopBiteConfig", () => () => ({
24
+ isCheckoutEnabled: ref(true),
25
+ }));
26
+
27
+ mockNuxtImport("useCart", () => () => ({
28
+ count: ref(0),
29
+ }));
30
+
31
+ mockNuxtImport("useRuntimeConfig", () => () => ({
32
+ app: {
33
+ baseURL: "/",
34
+ },
35
+ public: {
36
+ site: {
37
+ name: "ShopBite",
38
+ },
39
+ shopware: {
40
+ devStorefrontUrl: "http://localhost:3000",
41
+ },
42
+ },
43
+ }));
44
+
45
+ // Mock Nuxt Content queryCollection
46
+ mockNuxtImport("queryCollection", () => (collection: string) => ({
47
+ first: () =>
48
+ Promise.resolve({
49
+ main: [],
50
+ account: {
51
+ loggedIn: [
52
+ [{ label: "Mein Konto", type: "label" }],
53
+ [
54
+ { label: "Konto", icon: "i-lucide-user", to: "/konto" },
55
+ {
56
+ label: "Bestellungen",
57
+ icon: "i-lucide-pizza",
58
+ to: "/konto/bestellungen",
59
+ },
60
+ ],
61
+ [{ label: "Abmelden", icon: "i-lucide-log-out", action: "logout" }],
62
+ ],
63
+ loggedOut: [
64
+ [{ label: "Jetzt anmelden", type: "label" }],
65
+ [{ label: "Zur Anmeldung", icon: "i-lucide-user", to: "/anmelden" }],
66
+ ],
67
+ },
68
+ }),
69
+ }));
70
+
71
+ describe("Header", () => {
72
+ beforeEach(() => {
73
+ reactiveState.isLoggedIn = false;
74
+ reactiveState.isGuestSession = false;
75
+ reactiveState.user = null;
76
+ vi.clearAllMocks();
77
+ });
78
+
79
+ it("renders correctly when logged out", async () => {
80
+ const component = await mountSuspended(Header);
81
+ // Should show user icon
82
+ expect(component.html()).toContain("i-lucide:user");
83
+ // Should NOT show checkmark chip
84
+ expect(component.html()).not.toContain("✓");
85
+ });
86
+
87
+ it("renders correctly when logged in", async () => {
88
+ reactiveState.isLoggedIn = true;
89
+ reactiveState.user = { firstName: "John", lastName: "Doe" };
90
+ const component = await mountSuspended(Header);
91
+
92
+ // Should show checkmark chip
93
+ expect(component.html()).toContain("✓");
94
+ });
95
+
96
+ it("renders correctly for guest session", async () => {
97
+ reactiveState.isGuestSession = true;
98
+ reactiveState.user = { firstName: "Guest", lastName: "User" };
99
+ const component = await mountSuspended(Header);
100
+
101
+ // Should show checkmark chip for guest session too
102
+ expect(component.html()).toContain("✓");
103
+ });
104
+
105
+ it("filters menu items for guest session", async () => {
106
+ reactiveState.isGuestSession = true;
107
+ reactiveState.user = { firstName: "Guest", lastName: "User" };
108
+ const component = await mountSuspended(Header);
109
+
110
+ // Find the dropdown menu
111
+ const dropdown = component.findComponent({ name: "UDropdownMenu" });
112
+ expect(dropdown.exists()).toBe(true);
113
+
114
+ const items = dropdown.props("items");
115
+
116
+ // Group 0 should have the user label
117
+ // Group 1 should be gone (filtered out because it only contained links)
118
+ // Group 2 (now index 1) should have logout
119
+ expect(items.length).toBe(2);
120
+ expect(items[0][0].label).toBe("Guest User");
121
+ expect(items[1][0].label).toBe("Abmelden");
122
+ expect(items[1][0].onSelect).toBeDefined();
123
+ });
124
+ });
@@ -0,0 +1,141 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { mountSuspended } from "@nuxt/test-utils/runtime";
3
+ import LoginForm from "@/components/User/LoginForm.vue";
4
+ import { useUser } from "@shopware/composables";
5
+ import { ApiClientError } from "@shopware/api-client";
6
+
7
+ vi.mock("@shopware/api-client", () => ({
8
+ ApiClientError: class extends Error {
9
+ details: any;
10
+ constructor(details: any) {
11
+ super("ApiClientError");
12
+ this.details = details;
13
+ }
14
+ },
15
+ }));
16
+
17
+ vi.mock("@shopware/composables", () => ({
18
+ useUser: vi.fn(),
19
+ useWishlist: vi.fn(() => ({
20
+ mergeWishlistProducts: vi.fn(),
21
+ })),
22
+ }));
23
+
24
+ const mockToastAdd = vi.fn();
25
+ mockNuxtImport("useToast", () => {
26
+ return () => ({
27
+ add: mockToastAdd,
28
+ });
29
+ });
30
+
31
+ describe("LoginForm", () => {
32
+ let loginMock: any;
33
+ let userMock: any;
34
+
35
+ beforeEach(() => {
36
+ vi.clearAllMocks();
37
+ loginMock = vi.fn();
38
+ userMock = { value: { firstName: "John", lastName: "Doe" } };
39
+ (useUser as any).mockReturnValue({
40
+ isLoggedIn: { value: false },
41
+ login: loginMock,
42
+ user: userMock,
43
+ });
44
+ });
45
+
46
+ it("should show success toast on successful login", async () => {
47
+ loginMock.mockResolvedValueOnce({});
48
+ const wrapper = await mountSuspended(LoginForm);
49
+
50
+ // Call onSubmit directly if form trigger is not working in test
51
+ await (wrapper.vm as any).onSubmit({
52
+ data: {
53
+ email: "test@example.com",
54
+ password: "password123",
55
+ },
56
+ });
57
+
58
+ expect(loginMock).toHaveBeenCalledWith({
59
+ username: "test@example.com",
60
+ password: "password123",
61
+ });
62
+
63
+ expect(mockToastAdd).toHaveBeenCalledWith(
64
+ expect.objectContaining({
65
+ title: "Hallo John Doe!",
66
+ color: "success",
67
+ }),
68
+ );
69
+ });
70
+
71
+ it("should show error toast on failed login", async () => {
72
+ loginMock.mockRejectedValueOnce(new Error("Invalid credentials"));
73
+ const wrapper = await mountSuspended(LoginForm);
74
+
75
+ // Call onSubmit directly if form trigger is not working in test
76
+ await (wrapper.vm as any).onSubmit({
77
+ data: {
78
+ email: "test@example.com",
79
+ password: "wrongpassword",
80
+ },
81
+ });
82
+
83
+ expect(loginMock).toHaveBeenCalled();
84
+
85
+ expect(mockToastAdd).toHaveBeenCalledWith(
86
+ expect.objectContaining({
87
+ title: "Login fehlgeschlagen",
88
+ description: "Bitte überprüfen Sie Ihre Zugangsdaten.",
89
+ color: "error",
90
+ }),
91
+ );
92
+ });
93
+
94
+ it("should show detailed error toast on ApiClientError", async () => {
95
+ const apiClientError = new ApiClientError({
96
+ errors: [
97
+ {
98
+ detail: 'The email address "test@example.com" is already in use',
99
+ },
100
+ ],
101
+ });
102
+ loginMock.mockRejectedValueOnce(apiClientError);
103
+ const wrapper = await mountSuspended(LoginForm);
104
+
105
+ await (wrapper.vm as any).onSubmit({
106
+ data: {
107
+ email: "test@example.com",
108
+ password: "password123",
109
+ },
110
+ });
111
+
112
+ expect(mockToastAdd).toHaveBeenCalledWith(
113
+ expect.objectContaining({
114
+ title: "Login fehlgeschlagen",
115
+ description: 'The email address "test@example.com" is already in use',
116
+ color: "error",
117
+ }),
118
+ );
119
+ });
120
+
121
+ it("should handle ApiClientError with missing errors gracefully", async () => {
122
+ const apiClientError = new ApiClientError({});
123
+ loginMock.mockRejectedValueOnce(apiClientError);
124
+ const wrapper = await mountSuspended(LoginForm);
125
+
126
+ await (wrapper.vm as any).onSubmit({
127
+ data: {
128
+ email: "test@example.com",
129
+ password: "password123",
130
+ },
131
+ });
132
+
133
+ expect(mockToastAdd).toHaveBeenCalledWith(
134
+ expect.objectContaining({
135
+ title: "Login fehlgeschlagen",
136
+ description: "Bitte überprüfen Sie Ihre Zugangsdaten.",
137
+ color: "error",
138
+ }),
139
+ );
140
+ });
141
+ });
@@ -0,0 +1,78 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { mountSuspended, mockNuxtImport } from "@nuxt/test-utils/runtime";
3
+ import PaymentAndDelivery from "~/components/Checkout/PaymentAndDelivery.vue";
4
+ import { ref } from "vue";
5
+
6
+ const { mockSetPaymentMethod, mockSetShippingMethod, mockRefreshCart } =
7
+ vi.hoisted(() => ({
8
+ mockSetPaymentMethod: vi.fn(),
9
+ mockSetShippingMethod: vi.fn(),
10
+ mockRefreshCart: vi.fn(),
11
+ }));
12
+
13
+ mockNuxtImport("useCheckout", () => () => ({
14
+ paymentMethods: ref([
15
+ { id: "pm1", distinguishableName: "Payment 1" },
16
+ { id: "pm2", distinguishableName: "Payment 2" },
17
+ ]),
18
+ shippingMethods: ref([
19
+ { id: "sm1", name: "Shipping 1" },
20
+ { id: "sm2", name: "Shipping 2" },
21
+ ]),
22
+ selectedPaymentMethod: ref({ id: "pm1", distinguishableName: "Payment 1" }),
23
+ selectedShippingMethod: ref({ id: "sm1", name: "Shipping 1" }),
24
+ setPaymentMethod: mockSetPaymentMethod,
25
+ setShippingMethod: mockSetShippingMethod,
26
+ getPaymentMethods: vi.fn(),
27
+ getShippingMethods: vi.fn(),
28
+ }));
29
+
30
+ mockNuxtImport("useCart", () => () => ({
31
+ refreshCart: mockRefreshCart,
32
+ }));
33
+
34
+ mockNuxtImport("useToast", () => () => ({
35
+ add: vi.fn(),
36
+ }));
37
+
38
+ describe("PaymentAndDelivery", () => {
39
+ beforeEach(() => {
40
+ vi.clearAllMocks();
41
+ });
42
+
43
+ it("renders correctly", async () => {
44
+ const wrapper = await mountSuspended(PaymentAndDelivery);
45
+ expect(wrapper.exists()).toBeTruthy();
46
+ expect(wrapper.text()).toContain("Zahlungsarten");
47
+ expect(wrapper.text()).toContain("Versandarten");
48
+ });
49
+
50
+ it("updates payment method when changed", async () => {
51
+ const wrapper = await mountSuspended(PaymentAndDelivery);
52
+
53
+ // @ts-ignore - access internal state
54
+ wrapper.vm.selectedPaymentMethodId = "pm2";
55
+ await new Promise((resolve) => setTimeout(resolve, 50));
56
+
57
+ expect(mockSetPaymentMethod).toHaveBeenCalledWith({ id: "pm2" });
58
+ });
59
+
60
+ it("updates shipping method and refreshes cart when changed", async () => {
61
+ const wrapper = await mountSuspended(PaymentAndDelivery);
62
+
63
+ // @ts-ignore - access internal state
64
+ wrapper.vm.selectedShippingMethodId = "sm2";
65
+ await new Promise((resolve) => setTimeout(resolve, 50));
66
+
67
+ expect(mockSetShippingMethod).toHaveBeenCalledWith({ id: "sm2" });
68
+ expect(mockRefreshCart).toHaveBeenCalled();
69
+ });
70
+
71
+ it("renders help buttons with correct links", async () => {
72
+ const wrapper = await mountSuspended(PaymentAndDelivery);
73
+ const helpButtons = wrapper.findAll(
74
+ 'a[href="/unternehmen/zahlung-und-versand"]',
75
+ );
76
+ expect(helpButtons.length).toBe(2);
77
+ });
78
+ });
@@ -0,0 +1,255 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import { ref, nextTick } from "vue";
3
+ import { mountSuspended, mockNuxtImport } from "@nuxt/test-utils/runtime";
4
+ import RegistrationForm from "~/components/User/RegistrationForm.vue";
5
+ import { ApiClientError } from "@shopware/api-client";
6
+
7
+ vi.mock("@shopware/api-client", () => ({
8
+ ApiClientError: class extends Error {
9
+ details: any;
10
+ constructor(details: any) {
11
+ super("ApiClientError");
12
+ this.details = details;
13
+ }
14
+ },
15
+ }));
16
+
17
+ const { mockRegister, mockIsLoggedIn, mockGetSuggestions } = vi.hoisted(() => {
18
+ return {
19
+ mockRegister: vi.fn(),
20
+ mockIsLoggedIn: { value: false },
21
+ mockGetSuggestions: vi.fn().mockResolvedValue([]),
22
+ };
23
+ });
24
+
25
+ mockNuxtImport("useUser", () => () => ({
26
+ register: mockRegister,
27
+ isLoggedIn: ref(mockIsLoggedIn.value),
28
+ }));
29
+
30
+ mockNuxtImport("useAddressAutocomplete", () => () => ({
31
+ getSuggestions: mockGetSuggestions,
32
+ }));
33
+
34
+ const mockToastAdd = vi.fn();
35
+ mockNuxtImport("useToast", () => () => ({
36
+ add: mockToastAdd,
37
+ }));
38
+
39
+ // Mock useRuntimeConfig
40
+ mockNuxtImport("useRuntimeConfig", () => () => ({
41
+ public: {
42
+ shopware: {
43
+ devStorefrontUrl: "http://localhost:3000",
44
+ },
45
+ site: {
46
+ countryId: "default-country-id",
47
+ },
48
+ },
49
+ }));
50
+
51
+ describe("RegistrationForm", () => {
52
+ beforeEach(() => {
53
+ vi.clearAllMocks();
54
+ mockIsLoggedIn.value = false;
55
+ });
56
+
57
+ it("renders correctly", async () => {
58
+ const wrapper = await mountSuspended(RegistrationForm);
59
+ expect(wrapper.exists()).toBeTruthy();
60
+ expect(wrapper.find('input[name="email"]').exists()).toBe(true);
61
+ });
62
+
63
+ it("shows company field only for business account", async () => {
64
+ const wrapper = await mountSuspended(RegistrationForm);
65
+
66
+ // Initially private, so company field should NOT be in billing address
67
+ expect(wrapper.find('input[name="billingAddress.company"]').exists()).toBe(
68
+ false,
69
+ );
70
+
71
+ // Switch to business
72
+ // @ts-ignore
73
+ wrapper.vm.state.accountType = "business";
74
+ await nextTick();
75
+ await new Promise((resolve) => setTimeout(resolve, 50));
76
+
77
+ // Try to find by name again
78
+ expect(wrapper.find('input[name="billingAddress.company"]').exists()).toBe(
79
+ true,
80
+ );
81
+ });
82
+
83
+ it("shows shipping address fields when checkbox is checked", async () => {
84
+ const wrapper = await mountSuspended(RegistrationForm);
85
+
86
+ // Initial count of street inputs
87
+ const initialStreets = wrapper.findAll(
88
+ 'input[name="billingAddress.street"]',
89
+ ).length;
90
+
91
+ // @ts-ignore
92
+ wrapper.vm.state.isShippingAddressDifferent = true;
93
+ await nextTick();
94
+ await new Promise((resolve) => setTimeout(resolve, 50));
95
+
96
+ // Should have more street inputs now (billing street + shipping street)
97
+ expect(wrapper.findAll('input[name$=".street"]').length).toBeGreaterThan(
98
+ initialStreets,
99
+ );
100
+ });
101
+
102
+ it("submits the form with correct data", async () => {
103
+ const wrapper = await mountSuspended(RegistrationForm);
104
+
105
+ // Fill required fields
106
+ await wrapper.find('input[name="firstName"]').setValue("John");
107
+ await wrapper.find('input[name="lastName"]').setValue("Doe");
108
+ await wrapper.find('input[name="email"]').setValue("john@example.com");
109
+
110
+ // Billing address fields (AddressFields component)
111
+ // Manually update state since USelectMenu is hard to interact with in simple tests
112
+ // @ts-ignore
113
+ wrapper.vm.state.billingAddress.street = "Musterstr 1";
114
+ // Set zipcode and city directly since fields are removed
115
+ // @ts-ignore
116
+ wrapper.vm.state.billingAddress.zipcode = "12345";
117
+ // @ts-ignore
118
+ wrapper.vm.state.billingAddress.city = "Musterstadt";
119
+
120
+ await wrapper
121
+ .find('input[name="billingAddress.phoneNumber"]')
122
+ .setValue("12345678");
123
+
124
+ // Accept data protection
125
+ const dpCheckbox = wrapper.find('input[name="acceptedDataProtection"]');
126
+ await dpCheckbox.trigger("click");
127
+ await new Promise((resolve) => setTimeout(resolve, 0));
128
+
129
+ // Submit
130
+ await wrapper.find("form").trigger("submit");
131
+
132
+ // Wait for async validation and submission
133
+ await new Promise((resolve) => setTimeout(resolve, 100));
134
+
135
+ expect(mockRegister).toHaveBeenCalled();
136
+ const calledData = mockRegister.mock.calls[0][0];
137
+ expect(calledData.email).toBe("john@example.com");
138
+ expect(calledData.billingAddress.street).toBe("Musterstr 1");
139
+ // Check if firstName/lastName were copied to billing address as per logic in onSubmit
140
+ expect(calledData.billingAddress.firstName).toBe("John");
141
+ expect(calledData.billingAddress.lastName).toBe("Doe");
142
+ });
143
+
144
+ it("shows detailed error toast on ApiClientError during registration", async () => {
145
+ const apiClientError = new ApiClientError({
146
+ errors: [
147
+ {
148
+ detail: 'The email address "lirim@veliu.net" is already in use',
149
+ },
150
+ ],
151
+ });
152
+ mockRegister.mockRejectedValueOnce(apiClientError);
153
+ const wrapper = await mountSuspended(RegistrationForm);
154
+
155
+ // Fill minimum required fields to trigger onSubmit
156
+ await wrapper.find('input[name="firstName"]').setValue("John");
157
+ await wrapper.find('input[name="lastName"]').setValue("Doe");
158
+ await wrapper.find('input[name="email"]').setValue("lirim@veliu.net");
159
+ // @ts-ignore
160
+ wrapper.vm.state.billingAddress.street = "Musterstr 1";
161
+ // @ts-ignore
162
+ wrapper.vm.state.billingAddress.city = "Musterstadt";
163
+ await wrapper
164
+ .find('input[name="billingAddress.phoneNumber"]')
165
+ .setValue("12345678");
166
+ await wrapper.find('input[name="acceptedDataProtection"]').trigger("click");
167
+
168
+ await wrapper.find("form").trigger("submit");
169
+ await new Promise((resolve) => setTimeout(resolve, 100));
170
+
171
+ expect(mockToastAdd).toHaveBeenCalledWith(
172
+ expect.objectContaining({
173
+ title: "Registrierung fehlgeschlagen",
174
+ description: 'The email address "lirim@veliu.net" is already in use',
175
+ color: "error",
176
+ }),
177
+ );
178
+ });
179
+
180
+ it("handles ApiClientError with missing errors gracefully", async () => {
181
+ const apiClientError = new ApiClientError({});
182
+ mockRegister.mockRejectedValueOnce(apiClientError);
183
+ const wrapper = await mountSuspended(RegistrationForm);
184
+
185
+ // Fill minimum required fields to trigger onSubmit
186
+ await wrapper.find('input[name="firstName"]').setValue("John");
187
+ await wrapper.find('input[name="lastName"]').setValue("Doe");
188
+ await wrapper.find('input[name="email"]').setValue("lirim@veliu.net");
189
+ // @ts-ignore
190
+ wrapper.vm.state.billingAddress.street = "Musterstr 1";
191
+ // @ts-ignore
192
+ wrapper.vm.state.billingAddress.city = "Musterstadt";
193
+ await wrapper
194
+ .find('input[name="billingAddress.phoneNumber"]')
195
+ .setValue("12345678");
196
+ await wrapper.find('input[name="acceptedDataProtection"]').trigger("click");
197
+
198
+ await wrapper.find("form").trigger("submit");
199
+ await new Promise((resolve) => setTimeout(resolve, 100));
200
+
201
+ expect(mockToastAdd).toHaveBeenCalledWith(
202
+ expect.objectContaining({
203
+ title: "Registrierung fehlgeschlagen",
204
+ description: "Bitte versuchen Sie es erneut.",
205
+ color: "error",
206
+ }),
207
+ );
208
+ });
209
+
210
+ it("shows correction suggestion and stops submission when address needs correction", async () => {
211
+ mockGetSuggestions.mockResolvedValueOnce([
212
+ {
213
+ street: "Corrected Street 123",
214
+ city: "Corrected City",
215
+ zipcode: "54321",
216
+ label: "Corrected Street 123, 54321 Corrected City",
217
+ },
218
+ ]);
219
+
220
+ const wrapper = await mountSuspended(RegistrationForm);
221
+
222
+ // Fill required fields
223
+ await wrapper.find('input[name="firstName"]').setValue("John");
224
+ await wrapper.find('input[name="lastName"]').setValue("Doe");
225
+ await wrapper.find('input[name="email"]').setValue("john@example.com");
226
+ // @ts-ignore
227
+ wrapper.vm.state.billingAddress.street = "Musterstr 1";
228
+ // @ts-ignore
229
+ wrapper.vm.state.billingAddress.zipcode = "12345";
230
+ // @ts-ignore
231
+ wrapper.vm.state.billingAddress.city = "Musterstadt";
232
+ await wrapper
233
+ .find('input[name="billingAddress.phoneNumber"]')
234
+ .setValue("12345678");
235
+ await wrapper.find('input[name="acceptedDataProtection"]').trigger("click");
236
+
237
+ await wrapper.find("form").trigger("submit");
238
+ await new Promise((resolve) => setTimeout(resolve, 100));
239
+
240
+ // Should NOT have called register
241
+ expect(mockRegister).not.toHaveBeenCalled();
242
+
243
+ // Should have shown a toast
244
+ expect(mockToastAdd).toHaveBeenCalledWith(
245
+ expect.objectContaining({
246
+ title: "Adresskorrektur vorgeschlagen",
247
+ }),
248
+ );
249
+
250
+ // Should show the correction alert in the form
251
+ expect(wrapper.text()).toContain(
252
+ "Meinten Sie: Corrected Street 123, 54321 Corrected City?",
253
+ );
254
+ });
255
+ });
@@ -0,0 +1,39 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { mountSuspended } from "@nuxt/test-utils/runtime";
3
+ import RegistrationForm from "~/components/User/RegistrationForm.vue";
4
+ import { flushPromises } from "@vue/test-utils";
5
+
6
+ describe("RegistrationForm Validation", () => {
7
+ it("shows error for street when empty and clears it when filled", async () => {
8
+ const wrapper = await mountSuspended(RegistrationForm);
9
+
10
+ const form = wrapper.find("form");
11
+ await form.trigger("submit");
12
+ await flushPromises();
13
+
14
+ // Check for street error message
15
+ expect(wrapper.text()).toContain(
16
+ "Bitte geben Sie Ihre Straße und Hausnummer an.",
17
+ );
18
+
19
+ // Find the street input and fill it
20
+ const streetInput = wrapper.find('input[name="billingAddress.street"]');
21
+ await streetInput.setValue("Hauptstraße 1");
22
+
23
+ // Fill other required fields to satisfy overall validation if needed
24
+ const zipInput = wrapper.find('input[name="billingAddress.zipcode"]');
25
+ await zipInput.setValue("60311");
26
+ const cityInput = wrapper.find('input[name="billingAddress.city"]');
27
+ await cityInput.setValue("Frankfurt");
28
+
29
+ await flushPromises();
30
+
31
+ // Trigger validation again or check if error disappeared
32
+ await form.trigger("submit");
33
+ await flushPromises();
34
+
35
+ expect(wrapper.text()).not.toContain(
36
+ "Bitte geben Sie Ihre Straße und Hausnummer an.",
37
+ );
38
+ });
39
+ });