From 2885baa72d99eaa5a95d4e257c4e4edb5aadb7c1 Mon Sep 17 00:00:00 2001 From: jonulak Date: Thu, 9 Jan 2025 19:40:23 -0500 Subject: [PATCH 1/5] Add projects & github tests --- __tests__/lib/github.tests.tsx | 185 ++++++++++ __tests__/pages/projects.tests.tsx | 236 ++++++++++++ jest.config.ts | 215 +++++++++++ jest.setup.ts | 1 + package.json | 9 +- src/lib/git-api-client.ts | 9 + src/lib/github.ts | 16 +- src/pages/projects.tsx | 16 +- src/utils/types.ts | 1 + tests-examples/demo-todo-app.spec.ts | 428 ---------------------- tests/example.spec.ts | 18 - tsconfig.build.json | 8 + tsconfig.json | 5 +- yarn.lock | 527 ++++++++++++++++++++++++++- 14 files changed, 1189 insertions(+), 485 deletions(-) create mode 100644 __tests__/lib/github.tests.tsx create mode 100644 __tests__/pages/projects.tests.tsx create mode 100644 jest.config.ts create mode 100644 jest.setup.ts create mode 100644 src/lib/git-api-client.ts delete mode 100644 tests-examples/demo-todo-app.spec.ts delete mode 100644 tests/example.spec.ts create mode 100644 tsconfig.build.json diff --git a/__tests__/lib/github.tests.tsx b/__tests__/lib/github.tests.tsx new file mode 100644 index 00000000..5f95af34 --- /dev/null +++ b/__tests__/lib/github.tests.tsx @@ -0,0 +1,185 @@ +import { getProjectContributors, getGithubRepo, getGithubRepoContributors } from "lib/github"; +import { GithubContributor, GithubUser, GithubRepo } from "@utils/types"; +import { gitAPI } from "lib/git-api-client"; + +jest.mock("@/lib/git-api-client", () => ({ + gitAPI: { + get: jest.fn(), + }, +})); + +describe("GitHub API Functions", () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe("getProjectContributors", () => { + const mockContributors: GithubContributor[] = [ + { + login: "user1", + contributions: 100, + }, + { + login: "user2", + contributions: 50, + }, + ]; + + const mockUsers: GithubUser[] = [ + { + login: "user1", + name: "User One", + html_url: "", + avatar_url: "", + }, + { + login: "user2", + name: "User Two", + html_url: "", + avatar_url: "", + }, + ]; + + it("should return formatted contributor data", async () => { + // Mock contributors endpoint + (gitAPI.get as jest.Mock) + .mockResolvedValueOnce({ status: 200, data: mockContributors }) + // Mock individual user endpoints + .mockResolvedValueOnce({ status: 200, data: mockUsers[0] }) + .mockResolvedValueOnce({ status: 200, data: mockUsers[1] }); + + const result = await getProjectContributors("owner", "repo", 2); + + expect(result).toHaveLength(2); + expect(result[0]).toEqual( + expect.objectContaining({ + ...mockContributors[0], + ...mockUsers[0], + }) + ); + expect(gitAPI.get).toHaveBeenCalledWith("/repos/owner/repo/contributors"); + expect(gitAPI.get).toHaveBeenCalledWith("/users/user1"); + expect(gitAPI.get).toHaveBeenCalledWith("/users/user2"); + }); + + it("should handle contributor fetch error", async () => { + (gitAPI.get as jest.Mock).mockResolvedValueOnce({ + status: 404, + error: "Not Found", + }); + + await expect(getProjectContributors("owner", "repo")).rejects.toThrow( + "Error fetching contributor data for owner/repo" + ); + }); + + it("should handle user fetch error", async () => { + (gitAPI.get as jest.Mock) + .mockResolvedValueOnce({ status: 200, data: mockContributors }) + .mockResolvedValueOnce({ status: 404, error: "User not found" }); + + await expect(getProjectContributors("owner", "repo")).rejects.toThrow( + "Error fetching user data for user1" + ); + }); + }); + + describe("getGithubRepo", () => { + const mockRepo: GithubRepo = { + html_url: "", + stargazers_count: 100, + open_issues_count: 15, + forks_count: 40, + subscribers_count: 300, + }; + + it("should return repository data", async () => { + (gitAPI.get as jest.Mock).mockResolvedValueOnce({ + status: 200, + data: mockRepo, + }); + + const result = await getGithubRepo("owner", "repo"); + + expect(result).toEqual(mockRepo); + expect(gitAPI.get).toHaveBeenCalledWith("/repos/owner/repo"); + }); + + it("should handle error response", async () => { + (gitAPI.get as jest.Mock).mockResolvedValueOnce({ + status: 404, + error: "Repository not found", + }); + + await expect(getGithubRepo("owner", "repo")).rejects.toThrow( + "Error fetching repo data for owner/repo" + ); + }); + + it("should handle error response without error message", async () => { + (gitAPI.get as jest.Mock).mockResolvedValueOnce({ status: 500 }); + + await expect(getGithubRepo("owner", "repo")).rejects.toThrow( + "Error fetching repo data for owner/repo\nStatus code: 500" + ); + }); + }); + + describe("getGithubRepoContributors", () => { + const mockContributors: GithubContributor[] = [ + { + login: "user1", + contributions: 100, + }, + { + login: "user2", + contributions: 50, + }, + { + login: "user3", + contributions: 25, + }, + ]; + + it("should return contributor list with specified limit", async () => { + (gitAPI.get as jest.Mock).mockResolvedValueOnce({ + status: 200, + data: mockContributors, + }); + + const result = await getGithubRepoContributors("owner", "repo", 2); + + expect(result).toHaveLength(2); + expect(result[0]).toEqual( + expect.objectContaining({ + login: "user1", + contributions: 100, + }) + ); + expect(gitAPI.get).toHaveBeenCalledWith("/repos/owner/repo/contributors"); + }); + + it("should use default limit of 4", async () => { + (gitAPI.get as jest.Mock).mockResolvedValueOnce({ + status: 200, + data: mockContributors, + }); + + const result = await getGithubRepoContributors("owner", "repo"); + + expect(result).toHaveLength(3); // Only 3 mock contributors available + expect(gitAPI.get).toHaveBeenCalledWith("/repos/owner/repo/contributors"); + }); + + it("should handle error response", async () => { + (gitAPI.get as jest.Mock).mockResolvedValueOnce({ + status: 404, + error: "Not Found", + }); + + await expect(getGithubRepoContributors("owner", "repo")).rejects.toThrow( + "Error fetching contributor data for owner/repo" + ); + }); + }); +}); diff --git a/__tests__/pages/projects.tests.tsx b/__tests__/pages/projects.tests.tsx new file mode 100644 index 00000000..f4f60ce4 --- /dev/null +++ b/__tests__/pages/projects.tests.tsx @@ -0,0 +1,236 @@ +import { render, screen, fireEvent } from "@testing-library/react"; +import { VWCProject, VWCContributor, VWCProjectRepo } from "@utils/types"; +import Projects from "pages/projects"; +import { + TechStack, + LinkButtons, + RepoStats, + TopContributors, + ProjectDetailModal, + ProjectCard, +} from "pages/projects"; +import { getProjectData } from "lib/project"; +import { waitFor } from "@testing-library/react"; + +// Mock dependencies +jest.mock("@components/seo/page-seo", () => ({ + __esModule: true, + default: () =>
, +})); + +jest.mock("@layout/layout-01", () => ({ + __esModule: true, + default: ({ children }) =>
{children}
, +})); + +jest.mock("@components/breadcrumb", () => ({ + __esModule: true, + default: () =>
, +})); + +jest.mock("@components/vwc-grid", () => ({ + VWCGrid: ({ children }) =>
{children}
, +})); + +jest.mock("@components/markdown-renderer", () => ({ + __esModule: true, + default: ({ content }) =>
{content}
, +})); + +// Mock the AnimatePresence component +jest.mock("motion/react", () => ({ + AnimatePresence: ({ children }) =>
{children}
, + motion: { + div: ({ children }) =>
{children}
, + }, +})); + +jest.mock("@/lib/project", () => ({ + getProjectData: jest.fn(), +})); + +// Mock data +const mockContributor: VWCContributor = { + login: "testuser", + name: "Test User", + avatar_url: "https://example.com/avatar.jpg", + html_url: "https://github.com/testuser", + contributions: 10, + id: 1, + node_id: "node1", + type: "User", + url: "https://api.github.com/users/testuser", +}; + +const mockRepo: VWCProjectRepo = { + html_url: "", + stargazers_count: 100, + forks_count: 20, + open_issues_count: 5, + subscribers_count: 15, + contributors: [mockContributor], +}; + +const mockProject: VWCProject = { + details: { + index: 0, + name: "Test Project", + headline: "A test project", + owner: "testowner", + repo: "test-repo", + technologies: ["React", "TypeScript"], + thumbnail: { + src: "https://example.com/thumbnail.jpg", + alt: "Test thumbnail", + }, + live_url: "https://example.com", + long_description: ["Test description"], + }, + repo: mockRepo, +}; + +describe("TechStack Component", () => { + it("renders all technologies", () => { + const technologies = ["React", "TypeScript", "Node.js"]; + render(); + + technologies.forEach((tech) => { + expect(screen.getByText(tech)).toBeInTheDocument(); + }); + }); +}); + +describe("LinkButtons Component", () => { + it("renders GitHub link", () => { + const url = "https://github.com/test"; + render(); + const ghLink = screen.getByText("GitHub").closest("a"); + expect(ghLink).toHaveAttribute("href", url); + }); + + it("renders both GitHub and Live links when live_url is provided", () => { + const ghURL = "https://github.com/test"; + const liveURL = "https://test.com"; + render(); + const ghLink = screen.getByText("GitHub").closest("a"); + expect(ghLink).toHaveAttribute("href", ghURL); + const liveLink = screen.getByText("Live").closest("a"); + expect(liveLink).toHaveAttribute("href", liveURL); + }); +}); + +describe("RepoStats Component", () => { + it("renders repository statistics", () => { + render(); + + expect(screen.getByText("100")).toBeInTheDocument(); // Stars + expect(screen.getByText("5")).toBeInTheDocument(); // Issues + expect(screen.getByText("15")).toBeInTheDocument(); // Watching + expect(screen.getByText("20")).toBeInTheDocument(); // Forks + }); +}); + +describe("TopContributors Component", () => { + it("renders contributor information", () => { + render(); + + expect(screen.getByText("Test User")).toBeInTheDocument(); + expect(screen.getByText("@testuser")).toBeInTheDocument(); + expect(screen.getByAltText("Test User")).toHaveAttribute( + "src", + "https://example.com/avatar.jpg" + ); + }); +}); + +describe("ProjectDetailModal Component", () => { + it("renders project details", () => { + render(); + + expect(screen.getByText("Test Project")).toBeInTheDocument(); + expect(screen.getByText("A test project")).toBeInTheDocument(); + expect(screen.getByAltText("Test thumbnail")).toBeInTheDocument(); + }); + + it("renders markdown content", () => { + render(); + expect(screen.getByTestId("markdown")).toHaveTextContent("Test description"); + }); +}); + +describe("ProjectCard Component", () => { + it("opens modal on click", async () => { + render(); + + // Click the project card to open modal + fireEvent.click(screen.getByText("Test Project")); + + // Verify modal content is visible + await waitFor(() => { + expect(screen.getByText(mockProject.details.technologies[0])).toBeInTheDocument(); + }); + }); + + it("closes modal when clicking close button", () => { + render(); + + // Open the modal + fireEvent.click(screen.getByText("Test Project")); + + // Click the close button + fireEvent.click(screen.getByTestId("close-button")); + + // Verify modal is closed + // Note: We might need to use waitFor here if there are animations + expect(screen.queryByRole("dialog")).not.toBeInTheDocument(); + }); +}); + +describe("Projects Page", () => { + it("renders projects list", () => { + render(); + + expect(screen.getByTestId("seo")).toBeInTheDocument(); + expect(screen.getByTestId("breadcrumb")).toBeInTheDocument(); + expect(screen.getByTestId("vwc-grid")).toBeInTheDocument(); + expect(screen.getByText("Test Project")).toBeInTheDocument(); + }); + + it("renders description text", () => { + render(); + + expect( + screen.getByText(/Welcome to the Vets Who Code project showcase/) + ).toBeInTheDocument(); + expect(screen.getByText(/Here, you'll find innovative applications/)).toBeInTheDocument(); + expect(screen.getByText(/Explore their work and discover/)).toBeInTheDocument(); + }); +}); + +describe("getStaticProps", () => { + it("returns project data and layout settings", async () => { + (getProjectData as jest.Mock).mockResolvedValue([mockProject]); + + const { getStaticProps } = require("@/pages/projects"); + const result = await getStaticProps(); + + expect(result).toEqual({ + props: { + projects: [mockProject], + layout: { + headerShadow: true, + headerFluid: false, + footerMode: "light", + }, + }, + revalidate: 600, + }); + }); + + it("handles errors appropriately", async () => { + (getProjectData as jest.Mock).mockRejectedValue(new Error("API Error")); + + const { getStaticProps } = require("@/pages/projects"); + await expect(getStaticProps()).rejects.toThrow("Failed to update github project data"); + }); +}); diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 00000000..93ef20ba --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,215 @@ +import type { Config } from "jest"; +import nextJest from "next/jest.js"; + +const createJestConfig = nextJest({ + // Provide the path to your Next.js app to load next.config.js and .env files in your test environment + dir: "./", +}); + +const config: Config = { + // All imported modules in your tests should be mocked automatically + // automock: false, + + // Stop running tests after `n` failures + // bail: 0, + + // The directory where Jest should store its cached dependency information + // cacheDirectory: "/private/var/folders/cg/0g1n2b393jgg29vq5dm5x_dr0000gn/T/jest_dx", + + // Automatically clear mock calls, instances, contexts and results before every test + clearMocks: true, + + // Indicates whether the coverage information should be collected while executing the test + collectCoverage: true, + + // An array of glob patterns indicating a set of files for which coverage information should be collected + // collectCoverageFrom: undefined, + + // The directory where Jest should output its coverage files + coverageDirectory: "coverage", + + // An array of regexp pattern strings used to skip coverage collection + // coveragePathIgnorePatterns: [ + // "/node_modules/" + // ], + + // Indicates which provider should be used to instrument code for coverage + coverageProvider: "v8", + + // A list of reporter names that Jest uses when writing coverage reports + // coverageReporters: [ + // "json", + // "text", + // "lcov", + // "clover" + // ], + + // An object that configures minimum threshold enforcement for coverage results + // coverageThreshold: undefined, + + // A path to a custom dependency extractor + // dependencyExtractor: undefined, + + // Make calling deprecated APIs throw helpful error messages + // errorOnDeprecated: false, + + // The default configuration for fake timers + // fakeTimers: { + // "enableGlobally": false + // }, + + // Force coverage collection from ignored files using an array of glob patterns + // forceCoverageMatch: [], + + // A path to a module which exports an async function that is triggered once before all test suites + // globalSetup: undefined, + + // A path to a module which exports an async function that is triggered once after all test suites + // globalTeardown: undefined, + + // A set of global variables that need to be available in all test environments + // globals: {}, + + // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. + // maxWorkers: "50%", + + // An array of directory names to be searched recursively up from the requiring module's location + // moduleDirectories: [ + // "node_modules" + // ], + + // An array of file extensions your modules use + // moduleFileExtensions: [ + // "js", + // "mjs", + // "cjs", + // "jsx", + // "ts", + // "tsx", + // "json", + // "node" + // ], + + // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module + moduleNameMapper: { + "^@assets/(.*)$": "/src/assets/$1", + "^@components/(.*)$": "/src/components/$1", + "^@containers/(.*)$": "/src/containers/$1", + "^@contexts/(.*)$": "/src/contexts/$1", + "^@data/(.*)$": "/src/data/$1", + "^@hooks$": "/src/hooks", + "^@layout/(.*)$": "/src/layouts/$1", + "^@ui/(.*)$": "/src/components/ui/$1", + "^@utils/(.*)$": "/src/utils/$1", + "^@widgets/(.*)$": "/src/components/widgets/$1", + "^@fonts/(.*)$": "/src/public/fonts/$1", + "^@vercel/analytics/(.*)$": "/src/node_modules/@vercel/analytics/$1", + "^@/(.*)$": "/src/$1", + }, + + // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader + // modulePathIgnorePatterns: [], + + // Activates notifications for test results + // notify: false, + + // An enum that specifies notification mode. Requires { notify: true } + // notifyMode: "failure-change", + + // A preset that is used as a base for Jest's configuration + // preset: undefined, + + // Run tests from one or more projects + // projects: undefined, + + // Use this configuration option to add custom reporters to Jest + // reporters: undefined, + + // Automatically reset mock state before every test + // resetMocks: false, + + // Reset the module registry before running each individual test + // resetModules: false, + + // A path to a custom resolver + // resolver: undefined, + + // Automatically restore mock state and implementation before every test + // restoreMocks: false, + + // The root directory that Jest should scan for tests and modules within + // rootDir: undefined, + + // A list of paths to directories that Jest should use to search for files in + // roots: [ + // "" + // ], + + // Allows you to use a custom runner instead of Jest's default test runner + // runner: "jest-runner", + + // The paths to modules that run some code to configure or set up the testing environment before each test + // setupFiles: [], + + // A list of paths to modules that run some code to configure or set up the testing framework before each test + setupFilesAfterEnv: ["/jest.setup.ts"], + + // The number of seconds after which a test is considered as slow and reported as such in the results. + // slowTestThreshold: 5, + + // A list of paths to snapshot serializer modules Jest should use for snapshot testing + // snapshotSerializers: [], + + // The test environment that will be used for testing + testEnvironment: "jsdom", + + // Options that will be passed to the testEnvironment + // testEnvironmentOptions: {}, + + // Adds a location field to test results + // testLocationInResults: false, + + // The glob patterns Jest uses to detect test files + // testMatch: [ + // "**/__tests__/**/*.[jt]s?(x)", + // "**/?(*.)+(spec|test).[tj]s?(x)" + // ], + + // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped + // testPathIgnorePatterns: [ + // "/node_modules/" + // ], + + // The regexp pattern or array of patterns that Jest uses to detect test files + // testRegex: [], + + // This option allows the use of a custom results processor + // testResultsProcessor: undefined, + + // This option allows use of a custom test runner + // testRunner: "jest-circus/runner", + + // A map from regular expressions to paths to transformers + // transform: undefined, + + // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation + // transformIgnorePatterns: [ + // "/node_modules/", + // "\\.pnp\\.[^\\/]+$" + // ], + + // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them + // unmockedModulePathPatterns: undefined, + + // Indicates whether each individual test should be reported during the run + // verbose: undefined, + + // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode + // watchPathIgnorePatterns: [], + + // Whether to use watchman for file crawling + // watchman: true, +}; + +// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async +export default createJestConfig(config); diff --git a/jest.setup.ts b/jest.setup.ts new file mode 100644 index 00000000..d0de870d --- /dev/null +++ b/jest.setup.ts @@ -0,0 +1 @@ +import "@testing-library/jest-dom"; diff --git a/package.json b/package.json index 91f69146..2b814b22 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "lint": "next lint", "lint:fix": "yarn typecheck & yarn format & yarn lint --fix", "prepare": "husky install", - "postbuild": "next-sitemap" + "postbuild": "next-sitemap", + "test": "jest" }, "dependencies": { "@ai-sdk/azure": "^1.0.7", @@ -60,6 +61,9 @@ "@fullhuman/postcss-purgecss": "^4.1.3", "@svgr/webpack": "^8.1.0", "@tailwindcss/typography": "^0.5.2", + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/react": "^16.1.0", "@types/cookie": "^0.5.1", "@types/google.maps": "^3.58.1", "@types/jest": "^29.5.14", @@ -73,6 +77,7 @@ "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", "autoprefixer": "^10.4.4", + "axios-mock-adapter": "^2.1.0", "eslint": "^8.45.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb-typescript": "^17.0.0", @@ -85,6 +90,7 @@ "eslint-plugin-react": "^7.29.4", "husky": "^7.0.4", "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", "lint-staged": "^12.3.7", "postcss": "^8.4.12", "prettier": "^3.4.2", @@ -92,6 +98,7 @@ "rimraf": "^3.0.2", "tailwindcss": "^3.0.23", "ts-jest": "^29.2.5", + "ts-node": "^10.9.2", "typescript": "^5.6.3" }, "lint-staged": { diff --git a/src/lib/git-api-client.ts b/src/lib/git-api-client.ts new file mode 100644 index 00000000..9aba1e12 --- /dev/null +++ b/src/lib/git-api-client.ts @@ -0,0 +1,9 @@ +import axios from "axios"; + +const token = process.env.GITHUB_TOKEN || ""; +export const gitAPI = axios.create({ + baseURL: "https://api.github.com", + headers: { + Authorization: `Bearer ${token}`, + }, +}); diff --git a/src/lib/github.ts b/src/lib/github.ts index c6729a77..f0097320 100644 --- a/src/lib/github.ts +++ b/src/lib/github.ts @@ -1,13 +1,5 @@ import { VWCContributor, GithubRepo, GithubContributor, GithubUser } from "@utils/types"; -import axios from "axios"; - -const token = process.env.GITHUB_TOKEN || ""; -const git_api = axios.create({ - baseURL: "https://api.github.com", - headers: { - Authorization: `Bearer ${token}`, - }, -}); +import { gitAPI } from "./git-api-client"; export const getProjectContributors = async ( owner: string, @@ -17,7 +9,7 @@ export const getProjectContributors = async ( const topContributors = await getGithubRepoContributors(owner, repo, top); const projectContributors = Promise.all( topContributors.map(async (contributor) => { - const response = await git_api.get(`/users/${contributor.login}`); + const response = await gitAPI.get(`/users/${contributor.login}`); if (response.status == 200) { const user = response.data as GithubUser; return { @@ -40,7 +32,7 @@ export const getProjectContributors = async ( }; export const getGithubRepo = async (owner: string, repo: string): Promise => { - const response = await git_api.get(`/repos/${owner}/${repo}`); + const response = await gitAPI.get(`/repos/${owner}/${repo}`); if (response.status == 200) { return response.data as GithubRepo; } else { @@ -60,7 +52,7 @@ export const getGithubRepoContributors = async ( repo: string, top: number = 4 ): Promise => { - const response = await git_api.get(`/repos/${owner}/${repo}/contributors`); + const response = await gitAPI.get(`/repos/${owner}/${repo}/contributors`); if (response.status == 200) { return (response.data as GithubContributor[]).slice(0, top); } else { diff --git a/src/pages/projects.tsx b/src/pages/projects.tsx index 875e3ed0..5fcf2725 100644 --- a/src/pages/projects.tsx +++ b/src/pages/projects.tsx @@ -19,7 +19,7 @@ interface TechStackProps { techStack: string[]; } -const TechStack = ({ techStack }: TechStackProps) => { +export const TechStack = ({ techStack }: TechStackProps) => { return (
{techStack.map((tech) => ( @@ -36,7 +36,7 @@ interface LinkButtonsProps { live_url?: string; } -const LinkButtons = ({ github_url, live_url }: LinkButtonsProps) => { +export const LinkButtons = ({ github_url, live_url }: LinkButtonsProps) => { return ( <>
@@ -73,7 +73,7 @@ interface RepoStatsProps { repo: VWCProjectRepo; } -const RepoStats = ({ repo }: RepoStatsProps) => { +export const RepoStats = ({ repo }: RepoStatsProps) => { return ( <> {/* Repo stats */} @@ -128,7 +128,7 @@ interface TopContributorsProps { contributors: VWCContributor[]; } -const TopContributors = ({ contributors }: TopContributorsProps) => { +export const TopContributors = ({ contributors }: TopContributorsProps) => { return ( <>
Top Contributors
@@ -166,7 +166,7 @@ interface ProjectModalProps { className?: string; } -const ProjectDetailModal = ({ project, className }: ProjectModalProps) => { +export const ProjectDetailModal = ({ project, className }: ProjectModalProps) => { const duration = 0.35; const xOffset = 25; const delay = 0.1; @@ -240,7 +240,7 @@ interface ProjectCardProps { project: VWCProject; } -const ProjectCard = ({ project }: ProjectCardProps) => { +export const ProjectCard = ({ project }: ProjectCardProps) => { const [isOpen, setIsOpen] = useState(false); return ( @@ -289,7 +289,7 @@ const ProjectCard = ({ project }: ProjectCardProps) => { transition={{ bounce: false, duration: 0.3 }} > - + @@ -309,7 +309,7 @@ type PageProps = NextPage & { Layout: typeof Layout01; }; -const Projects: PageProps = ({ projects }: TProps) => { +export const Projects: PageProps = ({ projects }: TProps) => { const description = [ "Welcome to the Vets Who Code project showcase—a space dedicated to highlighting the exceptional work of our veteran developers.", "Here, you'll find innovative applications, tools, and solutions created by our talented community, demonstrating their technical expertise and commitment to excellence. Each project reflects the dedication, creativity, and skills that veterans bring to the tech industry.", diff --git a/src/utils/types.ts b/src/utils/types.ts index 0ad04268..d4458575 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -190,6 +190,7 @@ export interface VWCProject { } export interface GithubUser { + login: string; name: string; avatar_url: string; html_url: string; diff --git a/tests-examples/demo-todo-app.spec.ts b/tests-examples/demo-todo-app.spec.ts deleted file mode 100644 index 82710fdf..00000000 --- a/tests-examples/demo-todo-app.spec.ts +++ /dev/null @@ -1,428 +0,0 @@ -import { test, expect, type Page } from "@playwright/test"; - -test.beforeEach(async ({ page }) => { - await page.goto("https://demo.playwright.dev/todomvc"); -}); - -const TODO_ITEMS = ["buy some cheese", "feed the cat", "book a doctors appointment"]; - -test.describe("New Todo", () => { - test("should allow me to add todo items", async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder("What needs to be done?"); - - // Create 1st todo. - await newTodo.fill(TODO_ITEMS[0]); - await newTodo.press("Enter"); - - // Make sure the list only has one todo item. - await expect(page.getByTestId("todo-title")).toHaveText([TODO_ITEMS[0]]); - - // Create 2nd todo. - await newTodo.fill(TODO_ITEMS[1]); - await newTodo.press("Enter"); - - // Make sure the list now has two todo items. - await expect(page.getByTestId("todo-title")).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]); - - await checkNumberOfTodosInLocalStorage(page, 2); - }); - - test("should clear text input field when an item is added", async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder("What needs to be done?"); - - // Create one todo item. - await newTodo.fill(TODO_ITEMS[0]); - await newTodo.press("Enter"); - - // Check that input is empty. - await expect(newTodo).toBeEmpty(); - await checkNumberOfTodosInLocalStorage(page, 1); - }); - - test("should append new items to the bottom of the list", async ({ page }) => { - // Create 3 items. - await createDefaultTodos(page); - - // create a todo count locator - const todoCount = page.getByTestId("todo-count"); - - // Check test using different methods. - await expect(page.getByText("3 items left")).toBeVisible(); - await expect(todoCount).toHaveText("3 items left"); - await expect(todoCount).toContainText("3"); - await expect(todoCount).toHaveText(/3/); - - // Check all items in one call. - await expect(page.getByTestId("todo-title")).toHaveText(TODO_ITEMS); - await checkNumberOfTodosInLocalStorage(page, 3); - }); -}); - -test.describe("Mark all as completed", () => { - test.beforeEach(async ({ page }) => { - await createDefaultTodos(page); - await checkNumberOfTodosInLocalStorage(page, 3); - }); - - test.afterEach(async ({ page }) => { - await checkNumberOfTodosInLocalStorage(page, 3); - }); - - test("should allow me to mark all items as completed", async ({ page }) => { - // Complete all todos. - await page.getByLabel("Mark all as complete").check(); - - // Ensure all todos have 'completed' class. - await expect(page.getByTestId("todo-item")).toHaveClass([ - "completed", - "completed", - "completed", - ]); - await checkNumberOfCompletedTodosInLocalStorage(page, 3); - }); - - test("should allow me to clear the complete state of all items", async ({ page }) => { - const toggleAll = page.getByLabel("Mark all as complete"); - // Check and then immediately uncheck. - await toggleAll.check(); - await toggleAll.uncheck(); - - // Should be no completed classes. - await expect(page.getByTestId("todo-item")).toHaveClass(["", "", ""]); - }); - - test("complete all checkbox should update state when items are completed / cleared", async ({ - page, - }) => { - const toggleAll = page.getByLabel("Mark all as complete"); - await toggleAll.check(); - await expect(toggleAll).toBeChecked(); - await checkNumberOfCompletedTodosInLocalStorage(page, 3); - - // Uncheck first todo. - const firstTodo = page.getByTestId("todo-item").nth(0); - await firstTodo.getByRole("checkbox").uncheck(); - - // Reuse toggleAll locator and make sure its not checked. - await expect(toggleAll).not.toBeChecked(); - - await firstTodo.getByRole("checkbox").check(); - await checkNumberOfCompletedTodosInLocalStorage(page, 3); - - // Assert the toggle all is checked again. - await expect(toggleAll).toBeChecked(); - }); -}); - -test.describe("Item", () => { - test("should allow me to mark items as complete", async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder("What needs to be done?"); - - // Create two items. - for (const item of TODO_ITEMS.slice(0, 2)) { - await newTodo.fill(item); - await newTodo.press("Enter"); - } - - // Check first item. - const firstTodo = page.getByTestId("todo-item").nth(0); - await firstTodo.getByRole("checkbox").check(); - await expect(firstTodo).toHaveClass("completed"); - - // Check second item. - const secondTodo = page.getByTestId("todo-item").nth(1); - await expect(secondTodo).not.toHaveClass("completed"); - await secondTodo.getByRole("checkbox").check(); - - // Assert completed class. - await expect(firstTodo).toHaveClass("completed"); - await expect(secondTodo).toHaveClass("completed"); - }); - - test("should allow me to un-mark items as complete", async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder("What needs to be done?"); - - // Create two items. - for (const item of TODO_ITEMS.slice(0, 2)) { - await newTodo.fill(item); - await newTodo.press("Enter"); - } - - const firstTodo = page.getByTestId("todo-item").nth(0); - const secondTodo = page.getByTestId("todo-item").nth(1); - const firstTodoCheckbox = firstTodo.getByRole("checkbox"); - - await firstTodoCheckbox.check(); - await expect(firstTodo).toHaveClass("completed"); - await expect(secondTodo).not.toHaveClass("completed"); - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - - await firstTodoCheckbox.uncheck(); - await expect(firstTodo).not.toHaveClass("completed"); - await expect(secondTodo).not.toHaveClass("completed"); - await checkNumberOfCompletedTodosInLocalStorage(page, 0); - }); - - test("should allow me to edit an item", async ({ page }) => { - await createDefaultTodos(page); - - const todoItems = page.getByTestId("todo-item"); - const secondTodo = todoItems.nth(1); - await secondTodo.dblclick(); - await expect(secondTodo.getByRole("textbox", { name: "Edit" })).toHaveValue(TODO_ITEMS[1]); - await secondTodo.getByRole("textbox", { name: "Edit" }).fill("buy some sausages"); - await secondTodo.getByRole("textbox", { name: "Edit" }).press("Enter"); - - // Explicitly assert the new text value. - await expect(todoItems).toHaveText([TODO_ITEMS[0], "buy some sausages", TODO_ITEMS[2]]); - await checkTodosInLocalStorage(page, "buy some sausages"); - }); -}); - -test.describe("Editing", () => { - test.beforeEach(async ({ page }) => { - await createDefaultTodos(page); - await checkNumberOfTodosInLocalStorage(page, 3); - }); - - test("should hide other controls when editing", async ({ page }) => { - const todoItem = page.getByTestId("todo-item").nth(1); - await todoItem.dblclick(); - await expect(todoItem.getByRole("checkbox")).not.toBeVisible(); - await expect( - todoItem.locator("label", { - hasText: TODO_ITEMS[1], - }) - ).not.toBeVisible(); - await checkNumberOfTodosInLocalStorage(page, 3); - }); - - test("should save edits on blur", async ({ page }) => { - const todoItems = page.getByTestId("todo-item"); - await todoItems.nth(1).dblclick(); - await todoItems.nth(1).getByRole("textbox", { name: "Edit" }).fill("buy some sausages"); - await todoItems.nth(1).getByRole("textbox", { name: "Edit" }).dispatchEvent("blur"); - - await expect(todoItems).toHaveText([TODO_ITEMS[0], "buy some sausages", TODO_ITEMS[2]]); - await checkTodosInLocalStorage(page, "buy some sausages"); - }); - - test("should trim entered text", async ({ page }) => { - const todoItems = page.getByTestId("todo-item"); - await todoItems.nth(1).dblclick(); - await todoItems - .nth(1) - .getByRole("textbox", { name: "Edit" }) - .fill(" buy some sausages "); - await todoItems.nth(1).getByRole("textbox", { name: "Edit" }).press("Enter"); - - await expect(todoItems).toHaveText([TODO_ITEMS[0], "buy some sausages", TODO_ITEMS[2]]); - await checkTodosInLocalStorage(page, "buy some sausages"); - }); - - test("should remove the item if an empty text string was entered", async ({ page }) => { - const todoItems = page.getByTestId("todo-item"); - await todoItems.nth(1).dblclick(); - await todoItems.nth(1).getByRole("textbox", { name: "Edit" }).fill(""); - await todoItems.nth(1).getByRole("textbox", { name: "Edit" }).press("Enter"); - - await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); - }); - - test("should cancel edits on escape", async ({ page }) => { - const todoItems = page.getByTestId("todo-item"); - await todoItems.nth(1).dblclick(); - await todoItems.nth(1).getByRole("textbox", { name: "Edit" }).fill("buy some sausages"); - await todoItems.nth(1).getByRole("textbox", { name: "Edit" }).press("Escape"); - await expect(todoItems).toHaveText(TODO_ITEMS); - }); -}); - -test.describe("Counter", () => { - test("should display the current number of todo items", async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder("What needs to be done?"); - - // create a todo count locator - const todoCount = page.getByTestId("todo-count"); - - await newTodo.fill(TODO_ITEMS[0]); - await newTodo.press("Enter"); - - await expect(todoCount).toContainText("1"); - - await newTodo.fill(TODO_ITEMS[1]); - await newTodo.press("Enter"); - await expect(todoCount).toContainText("2"); - - await checkNumberOfTodosInLocalStorage(page, 2); - }); -}); - -test.describe("Clear completed button", () => { - test.beforeEach(async ({ page }) => { - await createDefaultTodos(page); - }); - - test("should display the correct text", async ({ page }) => { - await page.locator(".todo-list li .toggle").first().check(); - await expect(page.getByRole("button", { name: "Clear completed" })).toBeVisible(); - }); - - test("should remove completed items when clicked", async ({ page }) => { - const todoItems = page.getByTestId("todo-item"); - await todoItems.nth(1).getByRole("checkbox").check(); - await page.getByRole("button", { name: "Clear completed" }).click(); - await expect(todoItems).toHaveCount(2); - await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); - }); - - test("should be hidden when there are no items that are completed", async ({ page }) => { - await page.locator(".todo-list li .toggle").first().check(); - await page.getByRole("button", { name: "Clear completed" }).click(); - await expect(page.getByRole("button", { name: "Clear completed" })).toBeHidden(); - }); -}); - -test.describe("Persistence", () => { - test("should persist its data", async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder("What needs to be done?"); - - for (const item of TODO_ITEMS.slice(0, 2)) { - await newTodo.fill(item); - await newTodo.press("Enter"); - } - - const todoItems = page.getByTestId("todo-item"); - const firstTodoCheck = todoItems.nth(0).getByRole("checkbox"); - await firstTodoCheck.check(); - await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]); - await expect(firstTodoCheck).toBeChecked(); - await expect(todoItems).toHaveClass(["completed", ""]); - - // Ensure there is 1 completed item. - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - - // Now reload. - await page.reload(); - await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]); - await expect(firstTodoCheck).toBeChecked(); - await expect(todoItems).toHaveClass(["completed", ""]); - }); -}); - -test.describe("Routing", () => { - test.beforeEach(async ({ page }) => { - await createDefaultTodos(page); - // make sure the app had a chance to save updated todos in storage - // before navigating to a new view, otherwise the items can get lost :( - // in some frameworks like Durandal - await checkTodosInLocalStorage(page, TODO_ITEMS[0]); - }); - - test("should allow me to display active items", async ({ page }) => { - const todoItem = page.getByTestId("todo-item"); - await page.getByTestId("todo-item").nth(1).getByRole("checkbox").check(); - - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - await page.getByRole("link", { name: "Active" }).click(); - await expect(todoItem).toHaveCount(2); - await expect(todoItem).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); - }); - - test("should respect the back button", async ({ page }) => { - const todoItem = page.getByTestId("todo-item"); - await page.getByTestId("todo-item").nth(1).getByRole("checkbox").check(); - - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - - await test.step("Showing all items", async () => { - await page.getByRole("link", { name: "All" }).click(); - await expect(todoItem).toHaveCount(3); - }); - - await test.step("Showing active items", async () => { - await page.getByRole("link", { name: "Active" }).click(); - }); - - await test.step("Showing completed items", async () => { - await page.getByRole("link", { name: "Completed" }).click(); - }); - - await expect(todoItem).toHaveCount(1); - await page.goBack(); - await expect(todoItem).toHaveCount(2); - await page.goBack(); - await expect(todoItem).toHaveCount(3); - }); - - test("should allow me to display completed items", async ({ page }) => { - await page.getByTestId("todo-item").nth(1).getByRole("checkbox").check(); - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - await page.getByRole("link", { name: "Completed" }).click(); - await expect(page.getByTestId("todo-item")).toHaveCount(1); - }); - - test("should allow me to display all items", async ({ page }) => { - await page.getByTestId("todo-item").nth(1).getByRole("checkbox").check(); - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - await page.getByRole("link", { name: "Active" }).click(); - await page.getByRole("link", { name: "Completed" }).click(); - await page.getByRole("link", { name: "All" }).click(); - await expect(page.getByTestId("todo-item")).toHaveCount(3); - }); - - test("should highlight the currently applied filter", async ({ page }) => { - await expect(page.getByRole("link", { name: "All" })).toHaveClass("selected"); - - //create locators for active and completed links - const activeLink = page.getByRole("link", { name: "Active" }); - const completedLink = page.getByRole("link", { name: "Completed" }); - await activeLink.click(); - - // Page change - active items. - await expect(activeLink).toHaveClass("selected"); - await completedLink.click(); - - // Page change - completed items. - await expect(completedLink).toHaveClass("selected"); - }); -}); - -async function createDefaultTodos(page: Page) { - // create a new todo locator - const newTodo = page.getByPlaceholder("What needs to be done?"); - - for (const item of TODO_ITEMS) { - await newTodo.fill(item); - await newTodo.press("Enter"); - } -} - -async function checkNumberOfTodosInLocalStorage(page: Page, expected: number) { - return await page.waitForFunction((e) => { - return JSON.parse(localStorage["react-todos"]).length === e; - }, expected); -} - -async function checkNumberOfCompletedTodosInLocalStorage(page: Page, expected: number) { - return await page.waitForFunction((e) => { - return ( - JSON.parse(localStorage["react-todos"]).filter((todo: any) => todo.completed).length === - e - ); - }, expected); -} - -async function checkTodosInLocalStorage(page: Page, title: string) { - return await page.waitForFunction((t) => { - return JSON.parse(localStorage["react-todos"]) - .map((todo: any) => todo.title) - .includes(t); - }, title); -} diff --git a/tests/example.spec.ts b/tests/example.spec.ts deleted file mode 100644 index a149fe32..00000000 --- a/tests/example.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { test, expect } from "@playwright/test"; - -test("has title", async ({ page }) => { - await page.goto("https://playwright.dev/"); - - // Expect a title "to contain" a substring. - await expect(page).toHaveTitle(/Playwright/); -}); - -test("get started link", async ({ page }) => { - await page.goto("https://playwright.dev/"); - - // Click the get started link. - await page.getByRole("link", { name: "Get started" }).click(); - - // Expects page to have a heading with the name of Installation. - await expect(page.getByRole("heading", { name: "Installation" })).toBeVisible(); -}); diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 00000000..1eeee90e --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "exclude": [ + "__tests__/**/*.tests.*", + "jest.setup.ts", + "jest.config.ts" + ] +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 0d43c064..a03762d5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -44,7 +44,10 @@ "tailwind.config.js", "postcss.config.js", "next-sitemap.config.js", - "playwright.config.ts" + "playwright.config.ts", + "__tests__/**/*.tests.*", + "jest.setup.ts", + "jest.config.ts" ], "exclude": ["node_modules"] } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 464942f8..88179c9d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@adobe/css-tools@^4.4.0": + version "4.4.1" + resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.1.tgz#2447a230bfe072c1659e6815129c03cf170710e3" + integrity sha512-12WGKBQzjUAI4ayyF4IAtfw2QR/IDoqk6jTddXDhtYTJF9ASmoE1zst7cVtP0aL/F1jUJL5r+JxKXKEgHNbEUQ== + "@ai-sdk/azure@^1.0.7": version "1.0.17" resolved "https://registry.yarnpkg.com/@ai-sdk/azure/-/azure-1.0.17.tgz#68cba6b188313f43056b2ff0bc4ed452075bf595" @@ -980,7 +985,7 @@ "@babel/plugin-transform-modules-commonjs" "^7.25.9" "@babel/plugin-transform-typescript" "^7.25.9" -"@babel/runtime@^7.11.2", "@babel/runtime@^7.13.10", "@babel/runtime@^7.20.13", "@babel/runtime@^7.8.4": +"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.20.13", "@babel/runtime@^7.8.4": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.0.tgz#8600c2f595f277c60815256418b85356a65173c1" integrity sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw== @@ -1027,6 +1032,13 @@ resolved "https://registry.yarnpkg.com/@corex/deepmerge/-/deepmerge-4.0.43.tgz#9bd42559ebb41cc5a7fb7cfeea5f231c20977dca" integrity sha512-N8uEMrMPL0cu/bdboEWpQYb/0i2K5Qn8eCsxzOmxSggJbbQte7ljMRoXm917AbntqTGOzdTu+vP3KOOzoC70HQ== +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + "@emnapi/runtime@^1.2.0": version "1.3.1" resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.3.1.tgz#0fcaa575afc31f455fd33534c19381cfce6c6f60" @@ -1478,7 +1490,7 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.24" -"@jridgewell/resolve-uri@^3.1.0": +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": version "3.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== @@ -1501,6 +1513,14 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": version "0.3.25" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" @@ -2544,11 +2564,75 @@ lodash.merge "^4.6.2" postcss-selector-parser "6.0.10" +"@testing-library/dom@^10.4.0": + version "10.4.0" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-10.4.0.tgz#82a9d9462f11d240ecadbf406607c6ceeeff43a8" + integrity sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/runtime" "^7.12.5" + "@types/aria-query" "^5.0.1" + aria-query "5.3.0" + chalk "^4.1.0" + dom-accessibility-api "^0.5.9" + lz-string "^1.5.0" + pretty-format "^27.0.2" + +"@testing-library/jest-dom@^6.6.3": + version "6.6.3" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.6.3.tgz#26ba906cf928c0f8172e182c6fe214eb4f9f2bd2" + integrity sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA== + dependencies: + "@adobe/css-tools" "^4.4.0" + aria-query "^5.0.0" + chalk "^3.0.0" + css.escape "^1.5.1" + dom-accessibility-api "^0.6.3" + lodash "^4.17.21" + redent "^3.0.0" + +"@testing-library/react@^16.1.0": + version "16.1.0" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-16.1.0.tgz#aa0c61398bac82eaf89776967e97de41ac742d71" + integrity sha512-Q2ToPvg0KsVL0ohND9A3zLJWcOXXcO8IDu3fj11KhNt0UlCWyFyvnCIBkd12tidB2lkiVRG8VFqdhcqhqnAQtg== + dependencies: + "@babel/runtime" "^7.12.5" + +"@tootallnate/once@2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" + integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== + "@trysound/sax@0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== +"@tsconfig/node10@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" + integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@types/aria-query@^5.0.1": + version "5.0.4" + resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708" + integrity sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw== + "@types/babel__core@^7.1.14": version "7.20.5" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" @@ -2679,6 +2763,15 @@ expect "^29.0.0" pretty-format "^29.0.0" +"@types/jsdom@^20.0.0": + version "20.0.1" + resolved "https://registry.yarnpkg.com/@types/jsdom/-/jsdom-20.0.1.tgz#07c14bc19bd2f918c1929541cdaacae894744808" + integrity sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ== + dependencies: + "@types/node" "*" + "@types/tough-cookie" "*" + parse5 "^7.0.0" + "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.9": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" @@ -2808,6 +2901,11 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== +"@types/tough-cookie@*": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" + integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA== + "@types/trusted-types@^2.0.2": version "2.0.7" resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11" @@ -3000,6 +3098,11 @@ resolved "https://registry.yarnpkg.com/@vercel/analytics/-/analytics-1.4.1.tgz#a28a93133d68b6e3d86884a52fa7893f5ecaa381" integrity sha512-ekpL4ReX2TH3LnrRZTUKjHHNpNy9S1I7QmS+g/RQXoSUQ8ienzosuX7T9djZ/s8zPhBx1mpHP/Rw5875N+zQIQ== +abab@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" + integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== + accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -3013,16 +3116,38 @@ ace-builds@^1.32.8, ace-builds@^1.33.1: resolved "https://registry.yarnpkg.com/ace-builds/-/ace-builds-1.37.3.tgz#68a901ae8e5a673bcf7f408bea5b2f15617538f9" integrity sha512-LXMNR57LGyUaJZoAXqVuy6x/ipQvj62iKUHv0DlOb57DNRiV3ZIvYNTVeBHCkUeQAc3BBmyLWC2uvMixSbhj9Q== +acorn-globals@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-7.0.1.tgz#0dbf05c44fa7c94332914c02066d5beff62c40c3" + integrity sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q== + dependencies: + acorn "^8.1.0" + acorn-walk "^8.0.2" + acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.8.2, acorn@^8.9.0: +acorn-walk@^8.0.2, acorn-walk@^8.1.1: + version "8.3.4" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" + integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== + dependencies: + acorn "^8.11.0" + +acorn@^8.1.0, acorn@^8.11.0, acorn@^8.4.1, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0: version "8.14.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -3130,6 +3255,11 @@ anymatch@^3.0.3, anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + arg@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" @@ -3154,7 +3284,14 @@ aria-hidden@^1.1.1: dependencies: tslib "^2.0.0" -aria-query@^5.3.2: +aria-query@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" + integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== + dependencies: + dequal "^2.0.3" + +aria-query@^5.0.0, aria-query@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.2.tgz#93f81a43480e33a338f19163a3d10a50c01dcd59" integrity sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw== @@ -3345,6 +3482,14 @@ axe-core@^4.10.0: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.10.2.tgz#85228e3e1d8b8532a27659b332e39b7fa0e022df" integrity sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w== +axios-mock-adapter@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/axios-mock-adapter/-/axios-mock-adapter-2.1.0.tgz#25ab2d7558f915e391744a40bbeb7374ad5985a4" + integrity sha512-AZUe4OjECGCNNssH8SOdtneiQELsqTsat3SQQCWLPjN436/H+L9AjWfV7bF+Zg/YL9cgbhrz5671hoh+Tbn98w== + dependencies: + fast-deep-equal "^3.1.3" + is-buffer "^2.0.5" + axios@^1.4.0: version "1.7.9" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.9.tgz#d7d071380c132a24accda1b2cfc1535b79ec650a" @@ -3635,7 +3780,15 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== -chalk@^4.0.0, chalk@^4.0.2: +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -3911,6 +4064,11 @@ create-jest@^29.7.0: jest-util "^29.7.0" prompts "^2.0.1" +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" @@ -3957,6 +4115,11 @@ css-what@^6.1.0: resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== +css.escape@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" + integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg== + css@2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929" @@ -3979,6 +4142,23 @@ csso@^5.0.5: dependencies: css-tree "~2.2.0" +cssom@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.5.0.tgz#d254fa92cd8b6fbd83811b9fbaed34663cc17c36" + integrity sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw== + +cssom@~0.3.6: + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + +cssstyle@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== + dependencies: + cssom "~0.3.6" + csstype@^3.0.2: version "3.1.3" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" @@ -3996,6 +4176,15 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +data-urls@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-3.0.2.tgz#9cf24a477ae22bcef5cd5f6f0bfbc1d2d3be9143" + integrity sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ== + dependencies: + abab "^2.0.6" + whatwg-mimetype "^3.0.0" + whatwg-url "^11.0.0" + data-view-buffer@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.2.tgz#211a03ba95ecaf7798a8c7198d79536211f88570" @@ -4035,6 +4224,13 @@ debug@2.6.9: dependencies: ms "2.0.0" +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.7: + version "4.4.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== + dependencies: + ms "^2.1.3" + debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -4042,12 +4238,10 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.7: - version "4.4.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" - integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== - dependencies: - ms "^2.1.3" +decimal.js@^10.4.2: + version "10.4.3" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" + integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== decode-uri-component@^0.2.0: version "0.2.2" @@ -4150,6 +4344,11 @@ diff-sequences@^29.6.3: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -4181,6 +4380,16 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dom-accessibility-api@^0.5.9: + version "0.5.16" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453" + integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg== + +dom-accessibility-api@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz#993e925cc1d73f2c662e7d75dd5a5445259a8fd8" + integrity sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w== + dom-serializer@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" @@ -4202,6 +4411,13 @@ domelementtype@^2.3.0: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== +domexception@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-4.0.0.tgz#4ad1be56ccadc86fc76d033353999a8037d03673" + integrity sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw== + dependencies: + webidl-conversions "^7.0.0" + domhandler@^5.0.2, domhandler@^5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" @@ -4313,7 +4529,7 @@ enhanced-resolve@^5.15.0: graceful-fs "^4.2.4" tapable "^2.2.0" -entities@^4.2.0, entities@^4.4.0: +entities@^4.2.0, entities@^4.4.0, entities@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== @@ -4467,6 +4683,17 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== +escodegen@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17" + integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionalDependencies: + source-map "~0.6.1" + eslint-config-airbnb-base@^15.0.0: version "15.0.0" resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz#6b09add90ac79c2f8d723a2580e07f3925afd236" @@ -4716,7 +4943,7 @@ espree@^9.6.0, espree@^9.6.1: acorn-jsx "^5.3.2" eslint-visitor-keys "^3.4.1" -esprima@^4.0.0: +esprima@^4.0.0, esprima@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== @@ -5359,6 +5586,13 @@ hasown@^2.0.0, hasown@^2.0.2: dependencies: function-bind "^1.1.2" +html-encoding-sniffer@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz#2cb1a8cf0db52414776e5b2a7a04d5dd98158de9" + integrity sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA== + dependencies: + whatwg-encoding "^2.0.0" + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -5375,6 +5609,15 @@ http-errors@2.0.0: statuses "2.0.1" toidentifier "1.0.1" +http-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" + integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== + dependencies: + "@tootallnate/once" "2" + agent-base "6" + debug "4" + http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -5384,6 +5627,14 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" +https-proxy-agent@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== + dependencies: + agent-base "6" + debug "4" + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -5401,6 +5652,13 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" +iconv-lite@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + idb@^7.0.1: version "7.1.1" resolved "https://registry.yarnpkg.com/idb/-/idb-7.1.1.tgz#d910ded866d32c7ced9befc5bfdf36f572ced72b" @@ -5515,6 +5773,11 @@ is-boolean-object@^1.2.1: call-bound "^1.0.2" has-tostringtag "^1.0.2" +is-buffer@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + is-bun-module@^1.0.2: version "1.3.0" resolved "https://registry.yarnpkg.com/is-bun-module/-/is-bun-module-1.3.0.tgz#ea4d24fdebfcecc98e81bcbcb506827fee288760" @@ -5652,6 +5915,11 @@ is-path-inside@^3.0.3: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== +is-potential-custom-element-name@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== + is-regex@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" @@ -5940,6 +6208,20 @@ jest-each@^29.7.0: jest-util "^29.7.0" pretty-format "^29.7.0" +jest-environment-jsdom@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-29.7.0.tgz#d206fa3551933c3fd519e5dfdb58a0f5139a837f" + integrity sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/jsdom" "^20.0.0" + "@types/node" "*" + jest-mock "^29.7.0" + jest-util "^29.7.0" + jsdom "^20.0.0" + jest-environment-node@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" @@ -6243,6 +6525,38 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== +jsdom@^20.0.0: + version "20.0.3" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-20.0.3.tgz#886a41ba1d4726f67a8858028c99489fed6ad4db" + integrity sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ== + dependencies: + abab "^2.0.6" + acorn "^8.8.1" + acorn-globals "^7.0.0" + cssom "^0.5.0" + cssstyle "^2.3.0" + data-urls "^3.0.2" + decimal.js "^10.4.2" + domexception "^4.0.0" + escodegen "^2.0.0" + form-data "^4.0.0" + html-encoding-sniffer "^3.0.0" + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.1" + is-potential-custom-element-name "^1.0.1" + nwsapi "^2.2.2" + parse5 "^7.1.1" + saxes "^6.0.0" + symbol-tree "^3.2.4" + tough-cookie "^4.1.2" + w3c-xmlserializer "^4.0.0" + webidl-conversions "^7.0.0" + whatwg-encoding "^2.0.0" + whatwg-mimetype "^3.0.0" + whatwg-url "^11.0.0" + ws "^8.11.0" + xml-name-validator "^4.0.0" + jsesc@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" @@ -6502,7 +6816,7 @@ lodash.sortby@^4.7.0: resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA== -lodash@^4.0.0, lodash@^4.17.14, lodash@^4.17.20: +lodash@^4.0.0, lodash@^4.17.14, lodash@^4.17.20, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -6555,6 +6869,11 @@ lucide-react@^0.378.0: resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.378.0.tgz#232acb99c6baedfa90959a2c0dd11327b058bde8" integrity sha512-u6EPU8juLUk9ytRcyapkWI18epAv3RU+6+TC23ivjR0e+glWKBobFeSgRwOIJihzktILQuy6E0E80P2jVTDR5g== +lz-string@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" + integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== + magic-string@^0.25.0, magic-string@^0.25.7: version "0.25.9" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c" @@ -6586,7 +6905,7 @@ make-dir@^4.0.0: dependencies: semver "^7.5.3" -make-error@^1.3.6: +make-error@^1.1.1, make-error@^1.3.6: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -6673,6 +6992,11 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -6902,6 +7226,11 @@ nth-check@^2.0.1: dependencies: boolbase "^1.0.0" +nwsapi@^2.2.2: + version "2.2.16" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.16.tgz#177760bba02c351df1d2644e220c31dfec8cdb43" + integrity sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ== + oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" @@ -7111,6 +7440,13 @@ parse-json@^5.2.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" +parse5@^7.0.0, parse5@^7.1.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.2.1.tgz#8928f55915e6125f430cc44309765bf17556a33a" + integrity sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ== + dependencies: + entities "^4.5.0" + parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -7341,6 +7677,15 @@ pretty-bytes@^5.3.0, pretty-bytes@^5.4.1: resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb" integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg== +pretty-format@^27.0.2: + version "27.5.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" + integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== + dependencies: + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^17.0.1" + pretty-format@^29.0.0, pretty-format@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" @@ -7385,7 +7730,7 @@ proxy-from-env@^1.1.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== -psl@^1.1.28: +psl@^1.1.28, psl@^1.1.33: version "1.15.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.15.0.tgz#bdace31896f1d97cec6a79e8224898ce93d974c6" integrity sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w== @@ -7424,6 +7769,11 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -7485,6 +7835,11 @@ react-is@^16.13.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + react-is@^18.0.0: version "18.3.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" @@ -7554,6 +7909,14 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9: version "1.0.10" resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz#c629219e78a3316d8b604c765ef68996964e7bf9" @@ -7664,6 +8027,11 @@ require-from-string@^2.0.2: resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" @@ -7815,7 +8183,7 @@ safe-regex-test@^1.0.3, safe-regex-test@^1.1.0: es-errors "^1.3.0" is-regex "^1.2.1" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -7825,6 +8193,13 @@ sax@>=0.6.0: resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.1.tgz#44cc8988377f126304d3b3fc1010c733b929ef0f" integrity sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg== +saxes@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-6.0.0.tgz#fe5b4a4768df4f14a201b1ba6a65c1f3d9988cc5" + integrity sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA== + dependencies: + xmlchars "^2.2.0" + scheduler@^0.23.2: version "0.23.2" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" @@ -8376,6 +8751,13 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" @@ -8487,6 +8869,11 @@ swrv@1.0.4: resolved "https://registry.yarnpkg.com/swrv/-/swrv-1.0.4.tgz#278b4811ed4acbb1ae46654972a482fd1847e480" integrity sha512-zjEkcP8Ywmj+xOJW3lIT65ciY/4AL4e/Or7Gj0MzU3zBJNMdJiT8geVZhINavnlHRMMCcJLHhraLTAiDOTmQ9g== +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + tailwind-merge@^2.3.0: version "2.6.0" resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-2.6.0.tgz#ac5fb7e227910c038d458f396b7400d93a3142d5" @@ -8629,6 +9016,16 @@ toidentifier@1.0.1: resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== +tough-cookie@^4.1.2: + version "4.1.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.4.tgz#945f1461b45b5a8c76821c33ea49c3ac192c1b36" + integrity sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.2.0" + url-parse "^1.5.3" + tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" @@ -8644,6 +9041,13 @@ tr46@^1.0.1: dependencies: punycode "^2.1.0" +tr46@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-3.0.0.tgz#555c4e297a950617e8eeddef633c87d4d9d6cbf9" + integrity sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA== + dependencies: + punycode "^2.1.1" + traverse@0.6.6: version "0.6.6" resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" @@ -8674,6 +9078,25 @@ ts-jest@^29.2.5: semver "^7.6.3" yargs-parser "^21.1.1" +ts-node@^10.9.2: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + tsconfig-paths@^3.14.1, tsconfig-paths@^3.15.0: version "3.15.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" @@ -8848,6 +9271,11 @@ unique-string@^2.0.0: dependencies: crypto-random-string "^2.0.0" +universalify@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" + integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== + universalify@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" @@ -8883,6 +9311,14 @@ urix@^0.1.0: resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== +url-parse@^1.5.3: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + use-callback-ref@^1.3.0, use-callback-ref@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf" @@ -8923,6 +9359,11 @@ uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + v8-to-istanbul@^9.0.1: version "9.3.0" resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz#b9572abfa62bd556c16d75fdebc1a411d5ff3175" @@ -8946,6 +9387,13 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +w3c-xmlserializer@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz#aebdc84920d806222936e3cdce408e32488a3073" + integrity sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw== + dependencies: + xml-name-validator "^4.0.0" + walker@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" @@ -8958,6 +9406,11 @@ webidl-conversions@^4.0.2: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== +webidl-conversions@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" + integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== + webpack-sources@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" @@ -8966,6 +9419,26 @@ webpack-sources@^1.4.3: source-list-map "^2.0.0" source-map "~0.6.1" +whatwg-encoding@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz#e7635f597fd87020858626805a2729fa7698ac53" + integrity sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg== + dependencies: + iconv-lite "0.6.3" + +whatwg-mimetype@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" + integrity sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q== + +whatwg-url@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018" + integrity sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ== + dependencies: + tr46 "^3.0.0" + webidl-conversions "^7.0.0" + whatwg-url@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" @@ -9257,6 +9730,16 @@ write-file-atomic@^4.0.2: imurmurhash "^0.1.4" signal-exit "^3.0.7" +ws@^8.11.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== + +xml-name-validator@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz#79a006e2e63149a8600f15430f0a4725d1524835" + integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== + xml2js@0.4.17: version "0.4.17" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.17.tgz#17be93eaae3f3b779359c795b419705a8817e868" @@ -9272,6 +9755,11 @@ xmlbuilder@^4.1.0: dependencies: lodash "^4.0.0" +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -9315,6 +9803,11 @@ yargs@^17.3.1: y18n "^5.0.5" yargs-parser "^21.1.1" +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" From 2c206fdcd7573c8b7000629def4aa0ac2ea26d02 Mon Sep 17 00:00:00 2001 From: jonulak Date: Thu, 9 Jan 2025 19:49:39 -0500 Subject: [PATCH 2/5] Update github action to run yarn test --- .github/workflows/playwright.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index a82dc316..e7dc9f1f 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -33,6 +33,9 @@ jobs: - name: Install dependencies run: yarn + + - name: Run tests + run: yarn test - name: Cache Playwright Browsers uses: actions/cache@v4 From 0460b2f447caace9b308549719c4c92c13d39f18 Mon Sep 17 00:00:00 2001 From: jonulak Date: Thu, 9 Jan 2025 20:08:45 -0500 Subject: [PATCH 3/5] Revert playwright example test removal --- package.json | 1 - tests/example.spec.ts | 18 ++++++++++++++++++ tsconfig.build.json | 3 ++- tsconfig.json | 3 ++- yarn.lock | 13 ------------- 5 files changed, 22 insertions(+), 16 deletions(-) create mode 100644 tests/example.spec.ts diff --git a/package.json b/package.json index 2b814b22..b276013b 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,6 @@ "@typescript-eslint/eslint-plugin": "^5.62.0", "@typescript-eslint/parser": "^5.62.0", "autoprefixer": "^10.4.4", - "axios-mock-adapter": "^2.1.0", "eslint": "^8.45.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb-typescript": "^17.0.0", diff --git a/tests/example.spec.ts b/tests/example.spec.ts new file mode 100644 index 00000000..a149fe32 --- /dev/null +++ b/tests/example.spec.ts @@ -0,0 +1,18 @@ +import { test, expect } from "@playwright/test"; + +test("has title", async ({ page }) => { + await page.goto("https://playwright.dev/"); + + // Expect a title "to contain" a substring. + await expect(page).toHaveTitle(/Playwright/); +}); + +test("get started link", async ({ page }) => { + await page.goto("https://playwright.dev/"); + + // Click the get started link. + await page.getByRole("link", { name: "Get started" }).click(); + + // Expects page to have a heading with the name of Installation. + await expect(page.getByRole("heading", { name: "Installation" })).toBeVisible(); +}); diff --git a/tsconfig.build.json b/tsconfig.build.json index 1eeee90e..a8b07e7d 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -3,6 +3,7 @@ "exclude": [ "__tests__/**/*.tests.*", "jest.setup.ts", - "jest.config.ts" + "jest.config.ts", + "tests/**/*.spec.*" ] } \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index a03762d5..814f9764 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -47,7 +47,8 @@ "playwright.config.ts", "__tests__/**/*.tests.*", "jest.setup.ts", - "jest.config.ts" + "jest.config.ts", + "tests/**/*.spec.*" ], "exclude": ["node_modules"] } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 88179c9d..8e99b6e6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3482,14 +3482,6 @@ axe-core@^4.10.0: resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.10.2.tgz#85228e3e1d8b8532a27659b332e39b7fa0e022df" integrity sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w== -axios-mock-adapter@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/axios-mock-adapter/-/axios-mock-adapter-2.1.0.tgz#25ab2d7558f915e391744a40bbeb7374ad5985a4" - integrity sha512-AZUe4OjECGCNNssH8SOdtneiQELsqTsat3SQQCWLPjN436/H+L9AjWfV7bF+Zg/YL9cgbhrz5671hoh+Tbn98w== - dependencies: - fast-deep-equal "^3.1.3" - is-buffer "^2.0.5" - axios@^1.4.0: version "1.7.9" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.9.tgz#d7d071380c132a24accda1b2cfc1535b79ec650a" @@ -5773,11 +5765,6 @@ is-boolean-object@^1.2.1: call-bound "^1.0.2" has-tostringtag "^1.0.2" -is-buffer@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" - integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== - is-bun-module@^1.0.2: version "1.3.0" resolved "https://registry.yarnpkg.com/is-bun-module/-/is-bun-module-1.3.0.tgz#ea4d24fdebfcecc98e81bcbcb506827fee288760" From 32e64577dd37aeeb1b8bfd1b24a4dc1003b8dc61 Mon Sep 17 00:00:00 2001 From: jonulak Date: Thu, 9 Jan 2025 20:16:50 -0500 Subject: [PATCH 4/5] Add playwright test folder to jest path ignore --- jest.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jest.config.ts b/jest.config.ts index 93ef20ba..bf0afce4 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -108,7 +108,7 @@ const config: Config = { }, // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader - // modulePathIgnorePatterns: [], + modulePathIgnorePatterns: ["/tests/"], // Activates notifications for test results // notify: false, From 55fdd320171d971c143f06781d0091932d149aa9 Mon Sep 17 00:00:00 2001 From: jonulak Date: Thu, 9 Jan 2025 20:27:00 -0500 Subject: [PATCH 5/5] Change tsconfig.build.json to remove test dirs from include instead of exclude --- ...6icA5.js => fallback-Nzvr5ryCQtcQecaFx-g4T.js} | 0 tsconfig.build.json | 15 +++++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) rename public/{fallback-a7KM73030O40tzcX6icA5.js => fallback-Nzvr5ryCQtcQecaFx-g4T.js} (100%) diff --git a/public/fallback-a7KM73030O40tzcX6icA5.js b/public/fallback-Nzvr5ryCQtcQecaFx-g4T.js similarity index 100% rename from public/fallback-a7KM73030O40tzcX6icA5.js rename to public/fallback-Nzvr5ryCQtcQecaFx-g4T.js diff --git a/tsconfig.build.json b/tsconfig.build.json index a8b07e7d..c8242259 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -1,9 +1,12 @@ { "extends": "./tsconfig.json", - "exclude": [ - "__tests__/**/*.tests.*", - "jest.setup.ts", - "jest.config.ts", - "tests/**/*.spec.*" - ] + "include": [ + "next-env.d.ts", + "next.config.js", + "src/**/*.ts", + "src/**/*.tsx", + "tailwind.config.js", + "postcss.config.js", + "next-sitemap.config.js", + ], } \ No newline at end of file