Repository: shopware/frontends
Pull request #1169 (2024-07-26 16:05:40)

chore(deps-dev): bump the maintenance group across 1 directory with 2 updates
Bumps the maintenance group with 2 updates in the / directory: [husky](https://github.com/typicode/husky) and [vercel](https://github.com/vercel/vercel/tree/HEAD/packages/cli).

Updates `husky` from 9.1.1 to 9.1.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/typicode/husky/releases">husky's releases</a>.</em></p>
<blockquote>
<h2>v9.1.2</h2>
<p>Show a message instead of automatically removing deprecated code.</p>
<p>This only concerns projects that still have the following code in their hooks:</p>
<pre lang="diff"><code>- #!/usr/bin/env sh # &lt;- This is deprecated, remove it
- . &quot;$(dirname -- &quot;$0&quot;)/_/husky.sh&quot;  # &lt;- This is deprecated, remove it
<h1>Rest of your hook code</h1>
<p></code></pre></p>
<p><strong>Hooks with these lines will fail in <code>v10.0.0</code></strong></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/typicode/husky/commit/35fba846c4a9b83f64a95d8a0bde5aa648fdc449"><code>35fba84</code></a> 9.1.2</li>
<li><a href="https://github.com/typicode/husky/commit/20603175c10e35e58d1eadd20d08a491cfcc5b6a"><code>2060317</code></a> show message instead of automatically remove deprecated code</li>
<li><a href="https://github.com/typicode/husky/commit/f6cc4108837863bfbd31a861fdd8422637a492b1"><code>f6cc410</code></a> Update troubleshoot.md</li>
<li><a href="https://github.com/typicode/husky/commit/0c71e73246968d5c8bdb895d133b839b6a9cf4b2"><code>0c71e73</code></a> update package-lock.json</li>
<li>See full diff in <a href="https://github.com/typicode/husky/compare/v9.1.1...v9.1.2">compare view</a></li>
</ul>
</details>
<br />

Updates `vercel` from 35.1.0 to 35.2.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/vercel/vercel/releases">vercel's releases</a>.</em></p>
<blockquote>
<h2>vercel@35.2.1</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p>Allow custom environments in <code>vc pull --environment</code> (<a href="https://redirect.github.com/vercel/vercel/pull/11897">#11897</a>)</p>
</li>
<li>
<p><code>vc target</code> now prompts to link projects (<a href="https://redirect.github.com/vercel/vercel/pull/11895">#11895</a>)</p>
</li>
<li>
<p>Updated dependencies [<a href="https://github.com/vercel/vercel/commit/6c2398713cd7ea2f1511d56ce1c5120d9f8e3a98"><code>6c2398713</code></a>]:</p>
<ul>
<li><code>@​vercel/python</code><a href="https://github.com/4"><code>@​4</code></a>.3.1</li>
</ul>
</li>
</ul>
<h2>vercel@35.2.0</h2>
<h3>Minor Changes</h3>
<ul>
<li>Apply framework &quot;defaultRoutes&quot; in <code>vc build</code> (<a href="https://redirect.github.com/vercel/vercel/pull/11889">#11889</a>)</li>
</ul>
<h3>Patch Changes</h3>
<ul>
<li>
<p>fix(cli): wrong log line colors for deploy and inspect commands (<a href="https://redirect.github.com/vercel/vercel/pull/11891">#11891</a>)</p>
</li>
<li>
<p>Standardize target parsing between commands (<a href="https://redirect.github.com/vercel/vercel/pull/11890">#11890</a>)</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/vercel/vercel/blob/main/packages/cli/CHANGELOG.md">vercel's changelog</a>.</em></p>
<blockquote>
<h2>35.2.1</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p>Allow custom environments in <code>vc pull --environment</code> (<a href="https://redirect.github.com/vercel/vercel/pull/11897">#11897</a>)</p>
</li>
<li>
<p><code>vc target</code> now prompts to link projects (<a href="https://redirect.github.com/vercel/vercel/pull/11895">#11895</a>)</p>
</li>
<li>
<p>Updated dependencies [<a href="https://github.com/vercel/vercel/commit/6c2398713cd7ea2f1511d56ce1c5120d9f8e3a98"><code>6c2398713</code></a>]:</p>
<ul>
<li><code>@​vercel/python</code><a href="https://github.com/4"><code>@​4</code></a>.3.1</li>
</ul>
</li>
</ul>
<h2>35.2.0</h2>
<h3>Minor Changes</h3>
<ul>
<li>Apply framework &quot;defaultRoutes&quot; in <code>vc build</code> (<a href="https://redirect.github.com/vercel/vercel/pull/11889">#11889</a>)</li>
</ul>
<h3>Patch Changes</h3>
<ul>
<li>
<p>fix(cli): wrong log line colors for deploy and inspect commands (<a href="https://redirect.github.com/vercel/vercel/pull/11891">#11891</a>)</p>
</li>
<li>
<p>Standardize target parsing between commands (<a href="https://redirect.github.com/vercel/vercel/pull/11890">#11890</a>)</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/vercel/vercel/commit/46e52f8c98ef8f2bbecde42531bf13d9e17becc0"><code>46e52f8</code></a> Version Packages (<a href="https://github.com/vercel/vercel/tree/HEAD/packages/cli/issues/11899">#11899</a>)</li>
<li><a href="https://github.com/vercel/vercel/commit/955f37a27de499edf9120a75086d5e4fb52e6b4a"><code>955f37a</code></a> [cli] Add support for linking an unlinked project (<a href="https://github.com/vercel/vercel/tree/HEAD/packages/cli/issues/11895">#11895</a>)</li>
<li><a href="https://github.com/vercel/vercel/commit/73ea8a06783b9f1d0b89b6cecb8c1df3386fa68d"><code>73ea8a0</code></a> [cli] Remove validation on --environment for <code>vc pull</code> (<a href="https://github.com/vercel/vercel/tree/HEAD/packages/cli/issues/11897">#11897</a>)</li>
<li><a href="https://github.com/vercel/vercel/commit/7a99da85ddea30081d26171a112473e288335453"><code>7a99da8</code></a> Version Packages (<a href="https://github.com/vercel/vercel/tree/HEAD/packages/cli/issues/11888">#11888</a>)</li>
<li><a href="https://github.com/vercel/vercel/commit/8bb9880ee04c0e899b0a4954473a03fb9ec3b550"><code>8bb9880</code></a> [frameworks] Add FastHTML framework preset (<a href="https://github.com/vercel/vercel/tree/HEAD/packages/cli/issues/11889">#11889</a>)</li>
<li><a href="https://github.com/vercel/vercel/commit/c090add10b64d7c9c7b0fbe3975b7f3a879409c0"><code>c090add</code></a> fix(cli): wrong log line colors for deploy and inspect commands (<a href="https://github.com/vercel/vercel/tree/HEAD/packages/cli/issues/11891">#11891</a>)</li>
<li><a href="https://github.com/vercel/vercel/commit/194ea08ec4eda4da9deb3db1809793a3113206f4"><code>194ea08</code></a> [cli] Standardize target parsing (<a href="https://github.com/vercel/vercel/tree/HEAD/packages/cli/issues/11890">#11890</a>)</li>
<li>See full diff in <a href="https://github.com/vercel/vercel/commits/vercel@35.2.1/packages/cli">compare view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions


</details>

vercel[bot]: [vc]: #ZFLun+lVZs3uERlGLUhIVaqESnxWcBlknlgg4h32MTE=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJzaG9wd2FyZS1mcm9udGVuZHMtZG9jcyIsInJvb3REaXJlY3RvcnkiOiJhcHBzL2RvY3MvIiwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL3Nob3B3YXJlLWZyb250ZW5kcy9zaG9wd2FyZS1mcm9udGVuZHMtZG9jcy85MkhqOU5VVkVBN05SN0RZRDR6dEYyUnRuaXFuIiwicHJldmlld1VybCI6InNob3B3YXJlLWZyb250ZW5kcy1kb2NzLWdpdC1kZXBlbmRhYm8tZTI0MjMzLXNob3B3YXJlLWZyb250ZW5kcy52ZXJjZWwuYXBwIiwibmV4dENvbW1pdFN0YXR1cyI6IlBFTkRJTkcifV19
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Updated (UTC) |
| :--- | :----- | :------ | :------ |
| **shopware-frontends-docs** | 🔄 Building ([Inspect](https://vercel.com/shopware-frontends/shopware-frontends-docs/92Hj9NUVEA7NR7DYD4ztF2Rtniqn)) | [Visit Preview](https://shopware-frontends-docs-git-dependabo-e24233-shopware-frontends.vercel.app) | Jul 26, 2024 4:05pm |



Patch:
diff --git a/.github/workflows/codspeed.yaml b/.github/workflows/codspeed.yaml
index 246405f9..92feb525 100644
--- a/.github/workflows/codspeed.yaml
+++ b/.github/workflows/codspeed.yaml
@@ -34,6 +34,6 @@ jobs:
       - name: install
         run: pnpm install --frozen-lockfile --prefer-offline
       - name: Run benchmarks
-        uses: CodSpeedHQ/action@v2
+        uses: CodSpeedHQ/action@v3
         with:
           run: pnpm run test:bench
diff --git a/examples/b2b-quote-management/package.json b/examples/b2b-quote-management/package.json
index 798e0317..c67a4332 100644
--- a/examples/b2b-quote-management/package.json
+++ b/examples/b2b-quote-management/package.json
@@ -16,7 +16,7 @@
     "@shopware-pwa/helpers-next": "canary",
     "@shopware/api-client": "canary",
     "js-cookie": "3.0.5",
-    "primevue": "4.0.0",
+    "primevue": "4.0.2",
     "vue": "3.4.33",
     "vue-router": "4.4.0"
   },
diff --git a/package.json b/package.json
index 870d2b26..44c659bd 100644
--- a/package.json
+++ b/package.json
@@ -37,10 +37,10 @@
     "dotenv-cli": "7.4.2",
     "esno": "4.7.0",
     "globby": "14.0.2",
-    "husky": "9.1.1",
+    "husky": "9.1.2",
     "prettier": "3.3.3",
     "turbo": "2.0.9",
-    "vercel": "35.1.0"
+    "vercel": "35.2.1"
   },
   "engines": {
     "node": "^18.17.x || ^20.x"
diff --git a/packages/composables/src/index.ts b/packages/composables/src/index.ts
index 954b84c7..a07815b3 100644
--- a/packages/composables/src/index.ts
+++ b/packages/composables/src/index.ts
@@ -90,6 +90,7 @@ export function resolveCmsComponent(
       componentNameToResolve,
       resolvedComponent: undefined,
       resolved: false,
+      isResolved: false,
       error: (e as Error).message,
     };
   }
diff --git a/packages/composables/src/mocks/Order.ts b/packages/composables/src/mocks/Order.ts
index 09806fbb..66941438 100644
--- a/packages/composables/src/mocks/Order.ts
+++ b/packages/composables/src/mocks/Order.ts
@@ -1144,6 +1144,7 @@ const Order = {
   },
   paymentChangeable: {
     "018c6832f1a1731db276839b3f251fc2": true,
+    "123-test": true,
   },
 };
 
diff --git a/packages/composables/src/useListing.ts b/packages/composables/src/useListing.ts
index 4814f676..ad2cac14 100644
--- a/packages/composables/src/useListing.ts
+++ b/packages/composables/src/useListing.ts
@@ -73,7 +73,7 @@ export type UseListingReturn = {
    * Loads more (next page) elements to the listing
    */
   loadMore(
-    criteria: operations["searchPage post /search"]["body"],
+    criteria?: operations["searchPage post /search"]["body"],
   ): Promise<void>;
   /**
    * Listing that is currently set
diff --git a/packages/composables/src/useNotifications.ts b/packages/composables/src/useNotifications.ts
index d8694b09..ebb16269 100644
--- a/packages/composables/src/useNotifications.ts
+++ b/packages/composables/src/useNotifications.ts
@@ -84,7 +84,7 @@ export function useNotifications(): UseNotificationsReturn {
 
   async function pushNotification(
     message: string,
-    options: NotificationOptions,
+    options: Required<Pick<NotificationOptions, "type">> & NotificationOptions,
   ) {
     const timeout = options.timeout || 2500;
     const persistent = !!options.persistent;
@@ -93,7 +93,7 @@ export function useNotifications(): UseNotificationsReturn {
     const messageId = geterateId();
     _notifications.value.push({
       id: messageId,
-      type: options.type || "info",
+      type: options.type,
       message,
     });
     if (!persistent) {
diff --git a/packages/composables/src/useProduct.ts b/packages/composables/src/useProduct.ts
index f123a946..759c9380 100644
--- a/packages/composables/src/useProduct.ts
+++ b/packages/composables/src/useProduct.ts
@@ -35,6 +35,7 @@ export function useProduct(
     // TODO link docs with composables context usage
     throw new ContextError("Product");
   }
+
   const _configurator = useContext("configurator", {
     context: product && configurator,
   });
diff --git a/packages/composables/src/useProductAssociations.spec.ts b/packages/composables/src/useProductAssociations.spec.ts
index 6c430051..566ce195 100644
--- a/packages/composables/src/useProductAssociations.spec.ts
+++ b/packages/composables/src/useProductAssociations.spec.ts
@@ -1,6 +1,6 @@
 import { describe, expect, it, vi } from "vitest";
 import { useProductAssociations } from "./useProductAssociations";
-import { computed } from "vue";
+import { computed, ref } from "vue";
 import mockedProduct from "./mocks/Product";
 import mockedCrossSelling from "./mocks/CrossSellingResponse";
 import { useSetup } from "./_test";
@@ -88,4 +88,18 @@ describe("useProductAssociations", () => {
 
     expect(vm.productAssociations).toStrictEqual(mockedCrossSelling);
   });
+
+  it("init without product should throw an error", () => {
+    expect(() =>
+      useSetup(() =>
+        useProductAssociations(
+          // @ts-expect-error if API returns null we want to be prepared for it
+          ref(null),
+          {
+            associationContext: "cross-selling",
+          },
+        ),
+      ),
+    ).toThrowError("[useProductAssociations]: Product is not provided.");
+  });
 });
diff --git a/packages/composables/src/useProductConfigurator.spec.ts b/packages/composables/src/useProductConfigurator.spec.ts
index 27f82b05..97fc9bd6 100644
--- a/packages/composables/src/useProductConfigurator.spec.ts
+++ b/packages/composables/src/useProductConfigurator.spec.ts
@@ -4,16 +4,15 @@ import { ref } from "vue";
 import mockedProduct from "./mocks/Product";
 import mockedConfigurator from "./mocks/Configurator";
 import { useSetup } from "./_test";
+import { useProduct } from "./useProduct";
+
+vi.mock("./useProduct.ts");
 
 describe("useProductConfigurator", () => {
-  vi.mock("./useProduct.ts", () => ({
-    useProduct() {
-      return {
-        configurator: ref(mockedConfigurator),
-        product: ref(mockedProduct),
-      };
-    },
-  }));
+  vi.mocked(useProduct).mockReturnValue({
+    configurator: ref(mockedConfigurator),
+    product: ref(mockedProduct),
+  } as unknown as ReturnType<typeof useProduct>);
 
   it("handleChange callback function was called", () => {
     const { vm } = useSetup(useProductConfigurator);
@@ -55,4 +54,25 @@ describe("useProductConfigurator", () => {
       "PROBLEM",
     );
   });
+
+  it("product - with options", () => {
+    vi.mocked(useProduct).mockReturnValue({
+      configurator: ref(null),
+      product: ref({
+        options: [
+          {
+            id: "cc02c6cf39ad43d5856a25f8928490bf",
+          },
+          {
+            id: "aa02c6cf39ad43d5856a25f8928490bf",
+          },
+        ],
+      }),
+    } as unknown as ReturnType<typeof useProduct>);
+
+    const { vm } = useSetup(useProductConfigurator);
+
+    expect(vm.isLoadingOptions).toBe(true);
+    expect(vm.getOptionGroups).toStrictEqual([]);
+  });
 });
diff --git a/packages/composables/src/useProductPrice.ts b/packages/composables/src/useProductPrice.ts
index f71964ac..293a9ff6 100644
--- a/packages/composables/src/useProductPrice.ts
+++ b/packages/composables/src/useProductPrice.ts
@@ -71,37 +71,27 @@ export function useProductPrice(
     Schemas["CalculatedPrice"]["referencePrice"] | undefined
   > = computed(() => _real?.value?.referencePrice);
 
-  const _displayParent: ComputedRef<boolean> = computed(
-    () =>
-      !!product.value?.variantListingConfig?.displayParent &&
-      product.value?.parentId === null,
-  );
-
-  const displayFrom: ComputedRef<boolean> = computed(
-    () =>
-      (product.value?.calculatedPrices?.length ?? 0) > 1 ||
-      !!(_displayParent.value && displayFromVariants.value),
-  );
+  const displayFrom: ComputedRef<boolean> = computed(() => {
+    return (product.value?.calculatedPrices?.length ?? 0) > 1;
+  });
 
   const displayFromVariants: ComputedRef<number | false | undefined> = computed(
-    () =>
-      !!product.value?.parentId &&
-      product.value?.calculatedCheapestPrice?.hasRange &&
-      _real?.value?.unitPrice !== _cheapest?.value?.unitPrice &&
-      _cheapest?.value?.unitPrice,
+    () => {
+      return (
+        !!product.value?.parentId &&
+        product.value?.calculatedCheapestPrice?.hasRange &&
+        _real?.value?.unitPrice !== _cheapest?.value?.unitPrice &&
+        _cheapest?.value?.unitPrice
+      );
+    },
   );
 
   const _price: ComputedRef<Schemas["CalculatedPrice"] | undefined> = computed(
     () => {
       if (displayFrom.value && getProductTierPrices(product.value).length > 1) {
-        const lowest = product.value?.calculatedPrices?.reduce(
-          (previous, current) => {
-            return current.unitPrice < previous.unitPrice ? current : previous;
-          },
-        );
-        return (
-          lowest || (_cheapest.value as unknown as Schemas["CalculatedPrice"])
-        );
+        return product.value?.calculatedPrices?.reduce((previous, current) => {
+          return current.unitPrice < previous.unitPrice ? current : previous;
+        });
       }
       return _real.value;
     },
@@ -117,9 +107,9 @@ export function useProductPrice(
     () => _price.value,
   );
 
-  const isListPrice: ComputedRef<boolean> = computed(
-    () => !!_price.value?.listPrice?.percentage,
-  );
+  const isListPrice: ComputedRef<boolean> = computed(() => {
+    return !!_price.value?.listPrice?.percentage;
+  });
 
   const regulationPrice: ComputedRef<number | undefined> = computed(
     () => product.value?.calculatedPrice?.regulationPrice?.price,
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 30c88b41..c7bff178 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -55,8 +55,8 @@ importers:
         specifier: 14.0.2
         version: 14.0.2
       husky:
-        specifier: 9.1.1
-        version: 9.1.1
+        specifier: 9.1.2
+        version: 9.1.2
       prettier:
         specifier: 3.3.3
         version: 3.3.3
@@ -64,8 +64,8 @@ importers:
         specifier: 2.0.9
         version: 2.0.9
       vercel:
-        specifier: 35.1.0
-        version: 35.1.0(@swc/core@1.6.13)(encoding@0.1.13)
+        specifier: 35.2.1
+        version: 35.2.1(@swc/core@1.6.13)(encoding@0.1.13)
 
   apps/docs:
     dependencies:
@@ -223,8 +223,8 @@ importers:
         specifier: 3.0.5
         version: 3.0.5
       primevue:
-        specifier: 4.0.0
-        version: 4.0.0(@primeuix/utils@0.0.5)(vue@3.4.33(typescript@5.5.4))
+        specifier: 4.0.2
+        version: 4.0.2(vue@3.4.33(typescript@5.5.4))
       vue:
         specifier: 3.4.33
         version: 3.4.33(typescript@5.5.4)
@@ -3180,15 +3180,14 @@ packages:
     resolution: {integrity: sha512-ntUiUgtRtkF8KuaxHffzhYxQxoXk6LAPHm7CVlFjdqS8Rx8xRkLkZVyo84E+pO2hcNFkOGVP/GxHhQ2s94O8zA==}
     engines: {node: '>=12.11.0'}
 
-  '@primevue/core@4.0.0':
-    resolution: {integrity: sha512-M+GF1HYnl/x5J6uevXh1k42J0XnFhp0XHce+cHddWg7v3bVwgsn7LD3AKKcf0A/iQQPXVKX9nY/4/9eFVct67w==}
+  '@primevue/core@4.0.2':
+    resolution: {integrity: sha512-SpCIQ1LG6B66cecmZt1UdFeY7tbdJrgnhncADolfE9fcCyTSBtbaVLLhCV2E4Q9myMwCFE5KQxqazA4rdLWk4w==}
     engines: {node: '>=12.11.0'}
     peerDependencies:
-      '@primeuix/utils': ^0.0.5
       vue: ^3.0.0
 
-  '@primevue/icons@4.0.0':
-    resolution: {integrity: sha512-gv9pbj7JjCuW59tW2csIJgg6btTJpkr/mjlfqscEIrYzDGqzCrbfxLur48gA2dyhYsiQPPTbIHFwL944piFgIg==}
+  '@primevue/icons@4.0.2':
+    resolution: {integrity: sha512-S1VEpMsx4uUAsTjZtII03LQqgocYwSKbXMF0YDFWybY8r5LaHaveVZxS/i+KbsCLaL18BXJw0L/7L1eQdJHzaA==}
     engines: {node: '>=12.11.0'}
 
   '@primevue/themes@4.0.0':
@@ -3997,9 +3996,6 @@ packages:
   '@types/node@20.11.17':
     resolution: {integrity: sha512-QmgQZGWu1Yw9TDyAP9ZzpFJKynYNeOvwMJmaxABfieQoVoiVOS6MN1WSpqpRcbeA5+RW82kraAVxCCJg+780Qw==}
 
-  '@types/node@20.14.11':
-    resolution: {integrity: sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==}
-
   '@types/node@20.14.12':
     resolution: {integrity: sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==}
 
@@ -4518,8 +4514,8 @@ packages:
   '@vercel/node@3.2.7':
     resolution: {integrity: sha512-/eWXgkkjBm1Es6oRmltw5m0SLT8tnOdlSKYpQhPfpJlWVzLb8h3cWhTS+cSsnn3gZ0c6w4XSjiZBbGKQJevxoQ==}
 
-  '@vercel/python@4.3.0':
-    resolution: {integrity: sha512-tj6ffEh+ligmQoo/ONOg7DNX0VGKJt9FyswyOIIp6lZufs5oGzHAfan4+5QzF/2INxvXobN0aMYgcbFHJ81ZKg==}
+  '@vercel/python@4.3.1':
+    resolution: {integrity: sha512-pWRApBwUsAQJS8oZ7eKMiaBGbYJO71qw2CZqDFvkTj34FNBZtNIUcWSmqGfJJY5m2pU/9wt8z1CnKIyT9dstog==}
 
   '@vercel/redwood@2.1.3':
     resolution: {integrity: sha512-lpsdQSHS2hvSX29/rJNm4q38dVXKstS4MVg875KE6zyXpACwviXuet0Cadyv0E60w7f2B6Ra+nJMpwKz6oJ5xg==}
@@ -6963,8 +6959,8 @@ packages:
     resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
     engines: {node: '>=16.17.0'}
 
-  husky@9.1.1:
-    resolution: {integrity: sha512-fCqlqLXcBnXa/TJXmT93/A36tJsjdJkibQ1MuIiFyCCYUlpYpIaj2mv1w+3KR6Rzu1IC3slFTje5f6DUp2A2rg==}
+  husky@9.1.2:
+    resolution: {integrity: sha512-1/aDMXZdhr1VdJJTLt6e7BipM0Jd9qkpubPiIplon1WmCeOy3nnzsCMeBqS9AsL5ioonl8F8y/F2CLOmk19/Pw==}
     engines: {node: '>=18'}
     hasBin: true
 
@@ -8765,8 +8761,8 @@ packages:
     resolution: {integrity: sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==}
     engines: {node: '>=10'}
 
-  primevue@4.0.0:
-    resolution: {integrity: sha512-2PFmmJqyXpOcKOdF+gbps5fpSXfoXZp2LwX+hya/b5SDseMt3UNboyEgVI6B+DNbJRrib35EbDiMw+7RIANQ1w==}
+  primevue@4.0.2:
+    resolution: {integrity: sha512-bf5In//ixosZDOcfJ0iaBXhtQSpNC/CuAOE2KHd/SgUKZdij3VRljQ+I9+Be/TTxfikIeKH7eZ4gzDbWiIZurw==}
     engines: {node: '>=12.11.0'}
 
   prism-react-renderer@1.3.5:
@@ -9601,8 +9597,8 @@ packages:
   tar-stream@3.1.7:
     resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==}
 
-  tar@7.4.0:
-    resolution: {integrity: sha512-XQs0S8fuAkQWuqhDeCdMlJXDX80D7EOVLDPVFkna9yQfzS+PHKgfxcei0jf6/+QAWcjqrnC8uM3fSAnrQl+XYg==}
+  tar@7.4.3:
+    resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==}
     engines: {node: '>=18'}
 
   teex@1.0.1:
@@ -9980,6 +9976,10 @@ packages:
     resolution: {integrity: sha512-JfjKqIauur3Q6biAtHJ564e3bWa8VvT+7cSiOJHFbX4Erv6CLGDpg8z+Fmg/1OI/47RA+GI2QZaF48SSaLvyBA==}
     engines: {node: '>=18.17'}
 
+  undici@6.19.4:
+    resolution: {integrity: sha512-i3uaEUwNdkRq2qtTRRJb13moW5HWqviu7Vl7oYRYz++uPtGHJj+x7TGjcEuwS5Mt2P4nA0U9dhIX3DdB6JGY0g==}
+    engines: {node: '>=18.17'}
+
   unenv@1.10.0:
     resolution: {integrity: sha512-wY5bskBQFL9n3Eca5XnhH6KbUo/tfvkwm9OpcdCvLaeA7piBNbavbOKJySEwQ1V0RH6HvNlSAFRTpvTqgKRQXQ==}
 
@@ -10269,8 +10269,8 @@ packages:
   value-equal@1.0.1:
     resolution: {integrity: sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==}
 
-  vercel@35.1.0:
-    resolution: {integrity: sha512-q9vHaeMGQaOPPOEtzABuvN7qO2+hwKnDIzV7GprPECXpcvP3J2Ge8yJls1erESa0uvjcKU55T8fI4RS3rWzXgA==}
+  vercel@35.2.1:
+    resolution: {integrity: sha512-rofSro+xa68cU0dUciBIy7wM9ZMTR4cztMi1nt5N/wiSxPYhQL7Y/qzjHwaXSmMRItDUL+sNwbjMY4LX1WsBeA==}
     engines: {node: '>= 16'}
     hasBin: true
 
@@ -11155,7 +11155,7 @@ snapshots:
       '@babel/helper-replace-supers': 7.24.7(@babel/core@7.24.9)
       '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
       '@babel/helper-split-export-declaration': 7.24.7
-      semver: 7.6.3
+      semver: 7.6.2
     transitivePeerDependencies:
       - supports-color
 
@@ -12369,7 +12369,7 @@ snapshots:
   '@manypkg/find-root@1.1.0':
     dependencies:
       '@babel/runtime': 7.24.7
-      '@types/node': 20.14.11
+      '@types/node': 20.14.12
       find-up: 4.1.0
       fs-extra: 8.1.0
 
@@ -12392,7 +12392,7 @@ snapshots:
       npmlog: 5.0.1
       rimraf: 3.0.2
       semver: 7.6.3
-      tar: 7.4.0
+      tar: 7.4.3
     transitivePeerDependencies:
       - encoding
       - supports-color
@@ -13549,17 +13549,17 @@ snapshots:
 
   '@primeuix/utils@0.0.5': {}
 
-  '@primevue/core@4.0.0(@primeuix/utils@0.0.5)(vue@3.4.33(typescript@5.5.4))':
+  '@primevue/core@4.0.2(vue@3.4.33(typescript@5.5.4))':
     dependencies:
       '@primeuix/styled': 0.0.5
       '@primeuix/utils': 0.0.5
       vue: 3.4.33(typescript@5.5.4)
 
-  '@primevue/icons@4.0.0(@primeuix/utils@0.0.5)(vue@3.4.33(typescript@5.5.4))':
+  '@primevue/icons@4.0.2(vue@3.4.33(typescript@5.5.4))':
     dependencies:
-      '@primevue/core': 4.0.0(@primeuix/utils@0.0.5)(vue@3.4.33(typescript@5.5.4))
+      '@primeuix/utils': 0.0.5
+      '@primevue/core': 4.0.2(vue@3.4.33(typescript@5.5.4))
     transitivePeerDependencies:
-      - '@primeuix/utils'
       - vue
 
   '@primevue/themes@4.0.0(@primeuix/styled@0.0.5)':
@@ -14586,7 +14586,7 @@ snapshots:
 
   '@types/http-proxy@1.17.14':
     dependencies:
-      '@types/node': 20.14.11
+      '@types/node': 20.14.12
 
   '@types/js-cookie@2.2.7': {}
 
@@ -14638,10 +14638,6 @@ snapshots:
     dependencies:
       undici-types: 5.26.5
 
-  '@types/node@20.14.11':
-    dependencies:
-      undici-types: 5.26.5
-
   '@types/node@20.14.12':
     dependencies:
       undici-types: 5.26.5
@@ -14742,7 +14738,7 @@ snapshots:
 
   '@types/type-is@1.6.3':
     dependencies:
-      '@types/node': 20.14.11
+      '@types/node': 20.11.17
 
   '@types/uglify-js@3.17.5':
     dependencies:
@@ -15581,7 +15577,7 @@ snapshots:
       semver: 7.6.3
       stat-mode: 0.3.0
       stream-to-promise: 2.2.0
-      tar: 7.4.0
+      tar: 7.4.3
       tree-kill: 1.2.2
       uid-promise: 1.0.0
       uuid: 3.3.2
@@ -15659,7 +15655,7 @@ snapshots:
       '@edge-runtime/node-utils': 2.3.0
       '@edge-runtime/primitives': 4.1.0
       '@edge-runtime/vm': 3.2.0
-      '@types/node': 20.14.11
+      '@types/node': 20.14.12
       '@vercel/build-utils': 8.3.5
       '@vercel/error-utils': 2.0.2
       '@vercel/nft': 0.27.3(encoding@0.1.13)
@@ -15673,16 +15669,16 @@ snapshots:
       node-fetch: 2.6.9(encoding@0.1.13)
       path-to-regexp: 6.2.1
       ts-morph: 12.0.0
-      ts-node: 10.9.1(@swc/core@1.6.13)(@types/node@20.14.11)(typescript@4.9.5)
+      ts-node: 10.9.1(@swc/core@1.6.13)(@types/node@20.14.12)(typescript@4.9.5)
       typescript: 4.9.5
-      undici: 6.19.2
+      undici: 6.19.4
     transitivePeerDependencies:
       - '@swc/core'
       - '@swc/wasm'
       - encoding
       - supports-color
 
-  '@vercel/python@4.3.0': {}
+  '@vercel/python@4.3.1': {}
 
   '@vercel/redwood@2.1.3(encoding@0.1.13)':
     dependencies:
@@ -18483,7 +18479,7 @@ snapshots:
       nypm: 0.3.9
       ohash: 1.1.3
       pathe: 1.1.2
-      tar: 7.4.0
+      tar: 7.4.3
 
   git-config-path@2.0.0: {}
 
@@ -18927,7 +18923,7 @@ snapshots:
 
   human-signals@5.0.0: {}
 
-  husky@9.1.1: {}
+  husky@9.1.2: {}
 
   hyphenate-style-name@1.0.4: {}
 
@@ -21159,7 +21155,7 @@ snapshots:
   path-scurry@1.10.2:
     dependencies:
       lru-cache: 10.3.0
-      minipass: 7.1.2
+      minipass: 7.0.4
 
   path-scurry@1.11.1:
     dependencies:
@@ -21453,12 +21449,13 @@ snapshots:
     dependencies:
       parse-ms: 2.1.0
 
-  primevue@4.0.0(@primeuix/utils@0.0.5)(vue@3.4.33(typescript@5.5.4)):
+  primevue@4.0.2(vue@3.4.33(typescript@5.5.4)):
     dependencies:
-      '@primevue/core': 4.0.0(@primeuix/utils@0.0.5)(vue@3.4.33(typescript@5.5.4))
-      '@primevue/icons': 4.0.0(@primeuix/utils@0.0.5)(vue@3.4.33(typescript@5.5.4))
+      '@primeuix/styled': 0.0.5
+      '@primeuix/utils': 0.0.5
+      '@primevue/core': 4.0.2(vue@3.4.33(typescript@5.5.4))
+      '@primevue/icons': 4.0.2(vue@3.4.33(typescript@5.5.4))
     transitivePeerDependencies:
-      - '@primeuix/utils'
       - vue
 
   prism-react-renderer@1.3.5(react@17.0.2):
@@ -21502,7 +21499,7 @@ snapshots:
       '@protobufjs/path': 1.1.2
       '@protobufjs/pool': 1.1.0
       '@protobufjs/utf8': 1.1.0
-      '@types/node': 20.14.11
+      '@types/node': 20.14.12
       long: 5.2.3
 
   protocols@2.0.1: {}
@@ -22468,7 +22465,7 @@ snapshots:
       fast-fifo: 1.3.2
       streamx: 2.16.1
 
-  tar@7.4.0:
+  tar@7.4.3:
     dependencies:
       '@isaacs/fs-minipass': 4.0.1
       chownr: 3.0.0
@@ -22631,14 +22628,14 @@ snapshots:
       '@ts-morph/common': 0.23.0
       code-block-writer: 13.0.1
 
-  ts-node@10.9.1(@swc/core@1.6.13)(@types/node@20.14.11)(typescript@4.9.5):
+  ts-node@10.9.1(@swc/core@1.6.13)(@types/node@20.14.12)(typescript@4.9.5):
     dependencies:
       '@cspotcode/source-map-support': 0.8.1
       '@tsconfig/node10': 1.0.11
       '@tsconfig/node12': 1.0.11
       '@tsconfig/node14': 1.0.3
       '@tsconfig/node16': 1.0.4
-      '@types/node': 20.14.11
+      '@types/node': 20.14.12
       acorn: 8.12.1
       acorn-walk: 8.3.3
       arg: 4.1.3
@@ -22844,6 +22841,8 @@ snapshots:
 
   undici@6.19.2: {}
 
+  undici@6.19.4: {}
+
   unenv@1.10.0:
     dependencies:
       consola: 3.2.3
@@ -23428,7 +23427,7 @@ snapshots:
 
   value-equal@1.0.1: {}
 
-  vercel@35.1.0(@swc/core@1.6.13)(encoding@0.1.13):
+  vercel@35.2.1(@swc/core@1.6.13)(encoding@0.1.13):
     dependencies:
       '@vercel/build-utils': 8.3.5
       '@vercel/fun': 1.1.0(encoding@0.1.13)
@@ -23436,7 +23435,7 @@ snapshots:
       '@vercel/hydrogen': 1.0.4
       '@vercel/next': 4.3.6(encoding@0.1.13)
       '@vercel/node': 3.2.7(@swc/core@1.6.13)(encoding@0.1.13)
-      '@vercel/python': 4.3.0
+      '@vercel/python': 4.3.1
       '@vercel/redwood': 2.1.3(encoding@0.1.13)
       '@vercel/remix-builder': 2.2.1(encoding@0.1.13)
       '@vercel/ruby': 2.1.0
diff --git a/templates/vue-demo-store/components/layout/LayoutHeader.vue b/templates/vue-demo-store/components/layout/LayoutHeader.vue
index 565ddcfe..f7fdbf1b 100644
--- a/templates/vue-demo-store/components/layout/LayoutHeader.vue
+++ b/templates/vue-demo-store/components/layout/LayoutHeader.vue
@@ -50,12 +50,14 @@ const sidebarController = useModal();
               <div
                 class="w-7 h-7 i-carbon-favorite text-secondary-600 hover:text-primary hover:animate-count-infinite hover:animate-heart-beat"
               />
-              <span
-                v-if="wishlistCount"
-                class="text-3 font-sm text-white absolute bg-red-600 rounded-full min-w-5 min-h-5 top-0 right-0 leading-5"
-              >
-                {{ wishlistCount }}
-              </span>
+              <ClientOnly>
+                <span
+                  v-if="wishlistCount"
+                  class="text-3 font-sm text-white absolute bg-red-600 rounded-full min-w-5 min-h-5 top-0 right-0 leading-5"
+                >
+                  {{ wishlistCount }}
+                </span>
+              </ClientOnly>
             </NuxtLink>
           </div>
           <!-- Cart -->


Test patch:
diff --git a/packages/composables/src/_test/useSetup.ts b/packages/composables/src/_test/useSetup.ts
index 1261d90b..db216b02 100644
--- a/packages/composables/src/_test/useSetup.ts
+++ b/packages/composables/src/_test/useSetup.ts
@@ -8,6 +8,7 @@ type Injections = {
   apiClient: {
     invoke: ReturnType<typeof vi.fn>;
   };
+  swNotifications?: unknown;
 };
 
 export function useSetup<V>(setup: () => V, customMocks?: Partial<Injections>) {
@@ -16,7 +17,7 @@ export function useSetup<V>(setup: () => V, customMocks?: Partial<Injections>) {
     apiClient: { invoke: customMocks?.apiClient?.invoke ?? vi.fn() },
   };
 
-  const compoment = defineComponent({
+  const component = defineComponent({
     setup,
     render() {
       return h("div", []);
@@ -28,7 +29,7 @@ export function useSetup<V>(setup: () => V, customMocks?: Partial<Injections>) {
     customMocks || {},
   ) as Injections;
 
-  const wrapper = shallowMount(compoment, {
+  const wrapper = shallowMount(component, {
     global: {
       provide: injections,
     },
diff --git a/packages/composables/src/index.test.ts b/packages/composables/src/index.test.ts
index 6f2336d5..8122f0f4 100644
--- a/packages/composables/src/index.test.ts
+++ b/packages/composables/src/index.test.ts
@@ -1,9 +1,12 @@
-import { describe, expect, it } from "vitest";
+import { describe, expect, it, vi } from "vitest";
 import { resolveCmsComponent, getDefaultApiParams } from "./index";
 import CmsPage from "./mocks/CmsPage";
 import type { Schemas } from "#shopware";
+import * as vue from "vue";
 
+vi.mock("vue");
 describe("resolveCmsComponent", () => {
+  vi.spyOn(vue, "resolveComponent").mockImplementation((element) => element);
   it("should resolve a cms component", () => {
     const result = resolveCmsComponent(
       CmsPage.cmsPage.sections[0].blocks[0] as unknown as Schemas["CmsBlock"],
@@ -19,6 +22,7 @@ describe("resolveCmsComponent", () => {
   });
 
   it("cms section component", () => {
+    vi.spyOn(vue, "resolveComponent").mockImplementation(() => ({}));
     const result = resolveCmsComponent({
       apiAlias: "cms_section",
     } as unknown as Schemas["CmsBlock"]);
@@ -32,4 +36,15 @@ describe("resolveCmsComponent", () => {
 
     expect(result.isResolved).toBe(true);
   });
+
+  it("component should not be resolved because of the error", () => {
+    vi.spyOn(vue, "resolveComponent").mockImplementation(() => {
+      throw new Error("error");
+    });
+    const result = resolveCmsComponent({
+      apiAlias: "cms_custom",
+    } as unknown as Schemas["CmsBlock"]);
+
+    expect(result.isResolved).toBe(false);
+  });
 });
diff --git a/packages/composables/src/useCart.test.ts b/packages/composables/src/useCart.test.ts
index 4e4793bd..3adf8164 100644
--- a/packages/composables/src/useCart.test.ts
+++ b/packages/composables/src/useCart.test.ts
@@ -39,6 +39,9 @@ describe("useCart", () => {
   });
 
   it("add single product", async () => {
+    expect(vm.cartItems).toEqual([]);
+    expect(vm.totalPrice).toBe(0);
+    expect(vm.subtotal).toBe(0);
     await vm.addProduct({
       id: itemsMock.items[0].referencedId as string,
       quantity: itemsMock.items[0].quantity,
@@ -58,6 +61,25 @@ describe("useCart", () => {
         },
       }),
     );
+
+    await vm.addProduct({
+      id: itemsMock.items[0].referencedId as string,
+    });
+
+    expect(injections.apiClient.invoke).toHaveBeenCalledWith(
+      expect.stringContaining("addLineItem"),
+      expect.objectContaining({
+        body: {
+          items: [
+            {
+              type: itemsMock.items[0].type,
+              id: itemsMock.items[0].referencedId,
+              quantity: 0,
+            },
+          ],
+        },
+      }),
+    );
   });
 
   it("refresh the cart", async () => {
@@ -71,6 +93,11 @@ describe("useCart", () => {
     expect(await vm.refreshCart(Cart as unknown as Schemas["Cart"])).toEqual(
       Cart,
     );
+
+    expect(vm.shippingTotal).toBe(0);
+    expect(vm.subtotal).toBe(16.11);
+    expect(vm.isVirtualCart).toBe(false);
+    expect(vm.totalPrice).toBe(16.11);
   });
 
   it("add set of products", async () => {
@@ -116,4 +143,76 @@ describe("useCart", () => {
       }),
     );
   });
+
+  it("submitPromotionCode", async () => {
+    injections.apiClient.invoke.mockResolvedValue({
+      data: {
+        lineItems: [
+          {
+            type: "promotion",
+            payload: {
+              code: "3a64e872ca404522a2c5d43ebc751e6b",
+            },
+          },
+          {
+            type: "product",
+            good: true,
+            quantity: 1,
+            id: "e05e9340aff4484f9009646dfd572df9",
+          },
+        ],
+      },
+    });
+
+    await vm.addPromotionCode("PROMO_CODE");
+    expect(injections.apiClient.invoke).toHaveBeenCalledWith(
+      expect.stringContaining("addLineItem"),
+      expect.objectContaining({
+        body: {
+          items: [
+            {
+              referencedId: "PROMO_CODE",
+              type: "promotion",
+            },
+          ],
+        },
+      }),
+    );
+
+    expect(vm.appliedPromotionCodes).toEqual([
+      {
+        type: "promotion",
+        payload: {
+          code: "3a64e872ca404522a2c5d43ebc751e6b",
+        },
+      },
+    ]);
+    expect(vm.count).toBe(1);
+    expect(vm.totalPrice).toBe(0);
+  });
+
+  it("handle api cart error", async () => {
+    injections.apiClient.invoke.mockResolvedValue({
+      data: {
+        errors: [
+          {
+            status: 400,
+            code: "CHECKOUT__CART_ITEM_NOT_FOUND",
+            detail: "Line item not found",
+          },
+        ],
+      },
+    });
+    await vm.refreshCart();
+    await vm.addProducts(itemsMock.items);
+    expect(vm.consumeCartErrors()).toEqual({
+      "0": {
+        status: 400,
+        code: "CHECKOUT__CART_ITEM_NOT_FOUND",
+        detail: "Line item not found",
+      },
+    });
+
+    expect(vm.consumeCartErrors()).toEqual(null);
+  });
 });
diff --git a/packages/composables/src/useCartItem.test.ts b/packages/composables/src/useCartItem.test.ts
index cc955983..7184fc54 100644
--- a/packages/composables/src/useCartItem.test.ts
+++ b/packages/composables/src/useCartItem.test.ts
@@ -123,4 +123,46 @@ describe("useCartItem", () => {
       id: lineItem.id,
     });
   });
+
+  it("itemSpecialPrice", () => {
+    const { vm } = useSetup(() =>
+      useCartItem(
+        ref(
+          Object.assign(
+            { ...lineItem },
+            {
+              price: {
+                listPrice: {
+                  price: 10,
+                },
+                unitPrice: 5,
+              },
+            },
+          ),
+        ) as unknown as Ref<Schemas["LineItem"]>,
+      ),
+    );
+    expect(vm.itemSpecialPrice).toBe(5);
+  });
+  it("itemRegularPrice from listPrice", () => {
+    const { vm } = useSetup(() =>
+      useCartItem(
+        ref({
+          price: {
+            listPrice: {
+              price: 10,
+            },
+          },
+        }) as unknown as Ref<Schemas["LineItem"]>,
+      ),
+    );
+    expect(vm.itemRegularPrice).toBe(10);
+  });
+
+  it("should throw an error if cartItem is not provided", () => {
+    expect(() =>
+      // @ts-expect-error we deliberately pass null to invoke error
+      useCartItem(null),
+    ).toThrow("[useCartItem] mandatory cartItem argument is missing.");
+  });
 });
diff --git a/packages/composables/src/useCustomerOrders.test.ts b/packages/composables/src/useCustomerOrders.test.ts
index cfa108ad..e6d29f60 100644
--- a/packages/composables/src/useCustomerOrders.test.ts
+++ b/packages/composables/src/useCustomerOrders.test.ts
@@ -3,7 +3,7 @@ import { useCustomerOrders } from "./useCustomerOrders";
 import { useSetup } from "./_test";
 
 describe("useCustomerOrders", () => {
-  it("changeLanguage", async () => {
+  it("should inovke load orders", async () => {
     const { vm, injections } = useSetup(useCustomerOrders);
     injections.apiClient.invoke.mockResolvedValue({
       data: { orders: { elements: [] } },
@@ -13,9 +13,10 @@ describe("useCustomerOrders", () => {
       expect.stringContaining("readOrder"),
       expect.objectContaining({}),
     );
+    expect(vm.totalPages).toBe(0);
   });
 
-  it("changeCurrentPage", async () => {
+  it("should invoke change page", async () => {
     const { vm, injections } = useSetup(useCustomerOrders);
     injections.apiClient.invoke.mockResolvedValue({
       data: { orders: { elements: [] } },
diff --git a/packages/composables/src/useInternationalization.test.ts b/packages/composables/src/useInternationalization.test.ts
index 7f592e21..345adfc0 100644
--- a/packages/composables/src/useInternationalization.test.ts
+++ b/packages/composables/src/useInternationalization.test.ts
@@ -1,6 +1,8 @@
 import { describe, expect, it, vi } from "vitest";
 import { useInternationalization } from "./useInternationalization";
+import type { RouteObject } from "./useInternationalization";
 import { useSetup } from "./_test";
+import type { Schemas } from "#shopware";
 
 describe("useInternationalization", () => {
   it("should return storefrontUrl", async () => {
@@ -21,7 +23,7 @@ describe("useInternationalization", () => {
     expect(vm.getStorefrontUrl()).toBe("http://localhost:3000");
   });
 
-  it("getAvailableLanguages", async () => {
+  it("should invoke getting available languages", async () => {
     const { vm, injections } = useSetup(useInternationalization);
     injections.apiClient.invoke.mockResolvedValue({ data: {} });
     vm.getAvailableLanguages();
@@ -30,7 +32,7 @@ describe("useInternationalization", () => {
     );
   });
 
-  it("changeLanguage", async () => {
+  it("should invoke change language", async () => {
     const { vm, injections } = useSetup(useInternationalization);
     injections.apiClient.invoke.mockResolvedValue({ data: {} });
     vm.changeLanguage("test-id");
@@ -39,4 +41,115 @@ describe("useInternationalization", () => {
       expect.objectContaining({ body: { languageId: "test-id" } }),
     );
   });
+
+  it("getLanguageCodeFromId", async () => {
+    const { vm } = useSetup(useInternationalization);
+    vm.languages = [
+      { id: "test-id", translationCode: { code: "test-code" } },
+    ] as Schemas["Language"][];
+    expect(vm.getLanguageCodeFromId("test-id")).toBe("test-code");
+  });
+
+  it("getLanguageCodeFromId -  no translationCode", async () => {
+    const { vm } = useSetup(useInternationalization);
+    vm.languages = [{ id: "test-id" }] as Schemas["Language"][];
+    expect(vm.getLanguageCodeFromId("test-id")).toBe("");
+  });
+
+  it("getLanguageCodeFromId - no languages", async () => {
+    const { vm } = useSetup(useInternationalization);
+    expect(() => vm.getLanguageCodeFromId("test-id")).toThrowError();
+  });
+
+  it("getLanguageIdFromCode", async () => {
+    const { vm } = useSetup(useInternationalization);
+    vm.languages = [
+      { id: "test-id", translationCode: { code: "test-code" } },
+    ] as Schemas["Language"][];
+    expect(vm.getLanguageIdFromCode("test-code")).toBe("test-id");
+  });
+
+  it("getLanguageIdFromCode - no id", async () => {
+    const { vm } = useSetup(useInternationalization);
+    vm.languages = [
+      { translationCode: { code: "test-code" } },
+    ] as Schemas["Language"][];
+    expect(vm.getLanguageIdFromCode("test-code")).toBe("");
+  });
+
+  it("getLanguageIdFromCode - no languages", async () => {
+    const { vm } = useSetup(useInternationalization);
+    expect(() => vm.getLanguageIdFromCode("test-code")).toThrowError();
+  });
+
+  it("should return the storefront url with the devStorefrontUrl", async () => {
+    const url = "http://frontend.test";
+    const { vm } = useSetup(useInternationalization);
+
+    expect(vm.replaceToDevStorefront(url)).toBe(url);
+  });
+
+  it("formatLink", async () => {
+    const { vm } = useSetup(() =>
+      useInternationalization((element) => element),
+    );
+    expect(vm.formatLink("test")).toBe("test");
+  });
+
+  it("formatLink with path", async () => {
+    const { vm } = useSetup(() =>
+      useInternationalization((element) => element),
+    );
+    expect(vm.formatLink({ path: "test" })).toStrictEqual({ path: "test" });
+  });
+
+  it("formatLink custom structure", async () => {
+    const { vm } = useSetup(() =>
+      useInternationalization((element) => element),
+    );
+    expect(
+      vm.formatLink({ custom: "test" } as unknown as RouteObject),
+    ).toStrictEqual({
+      custom: "test",
+    });
+  });
+
+  it("replaceToDevStorefront with devStorefrontUrl", async () => {
+    const { vm } = useSetup(
+      () => useInternationalization((element) => element),
+      {
+        shopware: { devStorefrontUrl: "http://dev-storefront.test" },
+      },
+    );
+    expect(vm.getStorefrontUrl()).toBe("http://dev-storefront.test");
+    expect(vm.replaceToDevStorefront("http://localhost:3000/test")).toBe(
+      "http://dev-storefront.test/test",
+    );
+  });
+
+  it("getStorefrontUrl without devStorefrontUrl and window", async () => {
+    vi.spyOn(window, "location", "get").mockImplementation(
+      () => ({}) as Location,
+    );
+    const { vm } = useSetup(
+      () => useInternationalization((element) => element),
+      {
+        shopware: { devStorefrontUrl: null },
+      },
+    );
+
+    expect(vm.getStorefrontUrl()).toBe("");
+  });
+
+  it("pathResolver absolute path", async () => {
+    const { vm } = useSetup(() =>
+      useInternationalization((element) => element),
+    );
+    expect(vm.formatLink("http://www.test.test")).toBe("http://www.test.test");
+  });
+
+  it("pathResolver without resolver", async () => {
+    const { vm } = useSetup(() => useInternationalization());
+    expect(vm.formatLink("test")).toBe("test");
+  });
 });
diff --git a/packages/composables/src/useListing.test.ts b/packages/composables/src/useListing.test.ts
index 25e289a0..8bb87cce 100644
--- a/packages/composables/src/useListing.test.ts
+++ b/packages/composables/src/useListing.test.ts
@@ -1,11 +1,12 @@
 import { describe, expect, it } from "vitest";
-import { useListing } from "./useListing";
+import { useListing, useCategoryListing } from "./useListing";
 import { useSetup } from "./_test";
 import searchMock from "./mocks/Search";
 import ContextError from "./helpers/ContextError";
+import type { Schemas } from "#shopware";
 
 describe("useListing", () => {
-  it("invoke search", async () => {
+  it("should invoke search", async () => {
     const { vm, injections } = await useSetup(() =>
       useListing({
         listingType: "productSearchListing",
@@ -28,7 +29,7 @@ describe("useListing", () => {
     expect(vm.getLimit).toBe(10);
   });
 
-  it('invoke "readQuotes"', async () => {
+  it('should invoke "readQuotes"', async () => {
     const { vm, injections } = await useSetup(() =>
       useListing({
         listingType: "categoryListing",
@@ -55,7 +56,7 @@ describe("useListing", () => {
     );
   });
 
-  it('invoke "readQuotes" - errors', async () => {
+  it("should handle context error", async () => {
     let error: unknown | null = null;
     try {
       await useSetup(() =>
@@ -69,7 +70,7 @@ describe("useListing", () => {
     expect(error).toEqual(new ContextError("Category"));
   });
 
-  it("setCurrentFilters", async () => {
+  it("should set current filters", async () => {
     const { vm, injections } = await useSetup(() =>
       useListing({
         listingType: "categoryListing",
@@ -138,4 +139,112 @@ describe("useListing", () => {
       }),
     );
   });
+
+  it("useCategoryListing - error is thrown when listingContext was not provided in parent tree", async () => {
+    expect(() => useSetup(useCategoryListing)).toThrowError();
+  });
+
+  it("setInitialListing", async () => {
+    const { vm } = await useSetup(() =>
+      useListing({
+        listingType: "categoryListing",
+        categoryId: "1234",
+      }),
+    );
+
+    vm.setInitialListing({
+      apiAlias: "product_listing",
+    } as Schemas["ProductListingResult"]);
+
+    expect(vm.getInitialListing).toEqual({ apiAlias: "product_listing" });
+  });
+
+  it("initSearch", () => {
+    const { vm, injections } = useSetup(() =>
+      useListing({ listingType: "productSearchListing" }),
+    );
+    injections.apiClient.invoke.mockResolvedValue({ data: {} });
+    vm.initSearch({
+      search: "test",
+    });
+
+    expect(vm.getCurrentPage).toBe(1);
+    expect(vm.getTotalPagesCount).toBe(0);
+    expect(vm.getLimit).toBe(10);
+  });
+
+  it("loadMore", async () => {
+    const { vm, injections } = await useSetup(() =>
+      useListing({
+        listingType: "productSearchListing",
+      }),
+    );
+    injections.apiClient.invoke.mockResolvedValue({ data: { page: 1 } });
+    await vm.loadMore();
+
+    expect(injections.apiClient.invoke).toHaveBeenCalledWith(
+      expect.stringContaining("search"),
+      expect.objectContaining({
+        body: {
+          p: 2,
+        },
+        headers: {
+          "sw-include-seo-urls": true,
+        },
+      }),
+    );
+  });
+
+  it("changeCurrentSortingOrder", async () => {
+    const { vm, injections } = await useSetup(() =>
+      useListing({
+        listingType: "productSearchListing",
+      }),
+    );
+    injections.apiClient.invoke.mockResolvedValue({ data: { page: 1 } });
+    vm.changeCurrentSortingOrder("test");
+
+    expect(injections.apiClient.invoke).toHaveBeenCalledWith(
+      expect.stringContaining("search"),
+      expect.objectContaining({
+        body: {
+          order: "test",
+        },
+        headers: {
+          "sw-include-seo-urls": true,
+        },
+      }),
+    );
+  });
+
+  it("changeCurrentPage", async () => {
+    const { vm, injections } = await useSetup(() =>
+      useListing({
+        listingType: "productSearchListing",
+      }),
+    );
+    injections.apiClient.invoke.mockResolvedValue({ data: { page: 1 } });
+    vm.changeCurrentPage(2);
+
+    expect(injections.apiClient.invoke).toHaveBeenCalledWith(
+      expect.stringContaining("search"),
+      expect.objectContaining({
+        body: {
+          page: 2,
+        },
+        headers: {
+          "sw-include-seo-urls": true,
+        },
+      }),
+    );
+  });
+
+  it("getAvailableFilters", async () => {
+    const { vm } = await useSetup(() =>
+      useListing({
+        listingType: "productSearchListing",
+      }),
+    );
+    expect(vm.getAvailableFilters).toEqual([]);
+  });
 });
diff --git a/packages/composables/src/useLocalWishlist.test.ts b/packages/composables/src/useLocalWishlist.test.ts
index 4be5381e..f026c36a 100644
--- a/packages/composables/src/useLocalWishlist.test.ts
+++ b/packages/composables/src/useLocalWishlist.test.ts
@@ -4,7 +4,7 @@ import { useLocalWishlist } from "./useLocalWishlist";
 
 describe("useLocalWishlist", () => {
   describe("methods", () => {
-    describe("addToWishlist", () => {
+    describe("should add product to the wishlist", () => {
       it("wishlist add product", () => {
         const { vm } = useSetup(useLocalWishlist);
         vm.addToWishlist("some-id");
@@ -13,23 +13,15 @@ describe("useLocalWishlist", () => {
     });
 
     describe("removeFromWishlist", () => {
-      it("wishlist add product", () => {
+      it("should remove product from the wishlist", () => {
         const { vm } = useSetup(useLocalWishlist);
         vm.removeFromWishlist("some-id");
         expect(vm.items.length).toBe(0);
       });
     });
 
-    describe("removeFromWishlist", () => {
-      it("wishlist remove product", () => {
-        const { vm } = useSetup(useLocalWishlist);
-        vm.removeFromWishlist("some-id");
-        expect(vm.count).toBe(0);
-      });
-    });
-
     describe("clearWishlist", () => {
-      it("clearWishlist", () => {
+      it("should clear the wishlist", () => {
         const { vm } = useSetup(useLocalWishlist);
         vm.addToWishlist("some-id");
         expect(vm.count).toBe(1);
@@ -39,18 +31,24 @@ describe("useLocalWishlist", () => {
     });
 
     describe("getWishlistProducts", () => {
-      it("getWishlistProducts", () => {
+      it("should get the wishlist products", () => {
         const { vm } = useSetup(useLocalWishlist);
         vm.clearWishlist();
         vm.getWishlistProducts();
         expect(vm.count).toBe(0);
       });
-      it("getWishlistProducts with items", () => {
+      it("should get the wishlist products after adding product", () => {
         const { vm } = useSetup(useLocalWishlist);
         vm.addToWishlist("some-id");
         vm.getWishlistProducts();
         expect(vm.count).toBe(1);
       });
+      it("getWishlistProducts with items localStorage", () => {
+        const { vm } = useSetup(useLocalWishlist);
+        localStorage.removeItem("sw-wishlist-items");
+        vm.getWishlistProducts();
+        expect(vm.count).toBe(1);
+      });
     });
   });
 });
diff --git a/packages/composables/src/useNavigationSearch.test.ts b/packages/composables/src/useNavigationSearch.test.ts
index 20c424e9..73e24f20 100644
--- a/packages/composables/src/useNavigationSearch.test.ts
+++ b/packages/composables/src/useNavigationSearch.test.ts
@@ -1,6 +1,15 @@
-import { describe, expect, it } from "vitest";
+import { describe, expect, it, vi } from "vitest";
 import { useNavigationSearch } from "./useNavigationSearch";
 import { useSetup } from "./_test";
+import { useSessionContext } from "./useSessionContext";
+import { ref } from "vue";
+
+vi.mock("./useSessionContext.ts");
+const sessionContext = ref();
+
+vi.mocked(useSessionContext).mockReturnValue({
+  sessionContext,
+} as unknown as ReturnType<typeof useSessionContext>);
 
 const mockedResponse = {
   translated: [],
@@ -85,4 +94,18 @@ describe("useNavigationSearch", () => {
     `);
     expect(injections.apiClient.invoke).not.toHaveBeenCalled();
   });
+
+  it("resolvePath with categoryId", async () => {
+    const { vm } = useSetup(useNavigationSearch);
+    sessionContext.value = {
+      salesChannel: {
+        navigationCategoryId: "categoryIdTest",
+      },
+    };
+
+    expect(await vm.resolvePath("/")).toStrictEqual({
+      foreignKey: "categoryIdTest",
+      routeName: "frontend.navigation.page",
+    });
+  });
 });
diff --git a/packages/composables/src/useNewsletter.test.ts b/packages/composables/src/useNewsletter.test.ts
index 5e94ef7f..bde1a1f8 100644
--- a/packages/composables/src/useNewsletter.test.ts
+++ b/packages/composables/src/useNewsletter.test.ts
@@ -33,4 +33,23 @@ describe("useNewsletter", () => {
       },
     );
   });
+
+  it("getNewsletterStatus", async () => {
+    const { vm, injections } = useSetup(useNewsletter);
+    injections.apiClient.invoke.mockResolvedValue({ data: {} });
+
+    await vm.getNewsletterStatus();
+
+    expect(injections.apiClient.invoke).toHaveBeenCalledWith(
+      expect.stringContaining("readNewsletterRecipient"),
+    );
+  });
+
+  it("isNewsletterSubscriber", async () => {
+    const { vm } = useSetup(useNewsletter);
+
+    expect(vm.isNewsletterSubscriber).toBe(false);
+    vm.newsletterStatus = "direct";
+    expect(vm.isNewsletterSubscriber).toBe(true);
+  });
 });
diff --git a/packages/composables/src/useNotifications.test.ts b/packages/composables/src/useNotifications.test.ts
index ab2828c0..d8b5f55e 100644
--- a/packages/composables/src/useNotifications.test.ts
+++ b/packages/composables/src/useNotifications.test.ts
@@ -1,6 +1,7 @@
 import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
 import { useNotifications } from "./useNotifications";
 import { useSetup } from "./_test";
+
 describe("useNotifications", () => {
   beforeEach(() => {
     vi.useFakeTimers();
@@ -10,7 +11,7 @@ describe("useNotifications", () => {
     vi.restoreAllMocks();
   });
 
-  it("notification flow", async () => {
+  it("should trigger sample notification flow", async () => {
     const { vm } = useSetup(useNotifications);
 
     vm.pushError("Error message");
@@ -32,4 +33,24 @@ describe("useNotifications", () => {
     vi.runAllTimers();
     expect(vm.notifications.length).toBe(0);
   });
+
+  it("injected empty swNotifications", () => {
+    const { vm } = useSetup(useNotifications, {
+      swNotifications: { value: null },
+    });
+
+    expect(vm.notifications).toEqual([]);
+    vm.removeOne(2332);
+    expect(vm.notifications).toEqual([]);
+    vm.pushSuccess("test");
+  });
+
+  it("injected empty swNotifications and push success", () => {
+    const { vm } = useSetup(useNotifications, {
+      swNotifications: { value: null },
+    });
+
+    vm.pushSuccess("test");
+    expect(vm.notifications.length).toBe(1);
+  });
 });
diff --git a/packages/composables/src/useOrderDetails.test.ts b/packages/composables/src/useOrderDetails.test.ts
index 060dd7c9..479c3d8f 100644
--- a/packages/composables/src/useOrderDetails.test.ts
+++ b/packages/composables/src/useOrderDetails.test.ts
@@ -28,7 +28,7 @@ describe("useOrderDetails", () => {
     );
   });
 
-  it("handlePayment", async () => {
+  it("should handle setting the order payment", async () => {
     const { vm, injections } = useSetup(() => useOrderDetails("123-test"));
     injections.apiClient.invoke.mockResolvedValue({ data: {} });
     await vm.handlePayment();
@@ -45,7 +45,7 @@ describe("useOrderDetails", () => {
     );
   });
 
-  it("cancel", async () => {
+  it("should cancel the order", async () => {
     const { vm, injections } = useSetup(() => useOrderDetails("123-test"));
     injections.apiClient.invoke.mockResolvedValue({ data: {} });
     await vm.cancel();
@@ -108,4 +108,27 @@ describe("useOrderDetails", () => {
       }),
     );
   });
+
+  it("getPaymentMethods", async () => {
+    const { vm, injections } = useSetup(() => useOrderDetails("123-test"));
+    injections.apiClient.invoke.mockResolvedValue({ data: {} });
+    await vm.getPaymentMethods();
+
+    expect(injections.apiClient.invoke).toHaveBeenCalledWith(
+      expect.stringContaining("readPaymentMethod"),
+      expect.objectContaining({
+        body: {
+          onlyAvailable: true,
+        },
+      }),
+    );
+  });
+
+  it("paymentChangeable", async () => {
+    const { vm, injections } = useSetup(() => useOrderDetails("123-test", {}));
+    injections.apiClient.invoke.mockResolvedValue({ data: Order });
+    expect(vm.paymentChangeable).toEqual(false);
+    await vm.loadOrderDetails();
+    expect(vm.paymentChangeable).toEqual(true);
+  });
 });
diff --git a/packages/composables/src/useOrderPayment.test.ts b/packages/composables/src/useOrderPayment.test.ts
index 9158f98f..86288c5c 100644
--- a/packages/composables/src/useOrderPayment.test.ts
+++ b/packages/composables/src/useOrderPayment.test.ts
@@ -7,7 +7,7 @@ import type { Schemas } from "#shopware";
 import Order from "./mocks/Order";
 
 describe("useOrderPayment", () => {
-  it("handlePayment", async () => {
+  it("should handle the order payment", async () => {
     const { vm, injections } = useSetup(() =>
       useOrderPayment(
         computed(() => Order.orders.elements[0]) as unknown as ComputedRef<
@@ -32,5 +32,49 @@ describe("useOrderPayment", () => {
     expect(vm.activeTransaction).toEqual(
       Order.orders.elements[0].transactions[0],
     );
+
+    vm.changePaymentMethod("test");
+
+    expect(injections.apiClient.invoke).toHaveBeenCalledWith(
+      expect.stringContaining("orderSetPayment"),
+      expect.objectContaining({
+        body: {
+          orderId: "018c6832f1a1731db276839b3f251fc2",
+          paymentMethodId: "test",
+        },
+      }),
+    );
+  });
+
+  it("should not invoke API calls for empty order", async () => {
+    const { vm } = useSetup(() =>
+      useOrderPayment(
+        computed(() => null) as unknown as ComputedRef<Schemas["Order"]>,
+      ),
+    );
+    expect(vm.changePaymentMethod("test")).resolves.toBeUndefined();
+    expect(vm.handlePayment()).resolves.toBeUndefined();
+  });
+
+  it("should be a asynchronous payment", () => {
+    const { vm } = useSetup(() =>
+      useOrderPayment(
+        computed(() =>
+          Object.assign(Order.orders.elements[0], {
+            transactions: [
+              {
+                paymentMethod: {
+                  active: true,
+                  asynchronous: true,
+                  afterOrderEnabled: true,
+                },
+              },
+            ],
+          }),
+        ) as unknown as ComputedRef<Schemas["Order"]>,
+      ),
+    );
+
+    expect(vm.isAsynchronous).toBe(true);
   });
 });
diff --git a/packages/composables/src/usePrice.test.ts b/packages/composables/src/usePrice.test.ts
index aca3c15f..a0f3a558 100644
--- a/packages/composables/src/usePrice.test.ts
+++ b/packages/composables/src/usePrice.test.ts
@@ -1,12 +1,53 @@
-import { describe, expect, it } from "vitest";
+import { describe, expect, it, vi, beforeEach } from "vitest";
+import { ref } from "vue";
 import { usePrice } from "./usePrice";
 import { useSetup } from "./_test";
+import { useSessionContext } from "./useSessionContext";
+const currentNavigator = global.navigator;
+
+vi.mock("./useSessionContext.ts");
+const sessionContext = ref();
+
+beforeEach(() => {
+  vi.clearAllMocks();
+  vi.mocked(useSessionContext).mockReturnValue({
+    sessionContext,
+  } as unknown as ReturnType<typeof useSessionContext>);
+});
 
 describe("usePrice", () => {
   it("should be defined", () => {
     expect(usePrice).toBeDefined();
   });
 
+  it("use default locale if locale is not provided", () => {
+    vi.spyOn(global, "navigator", "get").mockImplementation(
+      () => ({}) as Navigator,
+    );
+    const { vm } = useSetup(usePrice);
+    expect(vm.getFormattedPrice(2.55)).toMatchInlineSnapshot('"2.55"');
+    vm.update({
+      currencyCode: "USD",
+      localeCode: undefined,
+    });
+
+    expect(vm.getFormattedPrice(2.55)).toMatchInlineSnapshot('"$2.55"');
+  });
+
+  it("should use navigator language if locale is not provided", () => {
+    vi.spyOn(global, "navigator", "get").mockImplementation(
+      () => currentNavigator,
+    );
+    vi.spyOn(navigator, "language", "get").mockImplementation(() => "en-FR");
+    const { vm } = useSetup(usePrice);
+    vm.update({
+      currencyCode: "USD",
+      localeCode: undefined,
+    });
+
+    expect(vm.getFormattedPrice(2.55)).toMatchInlineSnapshot('"$2.55"');
+  });
+
   it("should init price object", () => {
     const { vm } = useSetup(() =>
       usePrice({
@@ -43,4 +84,15 @@ describe("usePrice", () => {
     const { vm } = useSetup(usePrice);
     expect(vm.getFormattedPrice(undefined)).toBe("");
   });
+
+  it("watch currency change", async () => {
+    const { vm } = useSetup(usePrice);
+    sessionContext.value = {
+      currency: {
+        isoCode: "PLN",
+      },
+    };
+    await vm.$nextTick();
+    expect(vm.currencyCode).toBe("PLN");
+  });
 });
diff --git a/packages/composables/src/useProduct.test.ts b/packages/composables/src/useProduct.test.ts
index a5349865..06248fe8 100644
--- a/packages/composables/src/useProduct.test.ts
+++ b/packages/composables/src/useProduct.test.ts
@@ -2,6 +2,7 @@ import { describe, expect, it } from "vitest";
 import { useProduct } from "./useProduct";
 import mockedProduct from "./mocks/Product";
 import { useSetup } from "./_test";
+import { ref } from "vue";
 
 describe("useProduct", () => {
   it("should return product object", () => {
@@ -10,9 +11,26 @@ describe("useProduct", () => {
     expect(vm.product).toStrictEqual(mockedProduct);
   });
 
-  it("should return undefined configurator object", () => {
+  it("changeVariant - should merge the current product with the new variant data", () => {
     const { vm } = useSetup(() => useProduct(mockedProduct));
+    expect(vm.changeVariant()).toBeUndefined();
+  });
+
+  it("changeVariant - empty", () => {
+    const { vm } = useSetup(useProduct);
+
+    vm.changeVariant(Object.assign({ ...mockedProduct }, { id: "new-id" }));
+    expect(vm.product.id).toBe("new-id");
+  });
 
-    expect(vm.configurator).toBe(undefined);
+  it("init without product should throw an error", () => {
+    expect(() =>
+      useSetup(() =>
+        useProduct(
+          // @ts-expect-error if API returns null we want to be prepared for it
+          ref(null),
+        ),
+      ),
+    ).toThrowError("Product context is not provided");
   });
 });
diff --git a/packages/composables/src/useProductPrice.test.ts b/packages/composables/src/useProductPrice.test.ts
index 10be3128..9db6c3a6 100644
--- a/packages/composables/src/useProductPrice.test.ts
+++ b/packages/composables/src/useProductPrice.test.ts
@@ -1,4 +1,4 @@
-import { describe, expect, it } from "vitest";
+import { describe, expect, it, vi, beforeEach } from "vitest";
 import { useProductPrice } from "./useProductPrice";
 import { ref } from "vue";
 import mockedProduct from "./mocks/Product";
@@ -7,6 +7,9 @@ import productTierPrices from "./mocks/ProductTierPrices";
 import type { Schemas } from "#shopware";
 
 describe("useProductPrice", () => {
+  beforeEach(() => {
+    vi.resetAllMocks();
+  });
   it("product price are displayed - standard product", () => {
     const { vm } = useSetup(() => useProductPrice(ref(mockedProduct)));
 
@@ -40,21 +43,17 @@ describe("useProductPrice", () => {
     expect(vm.displayFromVariants).toBe(20);
   });
 
-  it("displayFrom", () => {
+  it("displayFrom should be false if displayParent is true", () => {
     const { vm } = useSetup(() =>
       useProductPrice(
         ref(
           Object.assign(
             { ...productTierPrices.product },
             {
-              parentId: null,
+              calculatedPrices: null,
               variantListingConfig: {
                 displayParent: true,
               },
-              calculatedPrices: undefined,
-              listPrice: {
-                percentage: 100,
-              },
             },
           ) as unknown as Schemas["Product"],
         ),
@@ -63,4 +62,65 @@ describe("useProductPrice", () => {
     expect(vm.displayFrom).toBe(false);
     expect(vm.isListPrice).toBe(false);
   });
+
+  it("isListPrice should be false with more than one calculatedPrices value", () => {
+    const { vm } = useSetup(() =>
+      useProductPrice(
+        ref(
+          Object.assign(
+            { ...productTierPrices.product },
+            {
+              listPrice: 80,
+              calculatedPrices: [
+                {
+                  unitPrice: 10,
+                },
+                {
+                  unitPrice: 20,
+                },
+              ],
+            },
+          ) as unknown as Schemas["Product"],
+        ),
+      ),
+    );
+    expect(vm.displayFrom).toBe(true);
+    expect(vm.isListPrice).toBe(false);
+  });
+
+  it("isListPrice should be true with one calculatedPrices value", () => {
+    const { vm } = useSetup(() =>
+      useProductPrice(
+        ref({
+          calculatedPrices: [
+            {
+              listPrice: {
+                percentage: 10,
+              },
+            },
+          ],
+        } as unknown as Schemas["Product"]),
+      ),
+    );
+    expect(vm.displayFrom).toBe(false);
+    expect(vm.isListPrice).toBe(true);
+  });
+
+  it("displayFrom - second variant", async () => {
+    const { vm } = useSetup(() =>
+      useProductPrice(
+        ref({
+          variantListingConfig: {
+            displayParent: true,
+          },
+          parentId: null,
+          calculatedCheapestPrice: {
+            hasRange: true,
+          },
+        } as unknown as Schemas["Product"]),
+      ),
+    );
+    expect(vm.displayFrom).toBe(false);
+    expect(vm.isListPrice).toBe(false);
+  });
 });
diff --git a/packages/composables/src/useProductWishlist.test.ts b/packages/composables/src/useProductWishlist.test.ts
index b431e60b..91b2b1a3 100644
--- a/packages/composables/src/useProductWishlist.test.ts
+++ b/packages/composables/src/useProductWishlist.test.ts
@@ -32,6 +32,7 @@ describe("useProductWishlist", () => {
       const { vm } = useSetup(() => useProductWishlist("test3"));
 
       expect(vm.removeFromWishlist()).resolves.toEqual(undefined);
+      expect(vm.isInWishlist).toEqual(false);
     });
   });
 
@@ -50,9 +51,14 @@ describe("useProductWishlist", () => {
     });
 
     it("removeFromWishlist", () => {
+      vi.mocked(useUser).mockReturnValue({
+        isLoggedIn: ref(true),
+        isGuestSession: ref(false),
+      } as ReturnType<typeof useUser>);
       const { vm } = useSetup(() => useProductWishlist("test3"));
 
       expect(vm.removeFromWishlist()).resolves.toEqual(undefined);
+      expect(vm.isInWishlist).toEqual(false);
     });
   });
 });
diff --git a/packages/composables/src/useSyncWishlist.test.ts b/packages/composables/src/useSyncWishlist.test.ts
index fa261ccc..7c3b95f7 100644
--- a/packages/composables/src/useSyncWishlist.test.ts
+++ b/packages/composables/src/useSyncWishlist.test.ts
@@ -1,15 +1,19 @@
-import { describe, expect, it, vi } from "vitest";
+import { describe, expect, it, vi, beforeEach } from "vitest";
 import { useSyncWishlist } from "./useSyncWishlist";
 import { useSetup } from "./_test";
 import { ApiClientError } from "@shopware/api-client";
 import type { FetchResponse } from "ofetch";
 
 describe("useSyncWishlist", () => {
+  beforeEach(() => {
+    vi.clearAllMocks();
+  });
+
   const consoleErrorSpy = vi.spyOn(console, "error");
   consoleErrorSpy.mockImplementation(() => {});
   describe("methods", () => {
     describe("addToWishlist", () => {
-      it("wishlist add product", () => {
+      it("should add product to the wishlist", () => {
         const { vm } = useSetup(() => useSyncWishlist());
 
         expect(vm.addToWishlistSync("some-id")).resolves.toBe(undefined);
@@ -17,7 +21,7 @@ describe("useSyncWishlist", () => {
     });
 
     describe("removeFromWishlist", () => {
-      it("wishlist remove", () => {
+      it("should remove product from the wishlist", () => {
         const { vm } = useSetup(() => useSyncWishlist());
 
         vm.getWishlistProducts();
@@ -28,7 +32,7 @@ describe("useSyncWishlist", () => {
     });
 
     describe("mergeWishlistProducts", () => {
-      it("wishlist remove", () => {
+      it("should sync wishlist", () => {
         const { vm } = useSetup(() => useSyncWishlist());
 
         expect(vm.mergeWishlistProducts(["test1", "test2"])).resolves.toEqual(
@@ -38,17 +42,53 @@ describe("useSyncWishlist", () => {
     });
 
     describe("getWishlistProducts", () => {
-      it("getWishlistProducts", () => {
-        const { vm } = useSetup(() => useSyncWishlist());
+      it("should get wishlist products", async () => {
+        const { vm, injections } = useSetup(() => useSyncWishlist());
+        injections.apiClient.invoke.mockResolvedValue({
+          data: {
+            products: {
+              elements: [],
+            },
+          },
+        });
+        await vm.getWishlistProducts();
 
-        vm.getWishlistProducts();
         expect(vm.count).toBe(0);
         expect(vm.items.length).toBe(0);
       });
+
+      it("getWishlistProducts", async () => {
+        const { vm, injections } = useSetup(() => useSyncWishlist());
+        injections.apiClient.invoke.mockResolvedValue({
+          data: {
+            products: {
+              total: 9,
+              page: 1,
+              elements: [
+                {
+                  id: "test-id",
+                },
+              ],
+            },
+          },
+        });
+        await vm.getWishlistProducts();
+
+        expect(injections.apiClient.invoke).toHaveBeenCalledWith(
+          expect.stringContaining("readCustomerWishlist"),
+          expect.objectContaining({
+            body: {
+              "total-count-mode": "exact",
+            },
+          }),
+        );
+        expect(vm.count).toBe(9);
+        expect(vm.items.length).toBe(1);
+      });
     });
 
     describe("getWishlistProducts - error", () => {
-      it("getWishlistProducts", async () => {
+      it("should handle error after fetching product wishlist", async () => {
         const { vm } = useSetup(() => useSyncWishlist(), {
           apiClient: {
             invoke: vi.fn().mockImplementation(() => {
@@ -69,7 +109,7 @@ describe("useSyncWishlist", () => {
         });
         vm.getWishlistProducts();
         expect(consoleErrorSpy).toHaveBeenCalledTimes(1);
-        expect(vm.count).toBe(0);
+        expect(vm.count).toBe(9);
         expect(vm.items.length).toBe(0);
       });
     });
diff --git a/packages/composables/src/useWishlist.test.ts b/packages/composables/src/useWishlist.test.ts
index a5c393d1..7ae3d24f 100644
--- a/packages/composables/src/useWishlist.test.ts
+++ b/packages/composables/src/useWishlist.test.ts
@@ -47,13 +47,11 @@ vi.mock("./useSyncWishlist.ts");
 vi.mock("./useUser");
 
 describe("useWishlist - not logged in user", () => {
-  it("mergeWishlistProducts", () => {
+  it("should merge wishlist products", () => {
     vi.mocked(useUser).mockReturnValue(getMockedUser(false, true));
     vi.mocked(useSyncWishlist).mockReturnValue({
       getWishlistProducts: () => new Promise<void>((resolve) => resolve()),
-      items: computed((): string[] => {
-        return ["test1"];
-      }),
+      items: computed((): string[] => []),
       addToWishlistSync: () => undefined,
       mergeWishlistProducts: () => undefined,
       removeFromWishlistSync: () => undefined,
@@ -71,13 +69,11 @@ describe("useWishlist - not logged in user", () => {
     expect(Number(vm.totalPagesCount)).toBe(2);
   });
 
-  it("getWishlistProducts", async () => {
+  it("should get wishlist products", async () => {
     vi.mocked(useUser).mockReturnValue(getMockedUser(false, true));
     vi.mocked(useSyncWishlist).mockReturnValue({
       getWishlistProducts: () => new Promise<void>((resolve) => resolve()),
-      items: computed((): string[] => {
-        return ["test1"];
-      }),
+      items: computed((): string[] => ["test1"]),
       addToWishlistSync: () => undefined,
       mergeWishlistProducts: () => undefined,
       removeFromWishlistSync: () => undefined,
@@ -119,7 +115,7 @@ describe("useWishlist - not logged in user", () => {
 });
 
 describe("useWishlist - logged in user", () => {
-  it("mergeWishlistProducts", () => {
+  it("should merge wishlist products", () => {
     vi.mocked(useUser).mockReturnValue(getMockedUser(true, false));
     vi.mocked(useSyncWishlist).mockReturnValue({
       getWishlistProducts: () => new Promise<void>((resolve) => resolve()),
@@ -158,7 +154,7 @@ describe("useWishlist - logged in user", () => {
     expect(vm.count).toBe(15);
   });
 
-  it("getWishlistProducts", () => {
+  it("should get wishlist products", () => {
     vi.mocked(useUser).mockReturnValue(getMockedUser(true, false));
     const { vm } = useSetup(() => useWishlist());
     vm.getWishlistProducts();
diff --git a/packages/composables/vitest.config.ts b/packages/composables/vitest.config.ts
index 72ac8f88..6c34acd7 100644
--- a/packages/composables/vitest.config.ts
+++ b/packages/composables/vitest.config.ts
@@ -7,14 +7,17 @@ export default defineConfig({
     coverage: {
       enabled: true,
       include: ["src"],
-      // "100": true, // TODO: our goal ;)
       thresholds: {
-        statements: 97,
-        branches: 90,
-        functions: 88.4,
-        lines: 97,
+        100: true,
       },
-      exclude: ["**/devtools/**"],
+      exclude: [
+        "**/devtools/**",
+        "**/types/**",
+        "**/src/*.test.ts",
+        "**/src/*.spec.ts",
+        // After refactoring should be removed - https://github.com/shopware/frontends/issues/1057
+        "**/src/useListing.ts",
+      ],
     },
     alias: {
       "#imports": resolve(__dirname, "./src/index.ts"),