@pplancq/react-template 2.9.0 → 2.10.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.
Files changed (89) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/mise.toml +2 -2
  3. package/mocks/browser.ts +1 -1
  4. package/mocks/fixtures/user.ts +14 -14
  5. package/mocks/handlers/userHandlers.ts +3 -3
  6. package/mocks/server.ts +1 -1
  7. package/package.json +24 -25
  8. package/playwright-report/html/index.html +90 -0
  9. package/playwright-report/sonar-results.xml +20 -0
  10. package/playwright.config.ts +3 -3
  11. package/src/app/App.tsx +5 -5
  12. package/src/app/AppHTMLElement.tsx +4 -4
  13. package/src/app/README.md +2 -2
  14. package/src/app/assets/css/index.ts +2 -2
  15. package/src/app/assets/css/reset.css +3 -3
  16. package/src/app/config/queryClientConfig.ts +1 -1
  17. package/src/app/config/serviceContainer.ts +2 -2
  18. package/src/app/providers/Providers/Providers.tsx +5 -5
  19. package/src/app/providers/QueryClientProvider/QueryClientProvider.tsx +3 -3
  20. package/src/app/providers/ServiceProvider/ServiceContext.ts +2 -2
  21. package/src/app/providers/ServiceProvider/ServiceProvider.tsx +4 -4
  22. package/src/app/routing/Router.tsx +2 -2
  23. package/src/app/routing/appRoutes.ts +1 -1
  24. package/src/app/routing/routes.tsx +3 -3
  25. package/src/demo/README.md +5 -4
  26. package/src/demo/application/dtos/ArchitecturePrinciple.ts +1 -1
  27. package/src/demo/application/use-cases/GetArchitecturePrinciplesUseCase.ts +3 -3
  28. package/src/demo/application/use-cases/GetArchitecturePrinciplesUseCaseInterface.ts +1 -1
  29. package/src/demo/application/use-cases/GetDemoUsersUseCase.ts +3 -3
  30. package/src/demo/application/use-cases/GetDemoUsersUseCaseInterface.ts +1 -1
  31. package/src/demo/domain/repositories/ArchitecturePrincipleRepositoryInterface.d.ts +1 -1
  32. package/src/demo/domain/repositories/DemoUserRepositoryInterface.d.ts +1 -1
  33. package/src/demo/infrastructure/repositories/HttpDemoUserRepository.ts +5 -5
  34. package/src/demo/infrastructure/repositories/StaticArchitecturePrincipleRepository.ts +14 -14
  35. package/src/demo/serviceDemo.ts +14 -13
  36. package/src/demo/serviceIdentifiers.ts +4 -4
  37. package/src/demo/ui/components/DemoFooter/DemoFooter.tsx +5 -5
  38. package/src/demo/ui/components/DemoFooter/index.ts +1 -1
  39. package/src/demo/ui/components/DemoHeader/DemoHeader.tsx +10 -10
  40. package/src/demo/ui/components/DemoHeader/index.ts +1 -1
  41. package/src/demo/ui/components/DemoNavigation/DemoNavigation.tsx +4 -4
  42. package/src/demo/ui/components/DemoNavigation/index.ts +1 -1
  43. package/src/demo/ui/components/Input/Input.tsx +3 -3
  44. package/src/demo/ui/components/Input/index.ts +1 -1
  45. package/src/demo/ui/components/Logo/Logo.tsx +2 -2
  46. package/src/demo/ui/components/Logo/index.ts +1 -1
  47. package/src/demo/ui/components/NavLink/NavLink.tsx +3 -3
  48. package/src/demo/ui/components/NavLink/index.ts +1 -1
  49. package/src/demo/ui/components/TextInput/TextInput.tsx +3 -3
  50. package/src/demo/ui/components/TextInput/index.ts +1 -1
  51. package/src/demo/ui/forms/ProfileForm/ProfileForm.tsx +9 -9
  52. package/src/demo/ui/forms/ProfileForm/index.ts +1 -1
  53. package/src/demo/ui/hooks/useDemoUsersQuery/useDemoUsersQuery.ts +5 -5
  54. package/src/demo/ui/layouts/DemoLayout/DemoLayout.tsx +4 -4
  55. package/src/demo/ui/layouts/MainTemplate/MainTemplate.tsx +2 -2
  56. package/src/demo/ui/layouts/MainTemplate/index.ts +1 -1
  57. package/src/demo/ui/pages/DemoHome/DemoHome.module.scss +5 -5
  58. package/src/demo/ui/pages/DemoHome/DemoHome.tsx +6 -6
  59. package/src/demo/ui/pages/DependencyInjectionDemo/DependencyInjectionDemo.tsx +5 -5
  60. package/src/demo/ui/pages/ReactHookFormDemo/ReactHookFormDemo.tsx +4 -4
  61. package/src/demo/ui/pages/ReactQueryDemo/ReactQueryDemo.tsx +3 -3
  62. package/src/demo/ui/routing/demoAppRoutes.ts +4 -4
  63. package/src/demo/ui/routing/demoRoutes.tsx +8 -8
  64. package/src/main.ts +5 -5
  65. package/src/react-app-env.d.ts +1 -1
  66. package/src/shared/infrastructure/http/constant.ts +8 -8
  67. package/src/shared/infrastructure/http/fetchApi.ts +3 -3
  68. package/src/shared/ui/hooks/useService/useService.ts +4 -4
  69. package/test-results/.last-run.json +4 -0
  70. package/tests/e2e/demo.test.ts +17 -0
  71. package/tests/e2e/fixture/playwright.fixture.ts +15 -0
  72. package/tests/{utils → e2e/utils}/createNetworkFixture.ts +2 -2
  73. package/tests/{utils → e2e/utils}/createTestWithCoverageFixture.ts +8 -8
  74. package/tests/{utils → e2e/utils}/playwright.globalSetup.ts +4 -4
  75. package/tests/{utils → e2e/utils}/playwright.globalTeardown.ts +3 -3
  76. package/{src/app/__tests__ → tests/unit/app}/AppHTMLElement.test.tsx +14 -14
  77. package/tests/unit/demo/ui/components/DemoFooter/Footer.test.tsx +15 -0
  78. package/tests/unit/demo/ui/components/DemoHeader/Header.test.tsx +15 -0
  79. package/tests/unit/demo/ui/components/Logo/Logo.test.tsx +12 -0
  80. package/tsconfig.json +1 -1
  81. package/vitest.config.mts +1 -1
  82. package/postcss.config.mjs +0 -5
  83. package/src/demo/ui/components/DemoFooter/__tests__/Footer.test.tsx +0 -15
  84. package/src/demo/ui/components/DemoHeader/__tests__/Header.test.tsx +0 -15
  85. package/src/demo/ui/components/Logo/__tests__/Logo.test.tsx +0 -12
  86. package/tests/demo.test.ts +0 -17
  87. package/tests/fixture/playwright.fixture.ts +0 -15
  88. /package/{src/demo/ui/components/DemoFooter/__tests__ → tests/unit/demo/ui/components/DemoFooter}/__snapshots__/Footer.test.tsx.snap +0 -0
  89. /package/{src/demo/ui/components/DemoHeader/__tests__ → tests/unit/demo/ui/components/DemoHeader}/__snapshots__/Header.test.tsx.snap +0 -0
