diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 28ddba1e6..2be3344d0 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -19,4 +19,18 @@ module.exports = { '@typescript-eslint/no-shadow': ['error'], 'no-only-tests/no-only-tests': 'error', }, + overrides: [ + { + files: ['packages/**/test/*.js', 'packages/**/*.test.js'], + env: { + mocha: true, + }, + globals: { + globalThis: false, // false means read-only + }, + rules: { + 'no-console': 'off', + }, + }, + ], }; diff --git a/packages/astro/test/.eslintrc.cjs b/packages/astro/test/.eslintrc.cjs deleted file mode 100644 index 0e6acda5e..000000000 --- a/packages/astro/test/.eslintrc.cjs +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - rules: { - 'no-console': 'off', - }, -}; diff --git a/packages/astro/test/fixtures/special-chars-in-component-imports/astro.config.mjs b/packages/astro/test/fixtures/special-chars-in-component-imports/astro.config.mjs new file mode 100644 index 000000000..5c044b69d --- /dev/null +++ b/packages/astro/test/fixtures/special-chars-in-component-imports/astro.config.mjs @@ -0,0 +1,8 @@ +import { defineConfig } from 'astro/config'; +import react from '@astrojs/react'; +import mdx from '@astrojs/mdx'; + +// https://astro.build/config +export default defineConfig({ + integrations: [react(), mdx()], +}); diff --git a/packages/astro/test/fixtures/special-chars-in-component-imports/package.json b/packages/astro/test/fixtures/special-chars-in-component-imports/package.json new file mode 100644 index 000000000..d8fbad235 --- /dev/null +++ b/packages/astro/test/fixtures/special-chars-in-component-imports/package.json @@ -0,0 +1,12 @@ +{ + "name": "@test/special-chars-in-component-imports", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/mdx": "workspace:*", + "@astrojs/react": "workspace:*", + "astro": "workspace:*", + "react": "^18.1.0", + "react-dom": "^18.1.0" + } +} diff --git a/packages/astro/test/fixtures/special-chars-in-component-imports/src/components/^--with-carets/Counter.tsx b/packages/astro/test/fixtures/special-chars-in-component-imports/src/components/^--with-carets/Counter.tsx new file mode 100644 index 000000000..5e1dec1b5 --- /dev/null +++ b/packages/astro/test/fixtures/special-chars-in-component-imports/src/components/^--with-carets/Counter.tsx @@ -0,0 +1,12 @@ +import React, { useState } from 'react'; + +export default function Counter ({ id }) { + const [count, setCount] = useState(0); + + return ( +
+
{id}: {count}
+ +
+ ); +} diff --git a/packages/astro/test/fixtures/special-chars-in-component-imports/src/components/and-rockets-🚀/Counter.tsx b/packages/astro/test/fixtures/special-chars-in-component-imports/src/components/and-rockets-🚀/Counter.tsx new file mode 100644 index 000000000..5e1dec1b5 --- /dev/null +++ b/packages/astro/test/fixtures/special-chars-in-component-imports/src/components/and-rockets-🚀/Counter.tsx @@ -0,0 +1,12 @@ +import React, { useState } from 'react'; + +export default function Counter ({ id }) { + const [count, setCount] = useState(0); + + return ( +
+
{id}: {count}
+ +
+ ); +} diff --git a/packages/astro/test/fixtures/special-chars-in-component-imports/src/components/now-100%-better/Counter.tsx b/packages/astro/test/fixtures/special-chars-in-component-imports/src/components/now-100%-better/Counter.tsx new file mode 100644 index 000000000..5e1dec1b5 --- /dev/null +++ b/packages/astro/test/fixtures/special-chars-in-component-imports/src/components/now-100%-better/Counter.tsx @@ -0,0 +1,12 @@ +import React, { useState } from 'react'; + +export default function Counter ({ id }) { + const [count, setCount] = useState(0); + + return ( +
+
{id}: {count}
+ +
+ ); +} diff --git a/packages/astro/test/fixtures/special-chars-in-component-imports/src/components/with some spaces/Counter.tsx b/packages/astro/test/fixtures/special-chars-in-component-imports/src/components/with some spaces/Counter.tsx new file mode 100644 index 000000000..5e1dec1b5 --- /dev/null +++ b/packages/astro/test/fixtures/special-chars-in-component-imports/src/components/with some spaces/Counter.tsx @@ -0,0 +1,12 @@ +import React, { useState } from 'react'; + +export default function Counter ({ id }) { + const [count, setCount] = useState(0); + + return ( +
+
{id}: {count}
+ +
+ ); +} diff --git a/packages/astro/test/fixtures/special-chars-in-component-imports/src/components/with-(round-brackets)/Counter.tsx b/packages/astro/test/fixtures/special-chars-in-component-imports/src/components/with-(round-brackets)/Counter.tsx new file mode 100644 index 000000000..5e1dec1b5 --- /dev/null +++ b/packages/astro/test/fixtures/special-chars-in-component-imports/src/components/with-(round-brackets)/Counter.tsx @@ -0,0 +1,12 @@ +import React, { useState } from 'react'; + +export default function Counter ({ id }) { + const [count, setCount] = useState(0); + + return ( +
+
{id}: {count}
+ +
+ ); +} diff --git a/packages/astro/test/fixtures/special-chars-in-component-imports/src/components/with-[square-brackets]/Counter.tsx b/packages/astro/test/fixtures/special-chars-in-component-imports/src/components/with-[square-brackets]/Counter.tsx new file mode 100644 index 000000000..5e1dec1b5 --- /dev/null +++ b/packages/astro/test/fixtures/special-chars-in-component-imports/src/components/with-[square-brackets]/Counter.tsx @@ -0,0 +1,12 @@ +import React, { useState } from 'react'; + +export default function Counter ({ id }) { + const [count, setCount] = useState(0); + + return ( +
+
{id}: {count}
+ +
+ ); +} diff --git a/packages/astro/test/fixtures/special-chars-in-component-imports/src/pages/index.astro b/packages/astro/test/fixtures/special-chars-in-component-imports/src/pages/index.astro new file mode 100644 index 000000000..5e7ff90cf --- /dev/null +++ b/packages/astro/test/fixtures/special-chars-in-component-imports/src/pages/index.astro @@ -0,0 +1,19 @@ +--- +import CaretCounter from '../components/^--with-carets/Counter'; +import RocketCounter from '../components/and-rockets-🚀/Counter'; +import PercentCounter from '../components/now-100%-better/Counter'; +import SpaceCounter from '../components/with some spaces/Counter'; +import RoundBracketCounter from '../components/with-(round-brackets)/Counter'; +import SquareBracketCounter from '../components/with-[square-brackets]/Counter'; +--- + + +

Special chars in component import paths from an .astro file

+ + + + + + + + diff --git a/packages/astro/test/fixtures/special-chars-in-component-imports/src/pages/mdx.mdx b/packages/astro/test/fixtures/special-chars-in-component-imports/src/pages/mdx.mdx new file mode 100644 index 000000000..f9ccc9e2b --- /dev/null +++ b/packages/astro/test/fixtures/special-chars-in-component-imports/src/pages/mdx.mdx @@ -0,0 +1,15 @@ +import CaretCounter from '../components/^--with-carets/Counter' +import RocketCounter from '../components/and-rockets-🚀/Counter' +import PercentCounter from '../components/now-100%-better/Counter' +import SpaceCounter from '../components/with some spaces/Counter' +import RoundBracketCounter from '../components/with-(round-brackets)/Counter' +import SquareBracketCounter from '../components/with-[square-brackets]/Counter' + +# Special chars in component import paths from an .mdx file + + + + + + + diff --git a/packages/astro/test/special-chars-in-component-imports.test.js b/packages/astro/test/special-chars-in-component-imports.test.js new file mode 100644 index 000000000..6d3b007b8 --- /dev/null +++ b/packages/astro/test/special-chars-in-component-imports.test.js @@ -0,0 +1,126 @@ +import { expect } from 'chai'; +import { load as cheerioLoad } from 'cheerio'; +import { isWindows, loadFixture } from './test-utils.js'; + +describe.skip('Special chars in component import paths', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture; + + const componentIds = ['caret', 'rocket', 'percent', 'space', 'round-bracket', 'square-bracket']; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/special-chars-in-component-imports/', + }); + }); + + describe('build', () => { + before(async () => { + await fixture.build(); + }); + + it('Build succeeds', async () => { + const html = await fixture.readFile('/index.html'); + expect(html).to.contain(''); + }); + + it('Special chars in imports work from .astro files', async () => { + const html = await fixture.readFile('/index.html'); + const $ = cheerioLoad(html); + + // Test 1: Correct page + expect($('h1').text()).to.contain('.astro'); + + // Test 2: All components exist + componentIds.forEach((componentId) => { + expect($(`#${componentId}`), `Component #${componentId} does not exist`).to.have.lengthOf(1); + }); + + // Test 3: Component contents were rendered properly + componentIds.forEach((componentId) => { + expect($(`#${componentId} > div`).text()).to.equal(`${componentId}: 0`); + }); + + // Test 4: There is an island for each component + expect($('astro-island[uid]')).to.have.lengthOf(componentIds.length); + }); + + it('Special chars in imports work from .mdx files', async () => { + const html = await fixture.readFile('/mdx/index.html'); + const $ = cheerioLoad(html); + + // Test 1: Correct page + expect($('h1').text()).to.contain('.mdx'); + + // Test 2: All components exist + componentIds.forEach((componentId) => { + expect($(`#${componentId}`), `Component #${componentId} does not exist`).to.have.lengthOf(1); + }); + + // Test 3: Component contents were rendered properly + componentIds.forEach((componentId) => { + expect($(`#${componentId} > div`).text()).to.equal(`${componentId}: 0`); + }); + + // Test 4: There is an island for each component + expect($('astro-island[uid]')).to.have.lengthOf(componentIds.length); + }); + + }); + + if (isWindows) return; + + describe('dev', () => { + let devServer; + + before(async () => { + devServer = await fixture.startDevServer(); + }); + + after(async () => { + await devServer.stop(); + }); + + it('Special chars in imports work from .astro files', async () => { + const html = await fixture.fetch('/').then((res) => res.text()); + const $ = cheerioLoad(html); + + // Test 1: Correct page + expect($('h1').text()).to.contain('.astro'); + + // Test 2: All components exist + componentIds.forEach((componentId) => { + expect($(`#${componentId}`), `Component #${componentId} does not exist`).to.have.lengthOf(1); + }); + + // Test 3: Component contents were rendered properly + componentIds.forEach((componentId) => { + expect($(`#${componentId} > div`).text()).to.equal(`${componentId}: 0`); + }); + + // Test 4: There is an island for each component + expect($('astro-island[uid]')).to.have.lengthOf(componentIds.length); + }); + + it('Special chars in imports work from .mdx files', async () => { + const html = await fixture.fetch('/mdx').then((res) => res.text()); + const $ = cheerioLoad(html); + + // Test 1: Correct page + expect($('h1').text()).to.contain('.mdx'); + + // Test 2: All components exist + componentIds.forEach((componentId) => { + expect($(`#${componentId}`), `Component #${componentId} does not exist`).to.have.lengthOf(1); + }); + + // Test 3: Component contents were rendered properly + componentIds.forEach((componentId) => { + expect($(`#${componentId} > div`).text()).to.equal(`${componentId}: 0`); + }); + + // Test 4: There is an island for each component + expect($('astro-island[uid]')).to.have.lengthOf(componentIds.length); + }); + }); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7575d01fd..a317f90ab 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1864,6 +1864,20 @@ importers: react: 18.2.0 react-dom: 18.2.0_react@18.2.0 + packages/astro/test/fixtures/special-chars-in-component-imports: + specifiers: + '@astrojs/mdx': workspace:* + '@astrojs/react': workspace:* + astro: workspace:* + react: ^18.1.0 + react-dom: ^18.1.0 + dependencies: + '@astrojs/mdx': link:../../../../integrations/mdx + '@astrojs/react': link:../../../../integrations/react + astro: link:../../.. + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + packages/astro/test/fixtures/ssr-api-route: specifiers: astro: workspace:*