Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(examples): add test-vitest example #2290

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions examples/test-vitest/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# compiled output
/dist
/node_modules

# Logs
logs
*.log
npm-debug.log*
pnpm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# OS
.DS_Store

# Tests
/coverage
/.nyc_output

# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
18 changes: 18 additions & 0 deletions examples/test-vitest/@types/i18next.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* If you want to enable locale keys typechecking and enhance IDE experience.
*
* Requires `resolveJsonModule:true` in your tsconfig.json.
*
* @link https://www.i18next.com/overview/typescript
*/
import 'i18next'

// resources.ts file is generated with `npm run toc`
import resources from './resources.ts'

declare module 'i18next' {
interface CustomTypeOptions {
defaultNS: 'common'
resources: typeof resources
}
}
11 changes: 11 additions & 0 deletions examples/test-vitest/@types/resources.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import common from '../public/locales/en/common.json';
import footer from '../public/locales/en/footer.json';
import secondpage from '../public/locales/en/second-page.json';

const resources = {
common,
footer,
'second-page': secondpage
} as const;

export default resources;
26 changes: 26 additions & 0 deletions examples/test-vitest/components/Footer.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { render, screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { Footer } from "./Footer";

vi.mock("next-i18next", () => ({
Trans: ({ children }: { children: React.ReactNode }) => <>{children}</>,
useTranslation: () => ({
t: (key: string) => key,
}),
}));

vi.mock("next-i18next/package.json", () => ({
default: { version: "1.0.0" },
}));

describe("Footer", () => {
it("renders correctly", () => {
render(<Footer />);

expect(screen.getByText("description")).toBeInTheDocument();
expect(screen.getByText("next-i18next v1.0.0")).toBeInTheDocument();
expect(screen.getByText(/With using/)).toBeInTheDocument();
expect(screen.getByText("locize")).toBeInTheDocument();
expect(screen.getByText("i18next")).toBeInTheDocument();
});
});
33 changes: 33 additions & 0 deletions examples/test-vitest/components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Trans, useTranslation } from "next-i18next";
import pkg from "next-i18next/package.json";
import type { FC } from "react";

export const Footer: FC = () => {
const { t } = useTranslation("footer");

return (
<footer>
<p>{t("description")}</p>
<p>next-i18next v{pkg.version}</p>
<p
style={{
fontSize: "smaller",
fontStyle: "italic",
marginTop: 20,
}}
>
<Trans i18nKey="helpLocize" t={t}>
With using
<a href="https://locize.com" target="_new">
locize
</a>
you directly support the future of
<a href="https://www.i18next.com" target="_new">
i18next
</a>
.
</Trans>
</p>
</footer>
);
};
25 changes: 25 additions & 0 deletions examples/test-vitest/components/Header.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { render, screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { Header } from "./Header";

vi.mock("next/head", () => ({
default: ({ children }: { children: React.ReactNode }) => <>{children}</>,
}));

describe("Header", () => {
it("renders correctly", () => {
const props = {
heading: "Test Heading",
title: "Test Title",
};

render(<Header {...props} />);

expect(screen.getByText("next-i18next")).toBeInTheDocument();
expect(screen.getByText(props.heading)).toBeInTheDocument();
expect(screen.getByRole("link", { name: "" })).toHaveAttribute(
"href",
"//github.com/i18next/next-i18next",
);
});
});
24 changes: 24 additions & 0 deletions examples/test-vitest/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Head from "next/head";
import Link from "next/link";
import type { FC } from "react";

type Props = {
heading: string;
title: string;
};

export const Header: FC<Props> = ({ heading, title }) => (
<>
<Head>
<title>{title}</title>
</Head>
<h2>
next-i18next
<hr />
</h2>
<h1>{heading}</h1>
<Link className="github" href="//github.com/i18next/next-i18next">
<i className="typcn typcn-social-github-circular" />
</Link>
</>
);
5 changes: 5 additions & 0 deletions examples/test-vitest/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
28 changes: 28 additions & 0 deletions examples/test-vitest/next-i18next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// @ts-check

/**
* @type {import('next-i18next').UserConfig}
*/
module.exports = {
// https://www.i18next.com/overview/configuration-options#logging
debug: process.env.NODE_ENV === 'development',
i18n: {
defaultLocale: 'en',
locales: ['en', 'de'],
},
/** To avoid issues when deploying to some paas (vercel...) */
localePath:
typeof window === 'undefined'
? require('path').resolve('./public/locales')
: '/locales',

reloadOnPrerender: process.env.NODE_ENV === 'development',

/**
* @link https://github.com/i18next/next-i18next#6-advanced-configuration
*/
// saveMissing: false,
// strictMode: true,
// serializeConfig: false,
// react: { useSuspense: false }
}
26 changes: 26 additions & 0 deletions examples/test-vitest/next-utils.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const pc = require('picocolors')

const nextUtilsConfig = () => {
const trueEnv = ['true', '1', 'yes']
const esmExternals = trueEnv.includes(
process.env?.NEXTJS_ESM_EXTERNALS ?? 'false'
)
const tsconfigPath = process.env.NEXTJS_TSCONFIG_PATH
? process.env.NEXTJS_TSCONFIG_PATH
: './tsconfig.json'

// eslint-disable-next-line no-console
console.warn(
`${pc.green('warn -')} experimental.esmExternals is ${
esmExternals ? 'enabled' : 'disabled'
}`
)
return {
esmExternals,
tsconfigPath,
}
}

module.exports = {
loadCustomBuildParams: nextUtilsConfig,
}
21 changes: 21 additions & 0 deletions examples/test-vitest/next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// @ts-check
const { i18n } = require('./next-i18next.config.js')

// You can remove the following 2 lines when integrating our example.
const { loadCustomBuildParams } = require('./next-utils.config')
const { esmExternals = false, tsconfigPath } =
loadCustomBuildParams()

/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
esmExternals, // https://nextjs.org/blog/next-11-1#es-modules-support
},
i18n,
reactStrictMode: true,
typescript: {
tsconfigPath,
},
}

