Files
next.js/test/unit/eslint-plugin-next/no-before-interactive-script-outside-document.test.ts
Arian Tron 61f56f997c
Some checks failed
Test examples / Test Examples (20) (push) Has been cancelled
Test examples / Test Examples (22) (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Trigger Release / start (push) Has been cancelled
Stale issue handler / stale (push) Has been cancelled
Update Font Data / create-pull-request (push) Has been cancelled
build-and-deploy / deploy-target (push) Has been cancelled
build-and-deploy / build (push) Has been cancelled
build-and-deploy / stable - aarch64-unknown-linux-musl - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-unknown-linux-musl - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-unknown-linux-gnu - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-unknown-linux-gnu - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-pc-windows-msvc - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-pc-windows-msvc - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-apple-darwin - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-apple-darwin - node@16 (push) Has been cancelled
build-and-deploy / build-wasm (nodejs) (push) Has been cancelled
build-and-deploy / build-wasm (web) (push) Has been cancelled
build-and-deploy / Deploy preview tarball (push) Has been cancelled
build-and-deploy / Potentially publish release (push) Has been cancelled
build-and-deploy / publish-turbopack-npm-packages (push) Has been cancelled
build-and-deploy / Deploy examples (push) Has been cancelled
build-and-deploy / thank you, build (push) Has been cancelled
build-and-deploy / Upload Turbopack Bytesize metrics to Datadog (push) Has been cancelled
Rspack Next.js development integration tests / Rspack integration tests (push) Has been cancelled
Rspack Next.js production integration tests / Rspack integration tests (push) Has been cancelled
Turbopack Next.js development integration tests / Next.js integration tests (push) Has been cancelled
Turbopack Next.js production integration tests / Next.js integration tests (push) Has been cancelled
Update Rspack test manifest / Update and upload Rspack development test manifest (push) Has been cancelled
Update Rspack test manifest / Update and upload Rspack production test manifest (push) Has been cancelled
Upload bundler test manifests to areweturboyet.com / Upload test results (push) Has been cancelled
Update React / create-pull-request (push) Has been cancelled
test-e2e-project-reset-cron / reset-test-project (push) Has been cancelled
Notify about the top 15 issues/PRs/feature requests (most reacted) in the last 90 days / run (push) Has been cancelled
first commit
2026-03-10 19:37:31 +03:30

296 lines
8.4 KiB
TypeScript

import { RuleTester } from 'eslint'
import { rules } from '@next/eslint-plugin-next'
const NextESLintRule = rules['no-before-interactive-script-outside-document']
const message =
"`next/script`'s `beforeInteractive` strategy should not be used outside of `pages/_document.js`. See: https://nextjs.org/docs/messages/no-before-interactive-script-outside-document"
const tests = {
valid: [
{
code: `
import Document, { Html, Main, NextScript } from 'next/document'
import Script from 'next/script'
class MyDocument extends Document {
render() {
return (
<Html>
<Head>
<meta charSet="utf-8" />
</Head>
<body>
<Main />
<NextScript />
<Script
id="scriptBeforeInteractive"
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy="beforeInteractive"
></Script>
</body>
</Html>
)
}
}
export default MyDocument
`,
filename: 'pages/_document.js',
},
{
code: `
import Document, { Html, Main, NextScript } from 'next/document'
import ScriptComponent from 'next/script'
class MyDocument extends Document {
render() {
return (
<Html>
<Head>
<meta charSet="utf-8" />
</Head>
<body>
<Main />
<NextScript />
<ScriptComponent
id="scriptBeforeInteractive"
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy="beforeInteractive"
></ScriptComponent>
</body>
</Html>
)
}
}
export default MyDocument
`,
filename: 'pages/_document.tsx',
},
{
code: `
import Document, { Html, Main, NextScript } from 'next/document'
import ScriptComponent from 'next/script'
class MyDocument extends Document {
render() {
return (
<Html>
<Head>
<meta charSet="utf-8" />
</Head>
<body>
<Main />
<NextScript />
<ScriptComponent
id="scriptBeforeInteractive"
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
></ScriptComponent>
</body>
</Html>
)
}
}
export default MyDocument
`,
filename: 'pages/_document.tsx',
},
{
code: `
import Script from "next/script";
export default function Index() {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<Script
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy='beforeInteractive'
/>
</html>
);
}`,
filename: '/Users/user_name/projects/project-name/app/layout.tsx',
},
{
code: `
import Script from "next/script";
export default function test() {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<Script
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy='beforeInteractive'
/>
</html>
);
}`,
filename: 'C:\\Users\\username\\projects\\project-name\\app\\layout.tsx',
},
{
code: `
import Script from "next/script";
export default function Index() {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<Script
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy='beforeInteractive'
/>
</html>
);
}`,
filename: '/Users/user_name/projects/project-name/src/app/layout.tsx',
},
{
code: `
import Script from "next/script";
export default function test() {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<Script
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy='beforeInteractive'
/>
</html>
);
}`,
filename:
'C:\\Users\\username\\projects\\project-name\\src\\app\\layout.tsx',
},
],
invalid: [
{
code: `
import Head from "next/head";
import Script from "next/script";
export default function Index() {
return (
<Script
id="scriptBeforeInteractive"
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy="beforeInteractive"
></Script>
);
}`,
filename: 'pages/index.js',
errors: [{ message }],
},
{
code: `
import Head from "next/head";
import Script from "next/script";
export default function Index() {
return (
<Script
id="scriptBeforeInteractive"
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy="beforeInteractive"
></Script>
);
}`,
filename: 'components/outside-known-dirs.js',
errors: [{ message }],
},
{
code: `
import Script from "next/script";
export default function Index() {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<Script
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy='beforeInteractive'
/>
</html>
);
}`,
filename: '/Users/user_name/projects/project-name/pages/layout.tsx',
errors: [{ message }],
},
{
code: `
import Script from "next/script";
export default function Index() {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<Script
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy='beforeInteractive'
/>
</html>
);
}`,
filename:
'C:\\Users\\username\\projects\\project-name\\pages\\layout.tsx',
errors: [{ message }],
},
{
code: `
import Script from "next/script";
export default function Index() {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<Script
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy='beforeInteractive'
/>
</html>
);
}`,
filename: '/Users/user_name/projects/project-name/src/pages/layout.tsx',
errors: [{ message }],
},
{
code: `
import Script from "next/script";
export default function test() {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
<Script
src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js?a=scriptBeforeInteractive"
strategy='beforeInteractive'
/>
</html>
);
}`,
filename:
'C:\\Users\\username\\projects\\project-name\\src\\pages\\layout.tsx',
errors: [{ message }],
},
],
}
describe('no-before-interactive-script-outside-document', () => {
new RuleTester({
languageOptions: {
ecmaVersion: 2018,
sourceType: 'module',
parserOptions: {
ecmaFeatures: {
modules: true,
jsx: true,
},
},
},
}).run('eslint', NextESLintRule, tests)
})