@@ -1,9 +1,9 @@
1
- import type { ProfileFormValues } from '@Demo/application/dtos/ProfileFormValues';
2
- import { TextInput } from '@Demo/ui/components/TextInput/TextInput';
3
- import { yupResolver } from '@hookform/resolvers/yup';
4
- import { FormProvider, type SubmitHandler, useForm } from 'react-hook-form';
5
- import * as yup from 'yup';
6
- import classes from './ProfileForm.module.scss';
1
+ import type { ProfileFormValues } from "@Demo/application/dtos/ProfileFormValues";
2
+ import { TextInput } from "@Demo/ui/components/TextInput/TextInput";
3
+ import { yupResolver } from "@hookform/resolvers/yup";
4
+ import { FormProvider, type SubmitHandler, useForm } from "react-hook-form";
5
+ import * as yup from "yup";
6
+ import classes from "./ProfileForm.module.scss";
7
7
 
8
8
  type ProfileFormProps = {
9
9
  onSubmit: SubmitHandler<ProfileFormValues>;
@@ -11,9 +11,9 @@ type ProfileFormProps = {
11
11
  };
12
12
 
13
13
  const schema = yup.object().shape({
14
- mail: yup.string().email('Check the mail pattern').required('This field is required'),
15
- firstName: yup.string().required('This field is required'),
16
- lastName: yup.string().required('This field is required'),
14
+ mail: yup.string().email("Check the mail pattern").required("This field is required"),
15
+ firstName: yup.string().required("This field is required"),
16
+ lastName: yup.string().required("This field is required"),
17
17
  });
18
18
 
19
19
  export const ProfileForm = ({ onSubmit, resetForm }: ProfileFormProps) => {
@@ -1 +1 @@
1
- export { ProfileForm } from './ProfileForm';
1
+ export { ProfileForm } from "./ProfileForm";
@@ -1,13 +1,13 @@
1
- import type { GetDemoUsersUseCaseInterface } from '@Demo/application/use-cases/GetDemoUsersUseCaseInterface';
2
- import { DEMO_SERVICES } from '@Demo/serviceIdentifiers';
3
- import { useService } from '@Shared/ui/hooks/useService/useService';
4
- import { useQuery } from '@tanstack/react-query';
1
+ import type { GetDemoUsersUseCaseInterface } from "@Demo/application/use-cases/GetDemoUsersUseCaseInterface";
2
+ import { DEMO_SERVICES } from "@Demo/serviceIdentifiers";
3
+ import { useService } from "@Shared/ui/hooks/useService/useService";
4
+ import { useQuery } from "@tanstack/react-query";
5
5
 
6
6
  export const useDemoUsersQuery = () => {
7
7
  const getDemoUsersUseCase = useService<GetDemoUsersUseCaseInterface>(DEMO_SERVICES.GetDemoUsersUseCase);
8
8
 
9
9
  return useQuery({
10
- queryKey: ['demo-users'],
10
+ queryKey: ["demo-users"],
11
11
  queryFn: () => getDemoUsersUseCase.execute(),
12
12
  });
13
13
  };
@@ -1,7 +1,7 @@
1
- import { DemoFooter } from '@Demo/ui/components/DemoFooter/DemoFooter';
2
- import { DemoHeader } from '@Demo/ui/components/DemoHeader/DemoHeader';
3
- import { MainTemplate } from '@Demo/ui/layouts/MainTemplate/MainTemplate';
4
- import { Outlet } from 'react-router';
1
+ import { DemoFooter } from "@Demo/ui/components/DemoFooter/DemoFooter";
2
+ import { DemoHeader } from "@Demo/ui/components/DemoHeader/DemoHeader";
3
+ import { MainTemplate } from "@Demo/ui/layouts/MainTemplate/MainTemplate";
4
+ import { Outlet } from "react-router";
5
5
 
6
6
  export const DemoLayout = () => {
7
7
  return (
@@ -1,6 +1,6 @@
1
- import type { PropsWithChildren, ReactNode } from 'react';
1
+ import type { PropsWithChildren, ReactNode } from "react";
2
2
 
3
- import classes from './MainTemplate.module.css';
3
+ import classes from "./MainTemplate.module.css";
4
4
 
5
5
  type MainTemplateProps = {
6
6
  headerProps: {
@@ -1 +1 @@
1
- export { MainTemplate } from './MainTemplate';
1
+ export { MainTemplate } from "./MainTemplate";
@@ -40,7 +40,7 @@
40
40
  border-top: 1px solid #ccc;
41
41
  border-bottom: 1px solid #ccc;
42
42
  background-color: #f8f8f8;
43
- content: '';
43
+ content: "";
44
44
  }
45
45
 
46
46
  &::after {
@@ -49,7 +49,7 @@
49
49
  border-top: 1px solid #ccc;
50
50
  border-bottom: 1px solid #ccc;
51
51
  background-color: #f8f8f8;
52
- content: ' ';
52
+ content: " ";
53
53
  }
54
54
  }
55
55
  }
@@ -83,7 +83,7 @@
83
83
  width: 55px;
84
84
  height: 5px;
85
85
  background-color: #111;
86
- content: '';
86
+ content: "";
87
87
  }
88
88
 
89
89
  &::after {
@@ -94,7 +94,7 @@
94
94
  max-width: 255px;
95
95
  height: 1px;
96
96
  background-color: #333;
97
- content: '';
97
+ content: "";
98
98
  }
99
99
  }
100
100
 
@@ -177,7 +177,7 @@ li {
177
177
  code {
178
178
  padding: 2px 5px;
179
179
  border-radius: 4px;
180
- font-family: 'Courier New', monospace;
180
+ font-family: "Courier New", monospace;
181
181
  font-size: 14px;
182
182
  background-color: #f8f9fa;
183
183
  }
@@ -1,7 +1,7 @@
1
- import image from '@Demo/ui/assets/images/templatePlugins.png';
2
- import { demoAppRoutes } from '@Demo/ui/routing/demoAppRoutes';
3
- import { NavLink } from '@Demo/ui/components/NavLink/NavLink';
4
- import classes from './DemoHome.module.scss';
1
+ import image from "@Demo/ui/assets/images/templatePlugins.png";
2
+ import { NavLink } from "@Demo/ui/components/NavLink/NavLink";
3
+ import { demoAppRoutes } from "@Demo/ui/routing/demoAppRoutes";
4
+ import classes from "./DemoHome.module.scss";
5
5
 
6
6
  export const DemoHome = () => {
7
7
  return (
@@ -18,8 +18,8 @@ export const DemoHome = () => {
18
18
  <span className={classes.centredText}>
19
19
  <p className={classes.paragraphStyle}>
20
20
  This template now starts from a <span className={classes.highlight}>Clean Architecture</span> inspired
21
- structure with a dedicated <span className={classes.boldText}>app</span> bootstrap layer, a{' '}
22
- <span className={classes.boldText}>shared</span> common layer, and a{' '}
21
+ structure with a dedicated <span className={classes.boldText}>app</span> bootstrap layer, a{" "}
22
+ <span className={classes.boldText}>shared</span> common layer, and a{" "}
23
23
  <span className={classes.boldText}>demo</span> bounded context.
24
24
  </p>
25
25
  <p className={classes.paragraphStyle}>
@@ -1,7 +1,7 @@
1
- import type { GetArchitecturePrinciplesUseCaseInterface } from '@Demo/application/use-cases/GetArchitecturePrinciplesUseCaseInterface';
2
- import { DEMO_SERVICES } from '@Demo/serviceIdentifiers';
3
- import { useService } from '@Shared/ui/hooks/useService/useService';
4
- import classes from './DependencyInjectionDemo.module.scss';
1
+ import type { GetArchitecturePrinciplesUseCaseInterface } from "@Demo/application/use-cases/GetArchitecturePrinciplesUseCaseInterface";
2
+ import { DEMO_SERVICES } from "@Demo/serviceIdentifiers";
3
+ import { useService } from "@Shared/ui/hooks/useService/useService";
4
+ import classes from "./DependencyInjectionDemo.module.scss";
5
5
 
6
6
  export const DependencyInjectionDemo = () => {
7
7
  const getArchitecturePrinciplesUseCase = useService<GetArchitecturePrinciplesUseCaseInterface>(
@@ -31,7 +31,7 @@ export const DependencyInjectionDemo = () => {
31
31
  </tr>
32
32
  </thead>
33
33
  <tbody>
34
- {architecturePrinciples.map(principle => (
34
+ {architecturePrinciples.map((principle) => (
35
35
  <tr key={`${principle.layer}-${principle.title}`}>
36
36
  <td>{principle.layer}</td>
37
37
  <td>{principle.title}</td>
@@ -1,8 +1,8 @@
1
- import type { ProfileFormValues } from '@Demo/application/dtos/ProfileFormValues';
2
- import { ProfileForm } from '@Demo/ui/forms/ProfileForm/ProfileForm';
3
- import { useState } from 'react';
1
+ import type { ProfileFormValues } from "@Demo/application/dtos/ProfileFormValues";
2
+ import { ProfileForm } from "@Demo/ui/forms/ProfileForm/ProfileForm";
3
+ import { useState } from "react";
4
4
 
5
- import classes from './ReactHookFormDemo.module.scss';
5
+ import classes from "./ReactHookFormDemo.module.scss";
6
6
 
7
7
  export const ReactHookFormDemo = () => {
8
8
  const [profileData, setProfileData] = useState<ProfileFormValues>();
@@ -1,5 +1,5 @@
1
- import { useDemoUsersQuery } from '@Demo/ui/hooks/useDemoUsersQuery/useDemoUsersQuery';
2
- import classes from './ReactQueryDemo.module.scss';
1
+ import { useDemoUsersQuery } from "@Demo/ui/hooks/useDemoUsersQuery/useDemoUsersQuery";
2
+ import classes from "./ReactQueryDemo.module.scss";
3
3
 
4
4
  export const ReactQueryDemo = () => {
5
5
  const { data = [], isLoading, isError } = useDemoUsersQuery();
@@ -36,7 +36,7 @@ export const ReactQueryDemo = () => {
36
36
  </tr>
37
37
  </thead>
38
38
  <tbody>
39
- {data.map(eachResult => (
39
+ {data.map((eachResult) => (
40
40
  <tr key={eachResult.id}>
41
41
  <td>{eachResult.id}</td>
42
42
  <td>{eachResult.name}</td>
@@ -1,6 +1,6 @@
1
1
  export const demoAppRoutes = Object.freeze({
2
- home: '/',
3
- reactQuery: '/react-query',
4
- reactHookForm: '/react-hook-form',
5
- dependencyInjection: '/dependency-injection',
2
+ home: "/",
3
+ reactQuery: "/react-query",
4
+ reactHookForm: "/react-hook-form",
5
+ dependencyInjection: "/dependency-injection",
6
6
  });
@@ -1,12 +1,12 @@
1
- import { demoAppRoutes } from '@Demo/ui/routing/demoAppRoutes';
2
- import { DemoLayout } from '@Demo/ui/layouts/DemoLayout/DemoLayout';
3
- import { DemoHome } from '@Demo/ui/pages/DemoHome/DemoHome';
4
- import { DependencyInjectionDemo } from '@Demo/ui/pages/DependencyInjectionDemo/DependencyInjectionDemo';
5
- import { ReactHookFormDemo } from '@Demo/ui/pages/ReactHookFormDemo/ReactHookFormDemo';
6
- import { ReactQueryDemo } from '@Demo/ui/pages/ReactQueryDemo/ReactQueryDemo';
7
- import type { RouteObject } from 'react-router';
1
+ import { DemoLayout } from "@Demo/ui/layouts/DemoLayout/DemoLayout";
2
+ import { DemoHome } from "@Demo/ui/pages/DemoHome/DemoHome";
3
+ import { DependencyInjectionDemo } from "@Demo/ui/pages/DependencyInjectionDemo/DependencyInjectionDemo";
4
+ import { ReactHookFormDemo } from "@Demo/ui/pages/ReactHookFormDemo/ReactHookFormDemo";
5
+ import { ReactQueryDemo } from "@Demo/ui/pages/ReactQueryDemo/ReactQueryDemo";
6
+ import { demoAppRoutes } from "@Demo/ui/routing/demoAppRoutes";
7
+ import type { RouteObject } from "react-router";
8
8
 
9
- const toRelativePath = (path: string) => path.replace(/^\//, '');
9
+ const toRelativePath = (path: string) => path.replace(/^\//, "");
10
10
 
11
11
  export const demoRoutes: RouteObject = {
12
12
  element: <DemoLayout />,
package/src/main.ts CHANGED
@@ -1,10 +1,10 @@
1
- import AppHTMLElement from '@App/AppHTMLElement';
1
+ import AppHTMLElement from "@App/AppHTMLElement";
2
2
 
3
- if (import.meta.env.FRONT_MOCK_ENABLE === 'true') {
4
- const { worker } = await import('@Mocks/browser');
3
+ if (import.meta.env.FRONT_MOCK_ENABLE === "true") {
4
+ const { worker } = await import("@Mocks/browser");
5
5
  await worker.start({
6
- onUnhandledRequest: 'warn',
6
+ onUnhandledRequest: "warn",
7
7
  });
8
8
  }
9
9
 
10
- customElements.define('app-react', AppHTMLElement);
10
+ customElements.define("app-react", AppHTMLElement);
@@ -1,3 +1,3 @@
1
1
  interface ImportMetaEnv {
2
- readonly FRONT_MOCK_ENABLE: 'true' | 'false';
2
+ readonly FRONT_MOCK_ENABLE: "true" | "false";
3
3
  }
@@ -1,16 +1,16 @@
1
1
  export enum METHODS {
2
- get = 'GET',
3
- post = 'POST',
4
- put = 'PUT',
5
- patch = 'PATCH',
6
- delete = 'DELETE',
2
+ get = "GET",
3
+ post = "POST",
4
+ put = "PUT",
5
+ patch = "PATCH",
6
+ delete = "DELETE",
7
7
  }
8
8
 
9
9
  export enum HEADERS {
10
- contentType = 'content-type',
10
+ contentType = "content-type",
11
11
  }
12
12
 
13
13
  export enum MIME_TYPES {
14
- json = 'application/json',
15
- text = 'plain/text',
14
+ json = "application/json",
15
+ text = "plain/text",
16
16
  }
@@ -1,5 +1,5 @@
1
- import type { Json } from './fetchApi.type';
2
- import { HEADERS, METHODS, MIME_TYPES } from './constant';
1
+ import { HEADERS, METHODS, MIME_TYPES } from "./constant";
2
+ import type { Json } from "./fetchApi.type";
3
3
 
4
4
  export type FetchApiError = Error & {
5
5
  code?: number;
@@ -41,7 +41,7 @@ export const fetchApi = async <T extends Json | string>({
41
41
  throw error;
42
42
  }
43
43
 
44
- if ((response.headers.get(HEADERS.contentType) ?? '').includes('json')) {
44
+ if ((response.headers.get(HEADERS.contentType) ?? "").includes("json")) {
45
45
  return JSON.parse(content) as T;
46
46
  }
47
47
 
@@ -1,12 +1,12 @@
1
- import { ServiceContext } from '@App/providers/ServiceProvider/ServiceContext';
2
- import type { ServiceIdentifier } from 'inversify';
3
- import { useContext } from 'react';
1
+ import { ServiceContext } from "@App/providers/ServiceProvider/ServiceContext";
2
+ import type { ServiceIdentifier } from "inversify";
3
+ import { useContext } from "react";
4
4
 
5
5
  export const useService = <T = unknown>(serviceIdentifier: ServiceIdentifier<T>): T => {
6
6
  const context = useContext(ServiceContext);
7
7
 
8
8
  if (!context) {
9
- throw new Error('useService must be used within a ServiceProvider');
9
+ throw new Error("useService must be used within a ServiceProvider");
10
10
  }
11
11
 
12
12
  return context.container.get<T>(serviceIdentifier);
@@ -0,0 +1,4 @@
1
+ {
2
+ "status": "passed",
3
+ "failedTests": []
4
+ }
@@ -0,0 +1,17 @@
1
+ import { getUsers200 } from "@Mocks/handlers/userHandlers";
2
+ import { expect } from "@playwright/test";
3
+ import { describe, it } from "./fixture/playwright.fixture";
4
+
5
+ describe("Demo Test", () => {
6
+ it("should have a title", async ({ page }) => {
7
+ await page.goto("/");
8
+ const title = page.getByText("WELCOME TO YOUR REACT STARTER KIT");
9
+ await expect(title).toBeVisible();
10
+ });
11
+
12
+ it("should data fetching", async ({ page, network }) => {
13
+ network.use(getUsers200);
14
+ await page.goto("/react-query");
15
+ await expect(page.getByText("Demo user")).toBeVisible();
16
+ });
17
+ });
@@ -0,0 +1,15 @@
1
+ import type { NetworkFixture } from "@msw/playwright";
2
+ import { test as base } from "@playwright/test";
3
+ import { createNetworkFixture } from "../utils/createNetworkFixture";
4
+ import { createTestWithCoverageFixture } from "../utils/createTestWithCoverageFixture";
5
+
6
+ export const test = base.extend<{
7
+ testWithCoverage: string;
8
+ network: NetworkFixture;
9
+ }>({
10
+ testWithCoverage: createTestWithCoverageFixture(),
11
+ network: createNetworkFixture(),
12
+ });
13
+
14
+ export const it = test;
15
+ export const { describe } = test;
@@ -1,5 +1,5 @@
1
- import { defineNetworkFixture, type NetworkFixture } from '@msw/playwright';
2
- import type { PlaywrightTestArgs, PlaywrightWorkerArgs, TestFixture } from '@playwright/test';
1
+ import { defineNetworkFixture, type NetworkFixture } from "@msw/playwright";
2
+ import type { PlaywrightTestArgs, PlaywrightWorkerArgs, TestFixture } from "@playwright/test";
3
3
 
4
4
  export const createNetworkFixture = (): [
5
5
  TestFixture<NetworkFixture, PlaywrightTestArgs & PlaywrightWorkerArgs>,
@@ -1,14 +1,14 @@
1
- import type { PlaywrightTestArgs, PlaywrightWorkerArgs, TestFixture } from '@playwright/test';
2
- import { test } from '@playwright/test';
3
- import { CoverageReport } from 'monocart-coverage-reports';
4
- import { coverageOptions } from '../../mrc.playwright.config';
1
+ import type { PlaywrightTestArgs, PlaywrightWorkerArgs, TestFixture } from "@playwright/test";
2
+ import { test } from "@playwright/test";
3
+ import { CoverageReport } from "monocart-coverage-reports";
4
+ import { coverageOptions } from "../../../mrc.playwright.config";
5
5
 
6
6
  export const createTestWithCoverageFixture = (): [
7
7
  TestFixture<string, PlaywrightTestArgs & PlaywrightWorkerArgs>,
8
- { scope: 'test'; auto: true },
8
+ { scope: "test"; auto: true },
9
9
  ] => [
10
10
  async ({ page }, use) => {
11
- const isChromium = test.info().project.name === 'chromium';
11
+ const isChromium = test.info().project.name === "chromium";
12
12
 
13
13
  if (isChromium && coverageOptions.enabled) {
14
14
  await page.coverage.startJSCoverage({
@@ -16,7 +16,7 @@ export const createTestWithCoverageFixture = (): [
16
16
  });
17
17
  }
18
18
 
19
- await use('testWithCoverage');
19
+ await use("testWithCoverage");
20
20
 
21
21
  if (isChromium && coverageOptions.enabled) {
22
22
  const coverageList = await page.coverage.stopJSCoverage();
@@ -25,7 +25,7 @@ export const createTestWithCoverageFixture = (): [
25
25
  }
26
26
  },
27
27
  {
28
- scope: 'test',
28
+ scope: "test",
29
29
  auto: true,
30
30
  },
31
31
  ];
@@ -1,10 +1,10 @@
1
- import type { FullConfig } from '@playwright/test';
2
- import { CoverageReport } from 'monocart-coverage-reports';
3
- import { coverageOptions } from '../../mrc.playwright.config';
1
+ import type { FullConfig } from "@playwright/test";
2
+ import { CoverageReport } from "monocart-coverage-reports";
3
+ import { coverageOptions } from "../../../mrc.playwright.config";
4
4
 
5
5
  const globalSetup = (config: FullConfig) => {
6
6
  if (config.webServer && coverageOptions.enabled) {
7
- console.info('[playwright] Coverage enabled with monocart');
7
+ console.info("[playwright] Coverage enabled with monocart");
8
8
  const mcr = new CoverageReport(coverageOptions);
9
9
  mcr.cleanCache();
10
10
  }
@@ -1,6 +1,6 @@
1
- import type { FullConfig } from '@playwright/test';
2
- import { CoverageReport } from 'monocart-coverage-reports';
3
- import { coverageOptions } from '../../mrc.playwright.config';
1
+ import type { FullConfig } from "@playwright/test";
2
+ import { CoverageReport } from "monocart-coverage-reports";
3
+ import { coverageOptions } from "../../../mrc.playwright.config";
4
4
 
5
5
  const globalTeardown = async (config: FullConfig) => {
6
6
  if (config.webServer && coverageOptions.enabled) {
@@ -1,19 +1,19 @@
1
- import { App } from '@App/App';
2
- import { waitFor } from '@testing-library/react';
3
- import { StrictMode } from 'react';
4
- import { createRoot } from 'react-dom/client';
5
- import { afterEach, beforeEach, describe, expect, it, type Mock, vi } from 'vitest';
6
- import AppHTMLElement from '../AppHTMLElement';
1
+ import { App } from "@App/App";
2
+ import AppHTMLElement from "@App/AppHTMLElement";
3
+ import { waitFor } from "@testing-library/react";
4
+ import { StrictMode } from "react";
5
+ import { createRoot } from "react-dom/client";
6
+ import { afterEach, beforeEach, describe, expect, it, type Mock, vi } from "vitest";
7
7
 
8
- vi.mock('@App/App', () => ({
8
+ vi.mock("@App/App", () => ({
9
9
  App: () => <div data-testid="app-mock">AppMock</div>,
10
10
  }));
11
11
 
12
- vi.mock('react-dom/client', () => ({
12
+ vi.mock("react-dom/client", () => ({
13
13
  createRoot: vi.fn(),
14
14
  }));
15
15
 
16
- describe('AppHTMLElement', () => {
16
+ describe("AppHTMLElement", () => {
17
17
  let container: HTMLElement;
18
18
  const render = vi.fn();
19
19
  const unmount = vi.fn();
@@ -22,17 +22,17 @@ describe('AppHTMLElement', () => {
22
22
  unmount,
23
23
  }));
24
24
 
25
- customElements.define('bootstrap-html-element', AppHTMLElement);
25
+ customElements.define("bootstrap-html-element", AppHTMLElement);
26
26
 
27
27
  beforeEach(() => {
28
- container = document.createElement('bootstrap-html-element');
28
+ container = document.createElement("bootstrap-html-element");
29
29
  });
30
30
 
31
31
  afterEach(() => {
32
32
  container.remove();
33
33
  });
34
34
 
35
- it('should mount the React component in the custom element', () => {
35
+ it("should mount the React component in the custom element", () => {
36
36
  document.body.appendChild(container);
37
37
 
38
38
  expect(createRoot as Mock).toHaveBeenCalledWith(expect.anything());
@@ -44,7 +44,7 @@ describe('AppHTMLElement', () => {
44
44
  expect(unmount).not.toHaveBeenCalled();
45
45
  });
46
46
 
47
- it('should unmount the React component when removed from the DOM', async () => {
47
+ it("should unmount the React component when removed from the DOM", async () => {
48
48
  document.body.appendChild(container);
49
49
 
50
50
  expect(unmount).not.toHaveBeenCalled();
@@ -56,7 +56,7 @@ describe('AppHTMLElement', () => {
56
56
  });
57
57
  });
58
58
 
59
- it('should not unmount when element is removed and re-added to the DOM', async () => {
59
+ it("should not unmount when element is removed and re-added to the DOM", async () => {
60
60
  document.body.appendChild(container);
61
61
  container.remove();
62
62
  document.body.appendChild(container);
@@ -0,0 +1,15 @@
1
+ import { DemoFooter } from "@Demo/ui/components/DemoFooter";
2
+ import { render } from "@testing-library/react";
3
+ import { BrowserRouter as Router } from "react-router";
4
+
5
+ describe("Footer Component", () => {
6
+ it("should render the Footer component correctly", () => {
7
+ const { container } = render(
8
+ <Router>
9
+ <DemoFooter />
10
+ </Router>,
11
+ );
12
+
13
+ expect(container).toMatchSnapshot();
14
+ });
15
+ });
@@ -0,0 +1,15 @@
1
+ import { DemoHeader } from "@Demo/ui/components/DemoHeader";
2
+ import { render } from "@testing-library/react";
3
+ import { BrowserRouter as Router } from "react-router";
4
+
5
+ describe("Header Component", () => {
6
+ it("should render the Header component correctly", () => {
7
+ const { container } = render(
8
+ <Router>
9
+ <DemoHeader />
10
+ </Router>,
11
+ );
12
+
13
+ expect(container).toMatchSnapshot();
14
+ });
15
+ });
@@ -0,0 +1,12 @@
1
+ import { Logo } from "@Demo/ui/components/Logo";
2
+ import { render } from "@testing-library/react";
3
+ import { expect } from "vitest";
4
+ import { axe } from "vitest-axe";
5
+
6
+ describe("<Logo />", () => {
7
+ it("should", async () => {
8
+ const { container } = render(<Logo src="foo" alt="bar" />);
9
+
10
+ expect(await axe(container)).toHaveNoViolations();
11
+ });
12
+ });
package/tsconfig.json CHANGED
@@ -29,6 +29,6 @@
29
29
  "@Mocks/*": ["./mocks/*"]
30
30
  }
31
31
  },
32
- "include": ["src", "mocks", "vitest.setup.ts", "rsbuild.config.ts"],
32
+ "include": ["src", "tests", "mocks", "vitest.setup.ts", "rsbuild.config.ts"],
33
33
  "exclude": ["node_modules"]
34
34
  }
package/vitest.config.mts CHANGED
@@ -28,7 +28,7 @@ export default defineConfig(({ mode }) => {
28
28
  'vitest-sonar-reporter': 'sonar-report.xml',
29
29
  junit: 'junit-report.xml',
30
30
  },
31
- include: ['src/**/*.(spec|test|steps).[jt]s?(x)'],
31
+ include: ['tests/unit/**/*.(spec|test|steps).[jt]s?(x)'],
32
32
  maxWorkers: env.CI ? 2 : undefined,
33
33
  coverage: {
34
34
  enabled: env.CI === 'true',
@@ -1,5 +0,0 @@
1
- import defaultConfig from '@pplancq/postcss-config';
2
-
3
- export default {
4
- ...defaultConfig,
5
- };
@@ -1,15 +0,0 @@
1
- import { render } from '@testing-library/react';
2
- import { BrowserRouter as Router } from 'react-router';
3
- import { DemoFooter } from '../DemoFooter';
4
-
5
- describe('Footer Component', () => {
6
- it('should render the Footer component correctly', () => {
7
- const { container } = render(
8
- <Router>
9
- <DemoFooter />
10
- </Router>,
11
- );
12
-
13
- expect(container).toMatchSnapshot();
14
- });
15
- });
@@ -1,15 +0,0 @@
1
- import { render } from '@testing-library/react';
2
- import { BrowserRouter as Router } from 'react-router';
3
- import { DemoHeader } from '../DemoHeader';
4
-
5
- describe('Header Component', () => {
6
- it('should render the Header component correctly', () => {
7
- const { container } = render(
8
- <Router>
9
- <DemoHeader />
10
- </Router>,
11
- );
12
-
13
- expect(container).toMatchSnapshot();
14
- });
15
- });
@@ -1,12 +0,0 @@
1
- import { render } from '@testing-library/react';
2
- import { expect } from 'vitest';
3
- import { axe } from 'vitest-axe';
4
- import { Logo } from '../Logo';
5
-
6
- describe('<Logo />', () => {
7
- it('should', async () => {
8
- const { container } = render(<Logo src="foo" alt="bar" />);
9
-
10
- expect(await axe(container)).toHaveNoViolations();
11
- });
12
- });