module.exports = nextConfig
45 changes: 45 additions & 0 deletions examples/test-vitest/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"name": "next-i18next-example-test-vitest",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start -p ${PORT:=3000}",
"typecheck": "tsc --project ./tsconfig.json --noEmit",
"clean": "rimraf .next",
"nuke:install": "rimraf ./node_modules ./package-lock.json",
"toc": "i18next-resources-for-ts toc -i ./public/locales/en -o ./@types/resources.ts",
"merge": "i18next-resources-for-ts merge -i ./public/locales/en -o ./@types/resources.json",
"interface": "i18next-resources-for-ts interface -i ./public/locales/en -o ./@types/resources.d.ts",
"test": "vitest",
"coverage": "vitest run --coverage"
},
"dependencies": {
"i18next": "23.11.5",
"next": "^14.2.4",
"next-i18next": "^15.3.0",
"react": "^18.3.1",
"react-i18next": "^14.1.2",
"react-dom": "^18.3.1"
},
"devDependencies": {
"@testing-library/jest-dom": "^6.4.8",
"@testing-library/react": "^16.0.0",
"@types/node": "^20.14.6",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react": "^4.3.1",
"@vitest/coverage-v8": "^2.0.4",
"eslint-config-next": "^14.2.4",
"i18next-resources-for-ts": "1.5.0",
"jsdom": "^24.1.1",
"picocolors": "^1.0.1",
"rimraf": "^5.0.7",
"typescript": "^5.4.5",
"vitest": "^2.0.4",
"whatwg-fetch": "^3.6.20"
},
"trustedDependencies": ["core-js"]
}
10 changes: 10 additions & 0 deletions examples/test-vitest/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { appWithTranslation } from "next-i18next";
import type { AppProps } from "next/app";
// import nextI18NextConfig from '../next-i18next.config.js'

const MyApp = ({ Component, pageProps }: AppProps) => (
<Component {...pageProps} />
);

// https://github.com/i18next/next-i18next#unserializable-configs
export default appWithTranslation(MyApp /*, nextI18NextConfig */);
45 changes: 45 additions & 0 deletions examples/test-vitest/pages/_document.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import Document, { Html, Head, Main, NextScript } from "next/document";
import type { DocumentProps } from "next/document";
import i18nextConfig from "../next-i18next.config";

type Props = DocumentProps & {
// add custom document props
};

class MyDocument extends Document<Props> {
render() {
const currentLocale =
this.props.__NEXT_DATA__.locale ?? i18nextConfig.i18n.defaultLocale;
return (
<Html lang={currentLocale}>
<Head>
<meta charSet="utf-8" />
<link
href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css"
rel="stylesheet"
/>
<link href="/app.css" rel="stylesheet" />
<link
href="https://cdnjs.cloudflare.com/ajax/libs/typicons/2.0.9/typicons.min.css"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Open+Sans:300,400|Oswald:600"
rel="stylesheet"
/>
<link
data-react-helmet="true"
rel="icon"
href="https://blobscdn.gitbook.com/v0/b/gitbook-28427.appspot.com/o/spaces%2F-L9iS6Wm2hynS5H9Gj7j%2Favatar.png?generation=1523462254548780&amp;alt=media"
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}

export default MyDocument;
Loading
Loading