diff --git a/.changeset/config.json b/.changeset/config.json index 8292fbe07..41ec3ec86 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -6,5 +6,5 @@ "access": "public", "baseBranch": "main", "updateInternalDependencies": "patch", - "ignore": ["@example/*", "@test/*"] + "ignore": ["@example/*", "@test/*", "@e2e/*"] } diff --git a/package.json b/package.json index 14e9e6193..b3e2bf6d3 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "test:smoke": "node scripts/smoke/index.js", "test:vite-ci": "turbo run test --no-deps --scope=astro --concurrency=1", "test:e2e": "cd packages/astro && pnpm playwright install && pnpm run test:e2e", + "test:e2e:match": "cd packages/astro && pnpm playwright install && pnpm run test:e2e:match", "benchmark": "turbo run benchmark --scope=astro", "lint": "eslint \"packages/**/*.ts\"", "format": "prettier -w .", diff --git a/packages/astro/e2e/astro-component.test.js b/packages/astro/e2e/astro-component.test.js new file mode 100644 index 000000000..65499499f --- /dev/null +++ b/packages/astro/e2e/astro-component.test.js @@ -0,0 +1,42 @@ +import { test as base, expect } from '@playwright/test'; +import { loadFixture } from './test-utils.js'; + +const test = base.extend({ + astro: async ({}, use) => { + const fixture = await loadFixture({ root: './fixtures/astro-component/' }); + await use(fixture); + }, +}); + +let devServer; + +test.beforeEach(async ({ astro }) => { + devServer = await astro.startDevServer(); +}); + +test.afterEach(async () => { + await devServer.stop(); +}); + +test.describe('Astro components', () => { + test('HMR', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const hero = page.locator('section'); + await expect(hero, 'hero has background: white').toHaveCSS( + 'background-color', + 'rgb(255, 255, 255)' + ); + await expect(hero, 'hero has color: black').toHaveCSS('color', 'rgb(0, 0, 0)'); + + // Edit the Hero component with a new background color + await astro.editFile('./src/components/Hero.astro', (content) => + content.replace('background: white', 'background: rgb(230, 230, 230)') + ); + + await expect(hero, 'background color updated').toHaveCSS( + 'background-color', + 'rgb(230, 230, 230)' + ); + }); +}); diff --git a/packages/astro/e2e/fixtures/astro-component/astro.config.mjs b/packages/astro/e2e/fixtures/astro-component/astro.config.mjs new file mode 100644 index 000000000..882e6515a --- /dev/null +++ b/packages/astro/e2e/fixtures/astro-component/astro.config.mjs @@ -0,0 +1,4 @@ +import { defineConfig } from 'astro/config'; + +// https://astro.build/config +export default defineConfig({}); diff --git a/packages/astro/e2e/fixtures/astro-component/package.json b/packages/astro/e2e/fixtures/astro-component/package.json new file mode 100644 index 000000000..33a377834 --- /dev/null +++ b/packages/astro/e2e/fixtures/astro-component/package.json @@ -0,0 +1,8 @@ +{ + "name": "@e2e/astro-component", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*" + } +} diff --git a/packages/astro/e2e/fixtures/astro-component/src/components/Counter.css b/packages/astro/e2e/fixtures/astro-component/src/components/Counter.css new file mode 100644 index 000000000..fb21044d7 --- /dev/null +++ b/packages/astro/e2e/fixtures/astro-component/src/components/Counter.css @@ -0,0 +1,11 @@ +.counter { + display: grid; + font-size: 2em; + grid-template-columns: repeat(3, minmax(0, 1fr)); + margin-top: 2em; + place-items: center; +} + +.counter-message { + text-align: center; +} diff --git a/packages/astro/e2e/fixtures/astro-component/src/components/Counter.jsx b/packages/astro/e2e/fixtures/astro-component/src/components/Counter.jsx new file mode 100644 index 000000000..526f26963 --- /dev/null +++ b/packages/astro/e2e/fixtures/astro-component/src/components/Counter.jsx @@ -0,0 +1,20 @@ +import { h, Fragment } from 'preact'; +import { useState } from 'preact/hooks'; +import './Counter.css'; + +export default function Counter({ children, count: initialCount, id }) { + const [count, setCount] = useState(initialCount); + const add = () => setCount((i) => i + 1); + const subtract = () => setCount((i) => i - 1); + + return ( + <> +
+ +
{count}
+ +
+
{children}
+ + ); +} diff --git a/packages/astro/e2e/fixtures/astro-component/src/components/Hero.astro b/packages/astro/e2e/fixtures/astro-component/src/components/Hero.astro new file mode 100644 index 000000000..680a5f639 --- /dev/null +++ b/packages/astro/e2e/fixtures/astro-component/src/components/Hero.astro @@ -0,0 +1,25 @@ +--- +export interface Props { + title: string; +} + +const { title } = Astro.props as Props; +--- + +
+

{title}

+ +
+ + diff --git a/packages/astro/e2e/fixtures/astro-component/src/components/JSXComponent.jsx b/packages/astro/e2e/fixtures/astro-component/src/components/JSXComponent.jsx new file mode 100644 index 000000000..6cc7b7858 --- /dev/null +++ b/packages/astro/e2e/fixtures/astro-component/src/components/JSXComponent.jsx @@ -0,0 +1,5 @@ +import { h } from 'preact'; + +export default function({ id }) { + return
Preact client:only component
+} diff --git a/packages/astro/e2e/fixtures/astro-component/src/pages/index.astro b/packages/astro/e2e/fixtures/astro-component/src/pages/index.astro new file mode 100644 index 000000000..a52ee713f --- /dev/null +++ b/packages/astro/e2e/fixtures/astro-component/src/pages/index.astro @@ -0,0 +1,16 @@ +--- +import Hero from '../components/Hero.astro'; +--- + + + + + + +
+ + Lorem ipsum, dolor sit amet consectetur adipisicing elit. + +
+ + diff --git a/packages/astro/e2e/fixtures/lit-component/astro.config.mjs b/packages/astro/e2e/fixtures/lit-component/astro.config.mjs new file mode 100644 index 000000000..1eab8f9ab --- /dev/null +++ b/packages/astro/e2e/fixtures/lit-component/astro.config.mjs @@ -0,0 +1,7 @@ +import { defineConfig } from 'astro/config'; +import lit from '@astrojs/lit'; + +// https://astro.build/config +export default defineConfig({ + integrations: [lit()], +}); diff --git a/packages/astro/e2e/fixtures/lit-component/package.json b/packages/astro/e2e/fixtures/lit-component/package.json new file mode 100644 index 000000000..ea73f5982 --- /dev/null +++ b/packages/astro/e2e/fixtures/lit-component/package.json @@ -0,0 +1,11 @@ +{ + "name": "@e2e/lit-component", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/lit": "workspace:*", + "astro": "workspace:*", + "@webcomponents/template-shadowroot": "^0.1.0", + "lit": "^2.2.3" + } +} diff --git a/packages/astro/e2e/fixtures/lit-component/src/components/Counter.js b/packages/astro/e2e/fixtures/lit-component/src/components/Counter.js new file mode 100644 index 000000000..3316a7342 --- /dev/null +++ b/packages/astro/e2e/fixtures/lit-component/src/components/Counter.js @@ -0,0 +1,36 @@ +import { LitElement, html } from 'lit'; + +export const tagName = 'my-counter'; + +class Counter extends LitElement { + static get properties() { + return { + count: { + type: Number, + }, + }; + } + + constructor() { + super(); + this.count = 0; + } + + increment() { + this.count++; + } + + render() { + return html` +
+

Count: ${this.count}

+ + + + +
+ `; + } +} + +customElements.define(tagName, Counter); diff --git a/packages/astro/e2e/fixtures/lit-component/src/pages/index.astro b/packages/astro/e2e/fixtures/lit-component/src/pages/index.astro new file mode 100644 index 000000000..48eb7d2f9 --- /dev/null +++ b/packages/astro/e2e/fixtures/lit-component/src/pages/index.astro @@ -0,0 +1,26 @@ +--- +import '../components/Counter.js'; + +const someProps = { + count: 0, +}; +--- + + + + + + + +

Hello, client:idle!

+
+ + +

Hello, client:load!

+
+ + +

Hello, client:visible!

+
+ + diff --git a/packages/astro/e2e/fixtures/lit-component/src/pages/media.astro b/packages/astro/e2e/fixtures/lit-component/src/pages/media.astro new file mode 100644 index 000000000..e54cec071 --- /dev/null +++ b/packages/astro/e2e/fixtures/lit-component/src/pages/media.astro @@ -0,0 +1,18 @@ +--- +import '../components/Counter.js'; + +const someProps = { + count: 0, +}; +--- + + + + + + + +

Hello, client:media!

+
+ + diff --git a/packages/astro/e2e/fixtures/multiple-frameworks/astro.config.mjs b/packages/astro/e2e/fixtures/multiple-frameworks/astro.config.mjs new file mode 100644 index 000000000..4b50887cd --- /dev/null +++ b/packages/astro/e2e/fixtures/multiple-frameworks/astro.config.mjs @@ -0,0 +1,12 @@ +import { defineConfig } from 'astro/config'; +import preact from '@astrojs/preact'; +import react from '@astrojs/react'; +import svelte from '@astrojs/svelte'; +import vue from '@astrojs/vue'; +import solid from '@astrojs/solid-js'; + +// https://astro.build/config +export default defineConfig({ + // Enable many frameworks to support all different kinds of components. + integrations: [preact(), react(), svelte(), vue(), solid()], +}); diff --git a/packages/astro/e2e/fixtures/multiple-frameworks/package.json b/packages/astro/e2e/fixtures/multiple-frameworks/package.json new file mode 100644 index 000000000..ab0dd06bc --- /dev/null +++ b/packages/astro/e2e/fixtures/multiple-frameworks/package.json @@ -0,0 +1,24 @@ +{ + "name": "@e2e/multiple-frameworks", + "version": "0.0.0", + "private": true, + "devDependencies": { + "@astrojs/lit": "^0.1.3", + "@astrojs/preact": "^0.1.2", + "@astrojs/react": "^0.1.2", + "@astrojs/solid-js": "^0.1.2", + "@astrojs/svelte": "^0.1.3", + "@astrojs/vue": "^0.1.4", + "astro": "^1.0.0-beta.31" + }, + "dependencies": { + "@webcomponents/template-shadowroot": "^0.1.0", + "lit": "^2.2.4", + "preact": "^10.7.2", + "react": "^18.1.0", + "react-dom": "^18.1.0", + "solid-js": "^1.4.2", + "svelte": "^3.48.0", + "vue": "^3.2.34" + } +} diff --git a/packages/astro/e2e/fixtures/multiple-frameworks/src/components/A.astro b/packages/astro/e2e/fixtures/multiple-frameworks/src/components/A.astro new file mode 100644 index 000000000..b2c223a29 --- /dev/null +++ b/packages/astro/e2e/fixtures/multiple-frameworks/src/components/A.astro @@ -0,0 +1,7 @@ +--- +const { id } = Astro.props +--- + +
+

Hello Astro (A)

+
diff --git a/packages/astro/e2e/fixtures/multiple-frameworks/src/components/B.astro b/packages/astro/e2e/fixtures/multiple-frameworks/src/components/B.astro new file mode 100644 index 000000000..339f63735 --- /dev/null +++ b/packages/astro/e2e/fixtures/multiple-frameworks/src/components/B.astro @@ -0,0 +1,7 @@ +--- +const { id } = Astro.props +--- + +
+

Hello Astro (B)

+
diff --git a/packages/astro/e2e/fixtures/multiple-frameworks/src/components/LitCounter.js b/packages/astro/e2e/fixtures/multiple-frameworks/src/components/LitCounter.js new file mode 100644 index 000000000..883a7581d --- /dev/null +++ b/packages/astro/e2e/fixtures/multiple-frameworks/src/components/LitCounter.js @@ -0,0 +1,33 @@ +import { LitElement, html } from 'lit'; + +export const tagName = 'my-counter'; + +class Counter extends LitElement { + static get properties() { + return { + count: { + type: Number, + }, + }; + } + + constructor() { + super(); + this.count = 0; + } + + increment() { + this.count++; + } + + render() { + return html` +
+

Count: ${this.count}

+ +
+ `; + } +} + +customElements.define(tagName, Counter); diff --git a/packages/astro/e2e/fixtures/multiple-frameworks/src/components/PreactCounter.tsx b/packages/astro/e2e/fixtures/multiple-frameworks/src/components/PreactCounter.tsx new file mode 100644 index 000000000..af2258fdf --- /dev/null +++ b/packages/astro/e2e/fixtures/multiple-frameworks/src/components/PreactCounter.tsx @@ -0,0 +1,19 @@ +import { useState } from 'preact/hooks'; + +/** a counter written in Preact */ +export function PreactCounter({ children, id }) { + const [count, setCount] = useState(0); + const add = () => setCount((i) => i + 1); + const subtract = () => setCount((i) => i - 1); + + return ( + <> +
+ +
{count}
+ +
+
{children}
+ + ); +} diff --git a/packages/astro/e2e/fixtures/multiple-frameworks/src/components/ReactCounter.jsx b/packages/astro/e2e/fixtures/multiple-frameworks/src/components/ReactCounter.jsx new file mode 100644 index 000000000..02eb19539 --- /dev/null +++ b/packages/astro/e2e/fixtures/multiple-frameworks/src/components/ReactCounter.jsx @@ -0,0 +1,19 @@ +import { useState } from 'react'; + +/** a counter written in React */ +export function Counter({ children, id }) { + const [count, setCount] = useState(0); + const add = () => setCount((i) => i + 1); + const subtract = () => setCount((i) => i - 1); + + return ( + <> +
+ +
{count}
+ +
+
{children}
+ + ); +} diff --git a/packages/astro/e2e/fixtures/multiple-frameworks/src/components/SolidCounter.tsx b/packages/astro/e2e/fixtures/multiple-frameworks/src/components/SolidCounter.tsx new file mode 100644 index 000000000..689c5222c --- /dev/null +++ b/packages/astro/e2e/fixtures/multiple-frameworks/src/components/SolidCounter.tsx @@ -0,0 +1,19 @@ +import { createSignal } from 'solid-js'; + +/** a counter written with Solid */ +export default function SolidCounter({ children, id }) { + const [count, setCount] = createSignal(0); + const add = () => setCount(count() + 1); + const subtract = () => setCount(count() - 1); + + return ( + <> +
+ +
{count()}
+ +
+
{children}
+ + ); +} diff --git a/packages/astro/e2e/fixtures/multiple-frameworks/src/components/SvelteCounter.svelte b/packages/astro/e2e/fixtures/multiple-frameworks/src/components/SvelteCounter.svelte new file mode 100644 index 000000000..ab13b9c71 --- /dev/null +++ b/packages/astro/e2e/fixtures/multiple-frameworks/src/components/SvelteCounter.svelte @@ -0,0 +1,29 @@ + + + +
+ +
{ count }
+ +
+
+ +
+ + diff --git a/packages/astro/e2e/fixtures/multiple-frameworks/src/components/VueCounter.vue b/packages/astro/e2e/fixtures/multiple-frameworks/src/components/VueCounter.vue new file mode 100644 index 000000000..4861511c8 --- /dev/null +++ b/packages/astro/e2e/fixtures/multiple-frameworks/src/components/VueCounter.vue @@ -0,0 +1,34 @@ + + + diff --git a/packages/astro/e2e/fixtures/multiple-frameworks/src/components/index.ts b/packages/astro/e2e/fixtures/multiple-frameworks/src/components/index.ts new file mode 100644 index 000000000..4077dcacd --- /dev/null +++ b/packages/astro/e2e/fixtures/multiple-frameworks/src/components/index.ts @@ -0,0 +1,2 @@ +export { default as A } from './A.astro'; +export { default as B } from './B.astro'; diff --git a/packages/astro/e2e/fixtures/multiple-frameworks/src/pages/index.astro b/packages/astro/e2e/fixtures/multiple-frameworks/src/pages/index.astro new file mode 100644 index 000000000..a30688bca --- /dev/null +++ b/packages/astro/e2e/fixtures/multiple-frameworks/src/pages/index.astro @@ -0,0 +1,50 @@ +--- +// Style Imports +import '../styles/global.css'; +// Component Imports +import { A, B as Renamed } from '../components'; +import * as react from '../components/ReactCounter.jsx'; +import { PreactCounter } from '../components/PreactCounter.tsx'; +import SolidCounter from '../components/SolidCounter.tsx'; +import VueCounter from '../components/VueCounter.vue'; +import SvelteCounter from '../components/SvelteCounter.svelte'; + +// Full Astro Component Syntax: +// https://docs.astro.build/core-concepts/astro-components/ +--- + + + + + + + + +
+ +

Hello React!

+

What's up?

+
+ + +

Hello Preact!

+
+ + +

Hello Solid!

+
+ + +

Hello Vue!

+
+ + +

Hello Svelte!

+
+ + + + +
+ + diff --git a/packages/astro/e2e/fixtures/multiple-frameworks/src/styles/global.css b/packages/astro/e2e/fixtures/multiple-frameworks/src/styles/global.css new file mode 100644 index 000000000..4912b4c39 --- /dev/null +++ b/packages/astro/e2e/fixtures/multiple-frameworks/src/styles/global.css @@ -0,0 +1,21 @@ +html, +body { + font-family: system-ui; + margin: 0; +} + +body { + padding: 2rem; +} + +.counter { + display: grid; + font-size: 2em; + grid-template-columns: repeat(3, minmax(0, 1fr)); + margin-top: 2em; + place-items: center; +} + +.counter-message { + text-align: center; +} diff --git a/packages/astro/e2e/fixtures/preact-component/astro.config.mjs b/packages/astro/e2e/fixtures/preact-component/astro.config.mjs new file mode 100644 index 000000000..08916b1fe --- /dev/null +++ b/packages/astro/e2e/fixtures/preact-component/astro.config.mjs @@ -0,0 +1,7 @@ +import { defineConfig } from 'astro/config'; +import preact from '@astrojs/preact'; + +// https://astro.build/config +export default defineConfig({ + integrations: [preact()], +}); diff --git a/packages/astro/e2e/fixtures/preact-component/package.json b/packages/astro/e2e/fixtures/preact-component/package.json new file mode 100644 index 000000000..8ee5c3a0a --- /dev/null +++ b/packages/astro/e2e/fixtures/preact-component/package.json @@ -0,0 +1,10 @@ +{ + "name": "@e2e/preact-component", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/preact": "workspace:*", + "astro": "workspace:*", + "preact": "^10.7.2" + } +} diff --git a/packages/astro/e2e/fixtures/preact-component/src/components/Counter.css b/packages/astro/e2e/fixtures/preact-component/src/components/Counter.css new file mode 100644 index 000000000..fb21044d7 --- /dev/null +++ b/packages/astro/e2e/fixtures/preact-component/src/components/Counter.css @@ -0,0 +1,11 @@ +.counter { + display: grid; + font-size: 2em; + grid-template-columns: repeat(3, minmax(0, 1fr)); + margin-top: 2em; + place-items: center; +} + +.counter-message { + text-align: center; +} diff --git a/packages/astro/e2e/fixtures/preact-component/src/components/Counter.jsx b/packages/astro/e2e/fixtures/preact-component/src/components/Counter.jsx new file mode 100644 index 000000000..526f26963 --- /dev/null +++ b/packages/astro/e2e/fixtures/preact-component/src/components/Counter.jsx @@ -0,0 +1,20 @@ +import { h, Fragment } from 'preact'; +import { useState } from 'preact/hooks'; +import './Counter.css'; + +export default function Counter({ children, count: initialCount, id }) { + const [count, setCount] = useState(initialCount); + const add = () => setCount((i) => i + 1); + const subtract = () => setCount((i) => i - 1); + + return ( + <> +
+ +
{count}
+ +
+
{children}
+ + ); +} diff --git a/packages/astro/e2e/fixtures/preact-component/src/components/JSXComponent.jsx b/packages/astro/e2e/fixtures/preact-component/src/components/JSXComponent.jsx new file mode 100644 index 000000000..6cc7b7858 --- /dev/null +++ b/packages/astro/e2e/fixtures/preact-component/src/components/JSXComponent.jsx @@ -0,0 +1,5 @@ +import { h } from 'preact'; + +export default function({ id }) { + return
Preact client:only component
+} diff --git a/packages/astro/e2e/fixtures/preact-component/src/pages/index.astro b/packages/astro/e2e/fixtures/preact-component/src/pages/index.astro new file mode 100644 index 000000000..946b90be0 --- /dev/null +++ b/packages/astro/e2e/fixtures/preact-component/src/pages/index.astro @@ -0,0 +1,37 @@ +--- +import Counter from '../components/Counter.jsx'; +import PreactComponent from '../components/JSXComponent.jsx'; + +const someProps = { + count: 0, +}; +--- + + + + + + + +

Hello, server!

+
+ + +

Hello, client:idle!

+
+ + +

Hello, client:load!

+
+ + +

Hello, client:visible!

+
+ + +

Hello, client:media!

+
+ + + + diff --git a/packages/astro/e2e/fixtures/react-component/astro.config.mjs b/packages/astro/e2e/fixtures/react-component/astro.config.mjs new file mode 100644 index 000000000..8a6f1951c --- /dev/null +++ b/packages/astro/e2e/fixtures/react-component/astro.config.mjs @@ -0,0 +1,7 @@ +import { defineConfig } from 'astro/config'; +import react from '@astrojs/react'; + +// https://astro.build/config +export default defineConfig({ + integrations: [react()], +}); diff --git a/packages/astro/e2e/fixtures/react-component/package.json b/packages/astro/e2e/fixtures/react-component/package.json new file mode 100644 index 000000000..9236558f0 --- /dev/null +++ b/packages/astro/e2e/fixtures/react-component/package.json @@ -0,0 +1,11 @@ +{ + "name": "@e2e/react-component", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/react": "workspace:*", + "astro": "workspace:*", + "react": "^18.1.0", + "react-dom": "^18.1.0" + } +} diff --git a/packages/astro/e2e/fixtures/react-component/src/components/Counter.css b/packages/astro/e2e/fixtures/react-component/src/components/Counter.css new file mode 100644 index 000000000..fb21044d7 --- /dev/null +++ b/packages/astro/e2e/fixtures/react-component/src/components/Counter.css @@ -0,0 +1,11 @@ +.counter { + display: grid; + font-size: 2em; + grid-template-columns: repeat(3, minmax(0, 1fr)); + margin-top: 2em; + place-items: center; +} + +.counter-message { + text-align: center; +} diff --git a/packages/astro/e2e/fixtures/react-component/src/components/Counter.jsx b/packages/astro/e2e/fixtures/react-component/src/components/Counter.jsx new file mode 100644 index 000000000..769e0cccf --- /dev/null +++ b/packages/astro/e2e/fixtures/react-component/src/components/Counter.jsx @@ -0,0 +1,19 @@ +import React, { useState } from 'react'; +import './Counter.css'; + +export default function Counter({ children, count: initialCount, id }) { + const [count, setCount] = useState(initialCount); + const add = () => setCount((i) => i + 1); + const subtract = () => setCount((i) => i - 1); + + return ( + <> +
+ +
{count}
+ +
+
{children}
+ + ); +} diff --git a/packages/astro/e2e/fixtures/react-component/src/components/JSXComponent.jsx b/packages/astro/e2e/fixtures/react-component/src/components/JSXComponent.jsx new file mode 100644 index 000000000..90a4d7c42 --- /dev/null +++ b/packages/astro/e2e/fixtures/react-component/src/components/JSXComponent.jsx @@ -0,0 +1,5 @@ +import React from 'react'; + +export default function({ id }) { + return
React client:only component
+} diff --git a/packages/astro/e2e/fixtures/react-component/src/pages/index.astro b/packages/astro/e2e/fixtures/react-component/src/pages/index.astro new file mode 100644 index 000000000..388fc1d98 --- /dev/null +++ b/packages/astro/e2e/fixtures/react-component/src/pages/index.astro @@ -0,0 +1,37 @@ +--- +import Counter from '../components/Counter.jsx'; +import ReactComponent from '../components/JSXComponent.jsx'; + +const someProps = { + count: 0, +}; +--- + + + + + + + +

Hello, server!

+
+ + +

Hello, client:idle!

+
+ + +

Hello, client:load!

+
+ + +

Hello, client:visible!

+
+ + +

Hello, client:media!

+
+ + + + diff --git a/packages/astro/e2e/fixtures/solid-component/astro.config.mjs b/packages/astro/e2e/fixtures/solid-component/astro.config.mjs new file mode 100644 index 000000000..a6c39b853 --- /dev/null +++ b/packages/astro/e2e/fixtures/solid-component/astro.config.mjs @@ -0,0 +1,7 @@ +import { defineConfig } from 'astro/config'; +import solid from '@astrojs/solid-js'; + +// https://astro.build/config +export default defineConfig({ + integrations: [solid()], +}); diff --git a/packages/astro/e2e/fixtures/solid-component/package.json b/packages/astro/e2e/fixtures/solid-component/package.json new file mode 100644 index 000000000..5973f12fa --- /dev/null +++ b/packages/astro/e2e/fixtures/solid-component/package.json @@ -0,0 +1,12 @@ +{ + "name": "@e2e/solid-component", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/solid-js": "workspace:*", + "astro": "workspace:*" + }, + "devDependencies": { + "solid-js": "^1.4.1" + } +} diff --git a/packages/astro/e2e/fixtures/solid-component/src/components/Counter.css b/packages/astro/e2e/fixtures/solid-component/src/components/Counter.css new file mode 100644 index 000000000..cffdbda7b --- /dev/null +++ b/packages/astro/e2e/fixtures/solid-component/src/components/Counter.css @@ -0,0 +1,11 @@ +.counter { + display: grid; + font-size: 2em; + grid-template-columns: repeat(3, minmax(0, 1fr)); + margin-top: 3em; + place-items: center; +} + +.counter-message { + text-align: center; +} diff --git a/packages/astro/e2e/fixtures/solid-component/src/components/Counter.jsx b/packages/astro/e2e/fixtures/solid-component/src/components/Counter.jsx new file mode 100644 index 000000000..e315033d3 --- /dev/null +++ b/packages/astro/e2e/fixtures/solid-component/src/components/Counter.jsx @@ -0,0 +1,19 @@ +import { createSignal } from 'solid-js'; +import './Counter.css'; + +export default function Counter({ children, id, count: initialCount = 0 }) { + const [count, setCount] = createSignal(initialCount); + const add = () => setCount(count() + 1); + const subtract = () => setCount(count() - 1); + + return ( + <> +
+ +
{count()}
+ +
+
{children}
+ + ); +} diff --git a/packages/astro/e2e/fixtures/solid-component/src/pages/index.astro b/packages/astro/e2e/fixtures/solid-component/src/pages/index.astro new file mode 100644 index 000000000..91013ad0e --- /dev/null +++ b/packages/astro/e2e/fixtures/solid-component/src/pages/index.astro @@ -0,0 +1,34 @@ +--- +import Counter from '../components/Counter.jsx'; + +const someProps = { + count: 0, +}; +--- + + + + + + + +

Hello, server!

+
+ + +

Hello, client:idle!

+
+ + +

Hello, client:load!

+
+ + +

Hello, client:visible!

+
+ + +

Hello, client:media!

+
+ + diff --git a/packages/astro/e2e/fixtures/svelte-component/astro.config.mjs b/packages/astro/e2e/fixtures/svelte-component/astro.config.mjs new file mode 100644 index 000000000..77fdcd1b9 --- /dev/null +++ b/packages/astro/e2e/fixtures/svelte-component/astro.config.mjs @@ -0,0 +1,7 @@ +import { defineConfig } from 'astro/config'; +import svelte from '@astrojs/svelte'; + +// https://astro.build/config +export default defineConfig({ + integrations: [svelte()], +}); diff --git a/packages/astro/e2e/fixtures/svelte-component/package.json b/packages/astro/e2e/fixtures/svelte-component/package.json new file mode 100644 index 000000000..2777c8ecd --- /dev/null +++ b/packages/astro/e2e/fixtures/svelte-component/package.json @@ -0,0 +1,10 @@ +{ + "name": "@e2e/svelte-component", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/svelte": "workspace:*", + "astro": "workspace:*", + "svelte": "^3.48.0" + } +} diff --git a/packages/astro/e2e/fixtures/svelte-component/src/components/Counter.svelte b/packages/astro/e2e/fixtures/svelte-component/src/components/Counter.svelte new file mode 100644 index 000000000..264ec9dde --- /dev/null +++ b/packages/astro/e2e/fixtures/svelte-component/src/components/Counter.svelte @@ -0,0 +1,35 @@ + + +
+ +
{ count }
+ +
+
+ +
+ + diff --git a/packages/astro/e2e/fixtures/svelte-component/src/pages/index.astro b/packages/astro/e2e/fixtures/svelte-component/src/pages/index.astro new file mode 100644 index 000000000..3c8117124 --- /dev/null +++ b/packages/astro/e2e/fixtures/svelte-component/src/pages/index.astro @@ -0,0 +1,34 @@ +--- +import Counter from '../components/Counter.svelte'; + +const someProps = { + count: 0, +}; +--- + + + + + + + +

Hello, server!

+
+ + +

Hello, client:idle!

+
+ + +

Hello, client:load!

+
+ + +

Hello, client:visible!

+
+ + +

Hello, client:media!

+
+ + diff --git a/packages/astro/e2e/fixtures/tailwindcss/package.json b/packages/astro/e2e/fixtures/tailwindcss/package.json index 4bcc56872..f06e3ea91 100644 --- a/packages/astro/e2e/fixtures/tailwindcss/package.json +++ b/packages/astro/e2e/fixtures/tailwindcss/package.json @@ -1,5 +1,5 @@ { - "name": "@test/e2e-tailwindcss", + "name": "@e2e/e2e-tailwindcss", "version": "0.0.0", "private": true, "dependencies": { diff --git a/packages/astro/e2e/fixtures/vue-component/astro.config.mjs b/packages/astro/e2e/fixtures/vue-component/astro.config.mjs new file mode 100644 index 000000000..94bdad87f --- /dev/null +++ b/packages/astro/e2e/fixtures/vue-component/astro.config.mjs @@ -0,0 +1,13 @@ +import { defineConfig } from 'astro/config'; +import vue from '@astrojs/vue'; + +// https://astro.build/config +export default defineConfig({ + integrations: [vue({ + template: { + compilerOptions: { + isCustomElement: tag => tag.includes('my-button') + } + } + })], +}); diff --git a/packages/astro/e2e/fixtures/vue-component/package.json b/packages/astro/e2e/fixtures/vue-component/package.json new file mode 100644 index 000000000..2322b5d2d --- /dev/null +++ b/packages/astro/e2e/fixtures/vue-component/package.json @@ -0,0 +1,9 @@ +{ + "name": "@test/vue-component", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/vue": "workspace:*", + "astro": "workspace:*" + } +} diff --git a/packages/astro/e2e/fixtures/vue-component/src/components/Counter.vue b/packages/astro/e2e/fixtures/vue-component/src/components/Counter.vue new file mode 100644 index 000000000..6516d1ee5 --- /dev/null +++ b/packages/astro/e2e/fixtures/vue-component/src/components/Counter.vue @@ -0,0 +1,47 @@ + + + diff --git a/packages/astro/e2e/fixtures/vue-component/src/components/Result.vue b/packages/astro/e2e/fixtures/vue-component/src/components/Result.vue new file mode 100644 index 000000000..90bf218b2 --- /dev/null +++ b/packages/astro/e2e/fixtures/vue-component/src/components/Result.vue @@ -0,0 +1,16 @@ + + + diff --git a/packages/astro/e2e/fixtures/vue-component/src/pages/index.astro b/packages/astro/e2e/fixtures/vue-component/src/pages/index.astro new file mode 100644 index 000000000..40619841f --- /dev/null +++ b/packages/astro/e2e/fixtures/vue-component/src/pages/index.astro @@ -0,0 +1,33 @@ +--- +import Counter from '../components/Counter.vue' +--- + + + + + Vue component + + + +
+ No Client + Hello, client:load! + + Hello, client:load! + + Hello, client:load! + Hello, client:idle! + + Hello, client:visible! + Hello, client:media! +
+ + diff --git a/packages/astro/e2e/lit-component.test.js b/packages/astro/e2e/lit-component.test.js new file mode 100644 index 000000000..b3f48a3af --- /dev/null +++ b/packages/astro/e2e/lit-component.test.js @@ -0,0 +1,103 @@ +import { test as base, expect } from '@playwright/test'; +import { loadFixture } from './test-utils.js'; + +const test = base.extend({ + astro: async ({}, use) => { + const fixture = await loadFixture({ root: './fixtures/lit-component/' }); + await use(fixture); + }, +}); + +let devServer; + +test.beforeEach(async ({ astro }) => { + devServer = await astro.startDevServer(); +}); + +test.afterEach(async () => { + await devServer.stop(); +}); + +// TODO: configure playwright to handle web component APIs +// https://github.com/microsoft/playwright/issues/14241 +test.describe.skip('Lit components', () => { + test('client:idle', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#client-idle'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('p'); + await expect(count, 'initial count is 0').toHaveText('Count: 0'); + + const inc = counter.locator('button'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('Count: 1'); + }); + + test('client:load', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#client-load'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('p'); + await expect(count, 'initial count is 0').toHaveText('Count: 0'); + + const inc = counter.locator('button'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('Count: 1'); + }); + + test('client:visible', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + // Make sure the component is on screen to trigger hydration + const counter = page.locator('#client-visible'); + await counter.scrollIntoViewIfNeeded(); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('p'); + await expect(count, 'initial count is 0').toHaveText('Count: 0'); + + const inc = counter.locator('button'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('Count: 1'); + }); + + test('client:media', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/media')); + + const counter = page.locator('#client-media'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('p'); + await expect(count, 'initial count is 0').toHaveText('Count: 0'); + + const inc = counter.locator('button'); + await inc.click(); + + await expect(count, 'component not hydrated yet').toHaveText('Count: 0'); + + // Reset the viewport to hydrate the component (max-width: 50rem) + await page.setViewportSize({ width: 414, height: 1124 }); + + await inc.click(); + await expect(count, 'count incremented by 1').toHaveText('Count: 1'); + }); + + test('HMR', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const label = page.locator('#client-idle h1'); + + await astro.editFile('./src/pages/index.astro', (original) => + original.replace('Hello, client:idle!', 'Hello, updated client:idle!') + ); + + await expect(label, 'slot text updated').toHaveText('Hello, updated client:idle!'); + }); +}); diff --git a/packages/astro/e2e/multiple-frameworks.test.js b/packages/astro/e2e/multiple-frameworks.test.js new file mode 100644 index 000000000..6f3906400 --- /dev/null +++ b/packages/astro/e2e/multiple-frameworks.test.js @@ -0,0 +1,141 @@ +import { test as base, expect } from '@playwright/test'; +import { loadFixture } from './test-utils.js'; + +const test = base.extend({ + astro: async ({}, use) => { + const fixture = await loadFixture({ root: './fixtures/multiple-frameworks/' }); + await use(fixture); + }, +}); + +let devServer; + +test.beforeEach(async ({ astro }) => { + devServer = await astro.startDevServer(); +}); + +test.afterEach(async () => { + await devServer.stop(); +}); + +test.describe('Multiple frameworks', () => { + test('React counter', async ({ astro, page }) => { + await page.goto('/'); + + const counter = await page.locator('#react-counter'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = await counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const increment = await counter.locator('.increment'); + await increment.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('Preact counter', async ({ astro, page }) => { + await page.goto('/'); + + const counter = await page.locator('#preact-counter'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = await counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const increment = await counter.locator('.increment'); + await increment.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('Solid counter', async ({ astro, page }) => { + await page.goto('/'); + + const counter = await page.locator('#solid-counter'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = await counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const increment = await counter.locator('.increment'); + await increment.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('Vue counter', async ({ astro, page }) => { + await page.goto('/'); + + const counter = await page.locator('#vue-counter'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = await counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const increment = await counter.locator('.increment'); + await increment.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('Svelte counter', async ({ astro, page }) => { + await page.goto('/'); + + const counter = await page.locator('#svelte-counter'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = await counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const increment = await counter.locator('.increment'); + await increment.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('Astro components', async ({ astro, page }) => { + await page.goto('/'); + + const aComponent = await page.locator('#astro-a'); + await expect(aComponent, 'component is visible').toBeVisible(); + await expect(aComponent, 'component text is visible').toHaveText('Hello Astro (A)'); + + + const bComponent = await page.locator('#astro-b'); + await expect(bComponent, 'component is visible').toBeVisible(); + await expect(bComponent, 'component text is visible').toHaveText('Hello Astro (B)'); + }); + + test('HMR', async ({ astro, page }) => { + await page.goto('/'); + + // 1: updating the page template + const preactSlot = page.locator('#preact-counter + .counter-message'); + await expect(preactSlot, 'initial slot content').toHaveText('Hello Preact!'); + + await astro.editFile('./src/pages/index.astro', (content) => + content.replace('Hello Preact!', 'Hello Preact, updated!') + ); + + await expect(preactSlot, 'slot content updated').toHaveText('Hello Preact, updated!'); + + // Edit the react component + await astro.editFile('./src/components/ReactCounter.jsx', (content) => + content.replace('useState(0)', 'useState(5)') + ); + + const reactCount = await page.locator('#react-counter pre'); + await expect(reactCount, 'initial count updated to 5').toHaveText('5'); + + // Edit the svelte component's style + const svelteCounter = page.locator('#svelte-counter'); + await expect(svelteCounter, 'initial background is white').toHaveCSS('background-color', 'rgb(255, 255, 255)'); + + await astro.editFile('./src/components/SvelteCounter.svelte', (content) => + content.replace('background: white', 'background: rgb(230, 230, 230)') + ); + + await expect(svelteCounter, 'background color updated').toHaveCSS('background-color', 'rgb(230, 230, 230)'); + }); +}); diff --git a/packages/astro/e2e/nested-styles.test.js b/packages/astro/e2e/nested-styles.test.js index 7c233d4cb..ff7dbac30 100644 --- a/packages/astro/e2e/nested-styles.test.js +++ b/packages/astro/e2e/nested-styles.test.js @@ -10,18 +10,18 @@ const test = base.extend({ let devServer; -test.beforeAll(async ({ astro }) => { +test.beforeEach(async ({ astro }) => { devServer = await astro.startDevServer(); }); -test.afterAll(async ({ astro }) => { +test.afterEach(async () => { await devServer.stop(); }); -test('Loading styles that are nested', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); +test.describe('Loading styles that are nested', () => { + test('header', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); - await test.step('header', async () => { const header = page.locator('header'); await expect(header, 'should have background color').toHaveCSS( diff --git a/packages/astro/e2e/preact-component.test.js b/packages/astro/e2e/preact-component.test.js new file mode 100644 index 000000000..7eca69044 --- /dev/null +++ b/packages/astro/e2e/preact-component.test.js @@ -0,0 +1,143 @@ +import { test as base, expect } from '@playwright/test'; +import { loadFixture } from './test-utils.js'; + +const test = base.extend({ + astro: async ({}, use) => { + const fixture = await loadFixture({ root: './fixtures/preact-component/' }); + await use(fixture); + }, +}); + +let devServer; + +test.beforeEach(async ({ astro }) => { + devServer = await astro.startDevServer(); +}); + +test.afterEach(async () => { + await devServer.stop(); +}); + +test.describe('Preact components', () => { + test('server only', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#server-only'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('0'); + }); + + test('client:idle', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#client-idle'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('client:load', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#client-load'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('client:visible', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + // Make sure the component is on screen to trigger hydration + const counter = page.locator('#client-visible'); + await counter.scrollIntoViewIfNeeded(); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('client:media', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#client-media'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + await expect(count, 'component not hydrated yet').toHaveText('0'); + + // Reset the viewport to hydrate the component (max-width: 50rem) + await page.setViewportSize({ width: 414, height: 1124 }); + await inc.click(); + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('client:only', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const label = page.locator('#client-only'); + await expect(label, 'component is visible').toBeVisible(); + + await expect(label, 'slot text is visible').toHaveText('Preact client:only component'); + }); + + test('HMR', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const count = page.locator('#client-idle pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + // Edit the component's initial count prop + await astro.editFile('./src/pages/index.astro', (original) => + original.replace('id="client-idle" {...someProps}', 'id="client-idle" count={5}') + ); + + await expect(count, 'count prop updated').toHaveText('5'); + + // Edit the component's slot text + await astro.editFile('./src/components/JSXComponent.jsx', (original) => + original.replace('Preact client:only component', 'Updated preact client:only component') + ); + + const label = page.locator('#client-only'); + await expect(label, 'client:only component is visible').toBeVisible(); + await expect(label, 'client:only slot text is visible').toHaveText( + 'Updated preact client:only component' + ); + + // Edit the imported CSS file + await astro.editFile('./src/components/Counter.css', (original) => + original.replace('font-size: 2em;', 'font-size: 24px;') + ); + + await expect(count, 'imported styles updated').toHaveCSS('font-size', '24px'); + }); +}); diff --git a/packages/astro/e2e/react-component.test.js b/packages/astro/e2e/react-component.test.js new file mode 100644 index 000000000..2dded1e6d --- /dev/null +++ b/packages/astro/e2e/react-component.test.js @@ -0,0 +1,143 @@ +import { test as base, expect } from '@playwright/test'; +import { loadFixture } from './test-utils.js'; + +const test = base.extend({ + astro: async ({}, use) => { + const fixture = await loadFixture({ root: './fixtures/react-component/' }); + await use(fixture); + }, +}); + +let devServer; + +test.beforeEach(async ({ astro }) => { + devServer = await astro.startDevServer(); +}); + +test.afterEach(async () => { + await devServer.stop(); +}); + +test.describe('React components', () => { + test('server only', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#server-only'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'component not hydrated').toHaveText('0'); + }); + + test('client:idle', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#client-idle'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('client:load', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#client-load'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('client:visible', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + // Make sure the component is on screen to trigger hydration + const counter = page.locator('#client-visible'); + await counter.scrollIntoViewIfNeeded(); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('client:media', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#client-media'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + await expect(count, 'component not hydrated yet').toHaveText('0'); + + // Reset the viewport to hydrate the component (max-width: 50rem) + await page.setViewportSize({ width: 414, height: 1124 }); + await inc.click(); + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('client:only', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const label = page.locator('#client-only'); + await expect(label, 'component is visible').toBeVisible(); + + await expect(label, 'slot text is visible').toHaveText('React client:only component'); + }); + + test('HMR', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const count = page.locator('#client-idle pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + // Edit the component's initial count prop + await astro.editFile('./src/pages/index.astro', (original) => + original.replace('id="client-idle" {...someProps}', 'id="client-idle" count={5}') + ); + + await expect(count, 'count prop updated').toHaveText('5'); + + // Edit the component's slot text + await astro.editFile('./src/components/JSXComponent.jsx', (original) => + original.replace('React client:only component', 'Updated react client:only component') + ); + + const label = page.locator('#client-only'); + await expect(label, 'client:only component is visible').toBeVisible(); + await expect(label, 'client:only slot text is visible').toHaveText( + 'Updated react client:only component' + ); + + // Edit the imported CSS file + await astro.editFile('./src/components/Counter.css', (original) => + original.replace('font-size: 2em;', 'font-size: 24px;') + ); + + await expect(count, 'imported CSS updated').toHaveCSS('font-size', '24px'); + }); +}); diff --git a/packages/astro/e2e/solid-component.test.js b/packages/astro/e2e/solid-component.test.js new file mode 100644 index 000000000..f02b76f65 --- /dev/null +++ b/packages/astro/e2e/solid-component.test.js @@ -0,0 +1,123 @@ +import { test as base, expect } from '@playwright/test'; +import { loadFixture } from './test-utils.js'; + +const test = base.extend({ + astro: async ({}, use) => { + const fixture = await loadFixture({ root: './fixtures/solid-component/' }); + await use(fixture); + }, +}); + +let devServer; + +test.beforeEach(async ({ astro }) => { + devServer = await astro.startDevServer(); +}); + +test.afterEach(async () => { + await devServer.stop(); +}); + +test.describe('Solid components', () => { + test('server only', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#server-only'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'component not hydrated').toHaveText('0'); + }); + + test('client:idle', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#client-idle'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('client:load', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#client-load'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('client:visible', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + // Make sure the component is on screen to trigger hydration + const counter = page.locator('#client-visible'); + await counter.scrollIntoViewIfNeeded(); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('client:media', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#client-media'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + await expect(count, 'component not hydrated yet').toHaveText('0'); + + // Reset the viewport to hydrate the component (max-width: 50rem) + await page.setViewportSize({ width: 414, height: 1124 }); + await inc.click(); + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('HMR', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const count = page.locator('#client-idle pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + // Edit the component's initial count prop + await astro.editFile('./src/pages/index.astro', (original) => + original.replace('id="client-idle" {...someProps}', 'id="client-idle" count={5}') + ); + + await expect(count, 'count prop updated').toHaveText('5'); + + // Edit the imported CSS + await astro.editFile('./src/components/Counter.css', (original) => + original.replace('font-size: 2em;', 'font-size: 24px;') + ); + + await expect(count, 'imported CSS updated').toHaveCSS('font-size', '24px'); + }); +}); diff --git a/packages/astro/e2e/svelte-component.test.js b/packages/astro/e2e/svelte-component.test.js new file mode 100644 index 000000000..65d9ea68e --- /dev/null +++ b/packages/astro/e2e/svelte-component.test.js @@ -0,0 +1,114 @@ +import { test as base, expect } from '@playwright/test'; +import { loadFixture } from './test-utils.js'; + +const test = base.extend({ + astro: async ({}, use) => { + const fixture = await loadFixture({ root: './fixtures/svelte-component/' }); + await use(fixture); + }, +}); + +let devServer; + +test.beforeEach(async ({ astro }) => { + devServer = await astro.startDevServer(); +}); + +test.afterEach(async () => { + await devServer.stop(); +}); + +test.describe('Svelte components', () => { + test('server only', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#server-only'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'component not hydrated').toHaveText('0'); + }); + + test('client:idle', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#client-idle'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('client:load', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#client-load'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('client:visible', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + // Make sure the component is on screen to trigger hydration + const counter = page.locator('#client-visible'); + await counter.scrollIntoViewIfNeeded(); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('client:media', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#client-media'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + await expect(count, 'component not hydrated yet').toHaveText('0'); + + // Reset the viewport to hydrate the component (max-width: 50rem) + await page.setViewportSize({ width: 414, height: 1124 }); + await inc.click(); + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('HMR', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + // Edit the component's slot text + await astro.editFile('./src/pages/index.astro', (original) => + original.replace('Hello, client:idle!', 'Hello, updated client:idle!') + ); + + const label = page.locator('#client-idle-message'); + await expect(label, 'slot text updated').toHaveText('Hello, updated client:idle!'); + }); +}); diff --git a/packages/astro/e2e/tailwindcss.test.js b/packages/astro/e2e/tailwindcss.test.js index e156a7be7..acfa9b724 100644 --- a/packages/astro/e2e/tailwindcss.test.js +++ b/packages/astro/e2e/tailwindcss.test.js @@ -10,18 +10,19 @@ const test = base.extend({ let devServer; -test.beforeAll(async ({ astro }) => { +test.beforeEach(async ({ astro }) => { devServer = await astro.startDevServer(); }); -test.afterAll(async ({ astro }) => { +test.afterEach(async ({ astro }) => { await devServer.stop(); + astro.resetAllFiles(); }); -test('Tailwind CSS', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); +test.describe('Tailwind CSS', () => { + test('body', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); - await test.step('body', async () => { const body = page.locator('body'); await expect(body, 'should have classes').toHaveClass('bg-dawn text-midnight'); @@ -32,7 +33,9 @@ test('Tailwind CSS', async ({ page, astro }) => { await expect(body, 'should have color').toHaveCSS('color', 'rgb(49, 39, 74)'); }); - await test.step('button', async () => { + test('button', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + const button = page.locator('button'); await expect(button, 'should have bg-purple-600').toHaveClass(/bg-purple-600/); @@ -48,4 +51,20 @@ test('Tailwind CSS', async ({ page, astro }) => { await expect(button, 'should have font-[900]').toHaveClass(/font-\[900\]/); await expect(button, 'should have font weight').toHaveCSS('font-weight', '900'); }); + + test('HMR', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + await astro.editFile('./src/components/Button.astro', (original) => + original.replace('bg-purple-600', 'bg-purple-400') + ); + + const button = page.locator('button'); + + await expect(button, 'should have bg-purple-400').toHaveClass(/bg-purple-400/); + await expect(button, 'should have background color').toHaveCSS( + 'background-color', + 'rgb(192, 132, 252)' + ); + }); }); diff --git a/packages/astro/e2e/vue-component.test.js b/packages/astro/e2e/vue-component.test.js new file mode 100644 index 000000000..28b5e3fd0 --- /dev/null +++ b/packages/astro/e2e/vue-component.test.js @@ -0,0 +1,144 @@ +import { test as base, expect } from '@playwright/test'; +import { loadFixture } from './test-utils.js'; + +const test = base.extend({ + astro: async ({}, use) => { + const fixture = await loadFixture({ root: './fixtures/vue-component/' }); + await use(fixture); + }, +}); + +let devServer; + +test.beforeEach(async ({ astro }) => { + devServer = await astro.startDevServer(); +}); + +test.afterEach(async () => { + await devServer.stop(); +}); + +test.describe('Vue components', () => { + test('server only', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#server-only'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'component not hydrated').toHaveText('0'); + }); + + test('client:idle', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#client-idle'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('client:load', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + // Multiple counters on the page to verify islands aren't sharing state + const counter = page.locator('#client-load'); + const counterDup = page.locator('#client-load-dup'); + const counterStep = page.locator('#client-load-step'); + + await expect(counter).toBeVisible(); + await expect(counterDup).toBeVisible(); + await expect(counterStep).toBeVisible(); + + const count = counter.locator('pre'); + const countDup = counterDup.locator('pre'); + const countStep = counterStep.locator('pre'); + + const countInc = counter.locator('.increment'); + const countDupInc = counterDup.locator('.increment'); + const countStepInc = counterStep.locator('.increment'); + + // Should only increment the first counter + await countInc.click(); + + await expect(count, 'intial count is 1').toHaveText('1'); + await expect(countDup, 'initial count is 0').toHaveText('0'); + await expect(countStep, 'initial count is 0').toHaveText('0'); + + // Should only increment the second counter + await countDupInc.click(); + + await expect(count, "count didn't change").toHaveText('1'); + await expect(countDup, 'count incremented by 1').toHaveText('1'); + await expect(countStep, "count didn't change").toHaveText('0'); + + // Should only increment the third counter + // Expecting an increase of 4 becasuse the component's + // step is set to 2 + await countStepInc.click(); + await countStepInc.click(); + + await expect(count, "count didn't change").toHaveText('1'); + await expect(countDup, "count didn't change").toHaveText('1'); + await expect(countStep, 'count incremented by 4').toHaveText('4'); + }); + + test('client:visible', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + // Make sure the component is on screen to trigger hydration + const counter = page.locator('#client-visible'); + await counter.scrollIntoViewIfNeeded(); + await expect(counter).toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('client:media', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + const counter = page.locator('#client-media'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + await expect(count, 'component not hydrated yet').toHaveText('0'); + + // Reset the viewport to hydrate the component (max-width: 50rem) + await page.setViewportSize({ width: 414, height: 1124 }); + await inc.click(); + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('HMR', async ({ page, astro }) => { + await page.goto(astro.resolveUrl('/')); + + // Edit the component's slot text + await astro.editFile('./src/pages/index.astro', (original) => + original.replace('Hello, client:visible!', 'Hello, updated client:visible!') + ); + + const label = page.locator('#client-visible h1'); + await expect(label, 'slotted text updated').toHaveText('Hello, updated client:visible!'); + }); +}); diff --git a/packages/astro/package.json b/packages/astro/package.json index 9a2b06ec3..709d6f21f 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -73,7 +73,8 @@ "benchmark": "node test/benchmark/dev.bench.js && node test/benchmark/build.bench.js", "test": "mocha --exit --timeout 20000 --ignore **/lit-element.test.js --ignore **/errors.test.js && mocha --timeout 20000 **/lit-element.test.js && mocha --timeout 20000 **/errors.test.js", "test:match": "mocha --timeout 20000 -g", - "test:e2e": "playwright test e2e" + "test:e2e": "playwright test", + "test:e2e:match": "playwright test -g" }, "dependencies": { "@astrojs/compiler": "^0.14.3", diff --git a/packages/astro/playwright.config.js b/packages/astro/playwright.config.js new file mode 100644 index 000000000..8c13d8ef9 --- /dev/null +++ b/packages/astro/playwright.config.js @@ -0,0 +1,42 @@ +import { devices } from '@playwright/test'; + +const config = { + testMatch: 'e2e/*.test.js', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: process.env.PLAYWRIGHT_TEST_BASE_URL || 'http://localhost:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + projects: [ + { + name: 'Chrome Stable', + use: { + browserName: 'chromium', + channel: 'chrome', + }, + }, + ], + +}; + +export default config; diff --git a/packages/astro/src/runtime/client/hmr.ts b/packages/astro/src/runtime/client/hmr.ts index 7cd773256..8a0512f26 100644 --- a/packages/astro/src/runtime/client/hmr.ts +++ b/packages/astro/src/runtime/client/hmr.ts @@ -31,7 +31,7 @@ if (import.meta.hot) { } } if (hasAstroUpdate) { - return updatePage(); + return await updatePage(); } } import.meta.hot.on('vite:beforeUpdate', async (event) => { diff --git a/packages/astro/test/errors.test.js b/packages/astro/test/errors.test.js index 7391d363e..2c5dbdbf3 100644 --- a/packages/astro/test/errors.test.js +++ b/packages/astro/test/errors.test.js @@ -52,9 +52,7 @@ describe('Error display', () => { expect($('.statusMessage').text()).to.equal('Internal Error'); // 2. Edit the file, fixing the error - let changeOccured = fixture.onNextChange(); await fixture.editFile('./src/components/SvelteSyntaxError.svelte', `

No mismatch

`); - await changeOccured; // 3. Verify that the file is fixed. html = await fixture.fetch('/svelte-syntax-error').then((res) => res.text()); diff --git a/packages/astro/test/test-utils.js b/packages/astro/test/test-utils.js index bbdd86b57..8fd5393c0 100644 --- a/packages/astro/test/test-utils.js +++ b/packages/astro/test/test-utils.js @@ -28,6 +28,7 @@ polyfill(globalThis, { * @property {(url: string) => string} resolveUrl * @property {(url: string, opts: any) => Promise} fetch * @property {(path: string) => Promise} readFile + * @property {(path: string, updater: (content: string) => string) => Promise} writeFile * @property {(path: string) => Promise} readdir * @property {() => Promise} startDevServer * @property {() => Promise} preview @@ -97,7 +98,7 @@ export async function loadFixture(inlineConfig) { const resolveUrl = (url) => `http://${'127.0.0.1'}:${config.server.port}${url.replace(/^\/?/, '/')}`; - + // A map of files that have been editted. let fileEdits = new Map(); @@ -108,6 +109,11 @@ export async function loadFixture(inlineConfig) { fileEdits.clear(); }; + const onNextChange = () => + devServer + ? new Promise((resolve) => devServer.watcher.once('change', resolve)) + : Promise.reject(new Error('No dev server running')) + // After each test, reset each of the edits to their original contents. if (typeof afterEach === 'function') { afterEach(resetAllFiles); @@ -134,7 +140,9 @@ export async function loadFixture(inlineConfig) { readFile: (filePath) => fs.promises.readFile(new URL(filePath.replace(/^\//, ''), config.outDir), 'utf8'), readdir: (fp) => fs.promises.readdir(new URL(fp.replace(/^\//, ''), config.outDir)), - clean: () => fs.promises.rm(config.outDir, { maxRetries: 10, recursive: true, force: true }), + clean: async () => { + await fs.promises.rm(config.outDir, { maxRetries: 10, recursive: true, force: true }); + }, loadTestAdapterApp: async () => { const url = new URL('./server/entry.mjs', config.outDir); const { createApp, manifest } = await import(url); @@ -142,22 +150,26 @@ export async function loadFixture(inlineConfig) { app.manifest = manifest; return app; }, - editFile: async (filePath, newContents) => { + editFile: async (filePath, newContentsOrCallback) => { const fileUrl = new URL(filePath.replace(/^\//, ''), config.root); const contents = await fs.promises.readFile(fileUrl, 'utf-8'); - const reset = () => fs.writeFileSync(fileUrl, contents); + const reset = () => { + fs.writeFileSync(fileUrl, contents); + } // Only save this reset if not already in the map, in case multiple edits happen // to the same file. if (!fileEdits.has(fileUrl.toString())) { fileEdits.set(fileUrl.toString(), reset); } + const newContents = typeof newContentsOrCallback === 'function' + ? newContentsOrCallback(contents) + : newContentsOrCallback; + const nextChange = onNextChange(); await fs.promises.writeFile(fileUrl, newContents); + await nextChange; return reset; }, - onNextChange: () => - devServer - ? new Promise((resolve) => devServer.watcher.once('change', resolve)) - : Promise.reject(new Error('No dev server running')), + resetAllFiles }; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index efaf70f05..3ef4e7001 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -661,12 +661,108 @@ importers: chai-as-promised: 7.1.1_chai@4.3.6 mocha: 9.2.2 + packages/astro/e2e/fixtures/astro-component: + specifiers: + astro: workspace:* + dependencies: + astro: link:../../.. + + packages/astro/e2e/fixtures/lit-component: + specifiers: + '@astrojs/lit': workspace:* + '@webcomponents/template-shadowroot': ^0.1.0 + astro: workspace:* + lit: ^2.2.3 + dependencies: + '@astrojs/lit': link:../../../../integrations/lit + '@webcomponents/template-shadowroot': 0.1.0 + astro: link:../../.. + lit: 2.2.4 + + packages/astro/e2e/fixtures/multiple-frameworks: + specifiers: + '@astrojs/lit': ^0.1.3 + '@astrojs/preact': ^0.1.2 + '@astrojs/react': ^0.1.2 + '@astrojs/solid-js': ^0.1.2 + '@astrojs/svelte': ^0.1.3 + '@astrojs/vue': ^0.1.4 + '@webcomponents/template-shadowroot': ^0.1.0 + astro: ^1.0.0-beta.31 + lit: ^2.2.4 + preact: ^10.7.2 + react: ^18.1.0 + react-dom: ^18.1.0 + solid-js: ^1.4.2 + svelte: ^3.48.0 + vue: ^3.2.34 + dependencies: + '@webcomponents/template-shadowroot': 0.1.0 + lit: 2.2.4 + preact: 10.7.2 + react: 18.1.0 + react-dom: 18.1.0_react@18.1.0 + solid-js: 1.4.2 + svelte: 3.48.0 + vue: 3.2.34 + devDependencies: + '@astrojs/lit': link:../../../../integrations/lit + '@astrojs/preact': link:../../../../integrations/preact + '@astrojs/react': link:../../../../integrations/react + '@astrojs/solid-js': link:../../../../integrations/solid + '@astrojs/svelte': link:../../../../integrations/svelte + '@astrojs/vue': link:../../../../integrations/vue + astro: link:../../.. + packages/astro/e2e/fixtures/nested-styles: specifiers: astro: workspace:* dependencies: astro: link:../../.. + packages/astro/e2e/fixtures/preact-component: + specifiers: + '@astrojs/preact': workspace:* + astro: workspace:* + preact: ^10.7.2 + dependencies: + '@astrojs/preact': link:../../../../integrations/preact + astro: link:../../.. + preact: 10.7.2 + + packages/astro/e2e/fixtures/react-component: + specifiers: + '@astrojs/react': workspace:* + astro: workspace:* + react: ^18.1.0 + react-dom: ^18.1.0 + dependencies: + '@astrojs/react': link:../../../../integrations/react + astro: link:../../.. + react: 18.1.0 + react-dom: 18.1.0_react@18.1.0 + + packages/astro/e2e/fixtures/solid-component: + specifiers: + '@astrojs/solid-js': workspace:* + astro: workspace:* + solid-js: ^1.4.1 + dependencies: + '@astrojs/solid-js': link:../../../../integrations/solid + astro: link:../../.. + devDependencies: + solid-js: 1.4.2 + + packages/astro/e2e/fixtures/svelte-component: + specifiers: + '@astrojs/svelte': workspace:* + astro: workspace:* + svelte: ^3.48.0 + dependencies: + '@astrojs/svelte': link:../../../../integrations/svelte + astro: link:../../.. + svelte: 3.48.0 + packages/astro/e2e/fixtures/tailwindcss: specifiers: '@astrojs/tailwind': workspace:* @@ -675,6 +771,14 @@ importers: '@astrojs/tailwind': link:../../../../integrations/tailwind astro: link:../../.. + packages/astro/e2e/fixtures/vue-component: + specifiers: + '@astrojs/vue': workspace:* + astro: workspace:* + dependencies: + '@astrojs/vue': link:../../../../integrations/vue + astro: link:../../.. + packages/astro/test/fixtures/0-css: specifiers: '@astrojs/react': workspace:* @@ -1972,7 +2076,7 @@ packages: resolution: {integrity: sha512-rgi3g078uAxdb8jg1A5U8sNWMUQq7UXwHT7qmPiGOeB+h5p+tzUFy/Awq2suv99Tq8efpn3HrAGTuDvxyvbwfg==} dependencies: svelte: 3.48.0 - svelte2tsx: 0.5.10_wwvk7nlptlrqo2czohjtk6eiqm + svelte2tsx: 0.5.9_wwvk7nlptlrqo2czohjtk6eiqm transitivePeerDependencies: - typescript dev: false @@ -3725,7 +3829,7 @@ packages: dependencies: '@lit-labs/ssr-client': 1.0.1 '@lit/reactive-element': 1.3.2 - '@types/node': 16.11.36 + '@types/node': 16.11.34 lit: 2.2.4 lit-element: 3.2.0 lit-html: 2.2.4 @@ -3748,7 +3852,7 @@ packages: resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} dependencies: '@babel/runtime': 7.18.0 - '@types/node': 12.20.52 + '@types/node': 12.20.51 find-up: 4.1.0 fs-extra: 8.1.0 dev: true @@ -6032,7 +6136,7 @@ packages: slash: 3.0.0 dev: true - /@rollup/plugin-babel/5.3.1_ykg7cmcqpmn5fbkb5gxs7i3du4: + /@rollup/plugin-babel/5.3.1_3gvlzenj6qraw2ojvkgevxalie: resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==} engines: {node: '>= 10.0.0'} peerDependencies: @@ -6047,8 +6151,8 @@ packages: dependencies: '@babel/core': 7.18.0 '@babel/helper-module-imports': 7.16.7 - '@rollup/pluginutils': 3.1.0_rollup@2.74.1 - rollup: 2.74.1 + '@rollup/pluginutils': 3.1.0_rollup@2.72.1 + rollup: 2.72.1 dev: true /@rollup/plugin-inject/4.0.4_rollup@2.74.1: @@ -6062,19 +6166,19 @@ packages: rollup: 2.74.1 dev: true - /@rollup/plugin-node-resolve/11.2.1_rollup@2.74.1: + /@rollup/plugin-node-resolve/11.2.1_rollup@2.72.1: resolution: {integrity: sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==} engines: {node: '>= 10.0.0'} peerDependencies: rollup: ^1.20.0||^2.0.0 dependencies: - '@rollup/pluginutils': 3.1.0_rollup@2.74.1 + '@rollup/pluginutils': 3.1.0_rollup@2.72.1 '@types/resolve': 1.17.1 builtin-modules: 3.3.0 deepmerge: 4.2.2 is-module: 1.0.0 resolve: 1.22.0 - rollup: 2.74.1 + rollup: 2.72.1 dev: true /@rollup/plugin-node-resolve/13.3.0_rollup@2.74.1: @@ -6092,14 +6196,14 @@ packages: rollup: 2.74.1 dev: true - /@rollup/plugin-replace/2.4.2_rollup@2.74.1: + /@rollup/plugin-replace/2.4.2_rollup@2.72.1: resolution: {integrity: sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==} peerDependencies: rollup: ^1.20.0 || ^2.0.0 dependencies: - '@rollup/pluginutils': 3.1.0_rollup@2.74.1 + '@rollup/pluginutils': 3.1.0_rollup@2.72.1 magic-string: 0.25.9 - rollup: 2.74.1 + rollup: 2.72.1 dev: true /@rollup/plugin-typescript/8.3.2_ewnwotriipvq7wps276zlnnxuy: @@ -6117,6 +6221,18 @@ packages: typescript: 4.6.4 dev: true + /@rollup/pluginutils/3.1.0_rollup@2.72.1: + resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} + engines: {node: '>= 8.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0 + dependencies: + '@types/estree': 0.0.39 + estree-walker: 1.0.1 + picomatch: 2.3.1 + rollup: 2.72.1 + dev: true + /@rollup/pluginutils/3.1.0_rollup@2.74.1: resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} engines: {node: '>= 8.0.0'} @@ -6255,7 +6371,7 @@ packages: /@types/connect/3.4.35: resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==} dependencies: - '@types/node': 17.0.35 + '@types/node': 17.0.32 dev: true /@types/debug/4.1.7: @@ -6296,7 +6412,7 @@ packages: resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} dependencies: '@types/minimatch': 3.0.5 - '@types/node': 17.0.35 + '@types/node': 17.0.32 dev: true /@types/hast/2.3.4: @@ -6360,20 +6476,20 @@ packages: '@types/unist': 2.0.6 dev: false - /@types/node/12.20.52: - resolution: {integrity: sha512-cfkwWw72849SNYp3Zx0IcIs25vABmFh73xicxhCkTcvtZQeIez15PpwQN8fY3RD7gv1Wrxlc9MEtfMORZDEsGw==} + /@types/node/12.20.51: + resolution: {integrity: sha512-anVDMfReTatfH8GVmHmaTZOL0jeTLNZ9wK9SSrQS3tMmn4vUc+9fVWlUzAieuQefWDyWUz4Z3aqXxDgO1VsYjg==} dev: true /@types/node/14.18.18: resolution: {integrity: sha512-B9EoJFjhqcQ9OmQrNorItO+OwEOORNn3S31WuiHvZY/dm9ajkB7AKD/8toessEtHHNL+58jofbq7hMMY9v4yig==} dev: true - /@types/node/16.11.36: - resolution: {integrity: sha512-FR5QJe+TaoZ2GsMHkjuwoNabr+UrJNRr2HNOo+r/7vhcuntM6Ee/pRPOnRhhL2XE9OOvX9VLEq+BcXl3VjNoWA==} + /@types/node/16.11.34: + resolution: {integrity: sha512-UrWGDyLAlQ2Z8bNOGWTsqbP9ZcBeTYBVuTRNxXTztBy5KhWUFI3BaeDWoCP/CzV/EVGgO1NTYzv9ZytBI9GAEw==} dev: false - /@types/node/17.0.35: - resolution: {integrity: sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg==} + /@types/node/17.0.32: + resolution: {integrity: sha512-eAIcfAvhf/BkHcf4pkLJ7ECpBAhh9kcxRBpip9cTiO+hf+aJrsxYxBeS6OXvOd9WqNAJmavXVpZvY1rBjNsXmw==} /@types/normalize-package-data/2.4.1: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} @@ -6397,7 +6513,7 @@ packages: /@types/prompts/2.0.14: resolution: {integrity: sha512-HZBd99fKxRWpYCErtm2/yxUZv6/PBI9J7N4TNFffl5JbrYMHBwF25DjQGTW3b3jmXq+9P6/8fCIb2ee57BFfYA==} dependencies: - '@types/node': 17.0.35 + '@types/node': 17.0.32 dev: false /@types/prop-types/15.7.5: @@ -6437,7 +6553,7 @@ packages: /@types/resolve/1.17.1: resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} dependencies: - '@types/node': 14.18.18 + '@types/node': 17.0.32 dev: true /@types/resolve/1.20.2: @@ -6447,19 +6563,19 @@ packages: resolution: {integrity: sha512-F3OznnSLAUxFrCEu/L5PY8+ny8DtcFRjx7fZZ9bycvXRi3KPTRS9HOitGZwvPg0juRhXFWIeKX58cnX5YqLohQ==} dependencies: '@types/glob': 7.2.0 - '@types/node': 17.0.35 + '@types/node': 17.0.32 dev: true /@types/sass/1.43.1: resolution: {integrity: sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==} dependencies: - '@types/node': 17.0.35 + '@types/node': 17.0.32 dev: false /@types/sax/1.2.4: resolution: {integrity: sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw==} dependencies: - '@types/node': 17.0.35 + '@types/node': 17.0.32 dev: false /@types/scheduler/0.16.2: @@ -6473,7 +6589,7 @@ packages: resolution: {integrity: sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==} dependencies: '@types/mime': 1.3.2 - '@types/node': 17.0.35 + '@types/node': 17.0.32 dev: true /@types/tailwindcss/3.0.10: @@ -6726,7 +6842,7 @@ packages: acorn: 8.7.1 bindings: 1.5.0 estree-walker: 2.0.2 - glob: 7.2.3 + glob: 7.2.0 graceful-fs: 4.2.10 micromatch: 4.0.5 node-gyp-build: 4.4.0 @@ -6974,13 +7090,8 @@ packages: engines: {node: '>=6'} dev: true - /ansi-colors/4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} - dev: true - /ansi-regex/2.1.1: - resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} + resolution: {integrity: sha1-w7M6te42DYbg5ijwRorn7yfWVN8=} engines: {node: '>=0.10.0'} /ansi-regex/5.0.1: @@ -7064,7 +7175,7 @@ packages: dev: false /arrify/1.0.1: - resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} + resolution: {integrity: sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=} engines: {node: '>=0.10.0'} dev: true @@ -7112,7 +7223,7 @@ packages: postcss: ^8.1.0 dependencies: browserslist: 4.20.3 - caniuse-lite: 1.0.30001341 + caniuse-lite: 1.0.30001340 fraction.js: 4.2.0 normalize-range: 0.1.2 picocolors: 1.0.0 @@ -7244,7 +7355,7 @@ packages: dev: false /boolbase/1.0.0: - resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + resolution: {integrity: sha1-aN/1++YMUes3cl6p4+0xDcwed24=} /boxen/6.2.1: resolution: {integrity: sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw==} @@ -7293,14 +7404,14 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001341 + caniuse-lite: 1.0.30001340 electron-to-chromium: 1.4.137 escalade: 3.1.1 node-releases: 2.0.4 picocolors: 1.0.0 /buffer-crc32/0.2.13: - resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + resolution: {integrity: sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=} dev: false /buffer-from/1.1.2: @@ -7369,8 +7480,8 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} - /caniuse-lite/1.0.30001341: - resolution: {integrity: sha512-2SodVrFFtvGENGCv0ChVJIDQ0KPaS1cg7/qtfMaICgeMolDdo/Z2OD32F0Aq9yl6F4YFwGPBS5AaPqNYiW4PoA==} + /caniuse-lite/1.0.30001340: + resolution: {integrity: sha512-jUNz+a9blQTQVu4uFcn17uAD8IDizPzQkIKh3LCJfg9BkyIqExYYdyc/ZSlWUSKb8iYiXxKsxbv4zYSvkqjrxw==} /canvas-confetti/1.5.1: resolution: {integrity: sha512-Ncz+oZJP6OvY7ti4E1slxVlyAV/3g7H7oQtcCDXgwGgARxPnwYY9PW5Oe+I8uvspYNtuHviAdgA0LfcKFWJfpg==} @@ -7451,7 +7562,7 @@ packages: dev: true /check-error/1.0.2: - resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} + resolution: {integrity: sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=} dev: true /cheerio-select/1.6.0: @@ -8037,7 +8148,7 @@ packages: resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==} engines: {node: '>=8.6'} dependencies: - ansi-colors: 4.1.3 + ansi-colors: 4.1.1 dev: true /entities/2.2.0: @@ -8682,10 +8793,8 @@ packages: resolution: {integrity: sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==} dev: true - /for-each/0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - dependencies: - is-callable: 1.2.4 + /foreach/2.0.6: + resolution: {integrity: sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg==} dev: false /formdata-polyfill/4.0.10: @@ -8883,17 +8992,6 @@ packages: minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 - dev: true - - /glob/7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 /globals/11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} @@ -9563,14 +9661,14 @@ packages: dependencies: has-symbols: 1.0.3 - /is-typed-array/1.1.9: - resolution: {integrity: sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==} + /is-typed-array/1.1.8: + resolution: {integrity: sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA==} engines: {node: '>= 0.4'} dependencies: available-typed-arrays: 1.0.5 call-bind: 1.0.2 es-abstract: 1.20.1 - for-each: 0.3.3 + foreach: 2.0.6 has-tostringtag: 1.0.0 dev: false @@ -9625,7 +9723,7 @@ packages: resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 17.0.35 + '@types/node': 17.0.32 merge-stream: 2.0.0 supports-color: 7.2.0 dev: true @@ -11711,13 +11809,25 @@ packages: resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} hasBin: true dependencies: - glob: 7.2.3 + glob: 7.2.0 /rimraf/3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} hasBin: true dependencies: - glob: 7.2.3 + glob: 7.2.0 + + /rollup-plugin-terser/7.0.2_rollup@2.72.1: + resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==} + peerDependencies: + rollup: ^2.0.0 + dependencies: + '@babel/code-frame': 7.16.7 + jest-worker: 26.6.2 + rollup: 2.72.1 + serialize-javascript: 4.0.0 + terser: 5.13.1 + dev: true /rollup-plugin-terser/7.0.2_rollup@2.74.1: resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==} @@ -11737,6 +11847,14 @@ packages: estree-walker: 0.6.1 dev: false + /rollup/2.72.1: + resolution: {integrity: sha512-NTc5UGy/NWFGpSqF1lFY8z9Adri6uhyMLI6LvPAXdBKoPRFhIIiBUpt+Qg2awixqO3xvzSijjhnb4+QEZwJmxA==} + engines: {node: '>=10.0.0'} + hasBin: true + optionalDependencies: + fsevents: 2.3.2 + dev: true + /rollup/2.74.1: resolution: {integrity: sha512-K2zW7kV8Voua5eGkbnBtWYfMIhYhT9Pel2uhBk2WO5eMee161nPze/XRfvEQPFYz7KgrCCnmh2Wy0AMFLGGmMA==} engines: {node: '>=10.0.0'} @@ -11955,7 +12073,7 @@ packages: engines: {node: '>=12.0.0', npm: '>=5.6.0'} hasBin: true dependencies: - '@types/node': 17.0.35 + '@types/node': 17.0.32 '@types/sax': 1.2.4 arg: 5.0.1 sax: 1.2.4 @@ -12012,6 +12130,10 @@ packages: smart-buffer: 4.2.0 dev: true + /solid-js/1.3.17: + resolution: {integrity: sha512-BFCosxa4hRm+LF7S+kBL5bNr4RtuZif6AaR5FdQkBpV1E6QNLAOFm4HWgEN8vL2aCWEKl384cT8Etw8ziW8aag==} + dev: false + /solid-js/1.4.2: resolution: {integrity: sha512-IU5yKuT8P/n5F5g8j1rTXqxUdPYmoZDk/074TG94AEYf/nyXAeG82BSge4/lLIbCfUcnGUJ6DRdebIjujOAYyg==} @@ -12019,7 +12141,7 @@ packages: resolution: {integrity: sha512-iwbgdBzQSxBKoxkzaZgC9MGGUsHWJ74at9i7FF0naoqtwGuKdLYOgOJ9QRlA353DHDS/ttH2e0SRS6s3gz8NLQ==} dependencies: nanostores: 0.5.12 - solid-js: 1.4.2 + solid-js: 1.3.17 dev: false /sorcery/0.10.0: @@ -12364,8 +12486,8 @@ packages: resolution: {integrity: sha512-fN2YRm/bGumvjUpu6yI3BpvZnpIm9I6A7HR4oUNYd7ggYyIwSA/BX7DJ+UXXffLp6XNcUijyLvttbPVCYa/3xQ==} engines: {node: '>= 8'} - /svelte2tsx/0.5.10_wwvk7nlptlrqo2czohjtk6eiqm: - resolution: {integrity: sha512-nokQ0HTTWMcNX6tLrDLiOmJCuqjKZU9nCZ6/mVuCL3nusXdbp+9nv69VG2pCy7uQC66kV4Ls+j0WfvvJuGVnkg==} + /svelte2tsx/0.5.9_wwvk7nlptlrqo2czohjtk6eiqm: + resolution: {integrity: sha512-xTDASjlh+rKo4QRhTRYSH87sS7fRoyX67xhGIMPKa3FYqftRHRmMes6nVgEskiuhBovslNHYYpMMg5YM5n/STg==} peerDependencies: svelte: ^3.24 typescript: ^4.1.2 @@ -12989,9 +13111,9 @@ packages: inherits: 2.0.4 is-arguments: 1.1.1 is-generator-function: 1.0.10 - is-typed-array: 1.1.9 + is-typed-array: 1.1.8 safe-buffer: 5.2.1 - which-typed-array: 1.1.8 + which-typed-array: 1.1.7 dev: false /uvu/0.5.3: @@ -13056,7 +13178,7 @@ packages: debug: 4.3.4 fast-glob: 3.2.11 pretty-bytes: 5.6.0 - rollup: 2.74.1 + rollup: 2.72.1 workbox-build: 6.5.3 workbox-window: 6.5.3 transitivePeerDependencies: @@ -13266,16 +13388,16 @@ packages: load-yaml-file: 0.2.0 path-exists: 4.0.0 - /which-typed-array/1.1.8: - resolution: {integrity: sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==} + /which-typed-array/1.1.7: + resolution: {integrity: sha512-vjxaB4nfDqwKI0ws7wZpxIlde1XrLX5uB0ZjpfshgmapJMD7jJWhZI+yToJTqaFByF0eNBcYxbjmCzoRP7CfEw==} engines: {node: '>= 0.4'} dependencies: available-typed-arrays: 1.0.5 call-bind: 1.0.2 es-abstract: 1.20.1 - for-each: 0.3.3 + foreach: 2.0.6 has-tostringtag: 1.0.0 - is-typed-array: 1.1.9 + is-typed-array: 1.1.8 dev: false /which/1.3.1: @@ -13330,19 +13452,19 @@ packages: '@babel/core': 7.18.0 '@babel/preset-env': 7.18.0_@babel+core@7.18.0 '@babel/runtime': 7.18.0 - '@rollup/plugin-babel': 5.3.1_ykg7cmcqpmn5fbkb5gxs7i3du4 - '@rollup/plugin-node-resolve': 11.2.1_rollup@2.74.1 - '@rollup/plugin-replace': 2.4.2_rollup@2.74.1 + '@rollup/plugin-babel': 5.3.1_3gvlzenj6qraw2ojvkgevxalie + '@rollup/plugin-node-resolve': 11.2.1_rollup@2.72.1 + '@rollup/plugin-replace': 2.4.2_rollup@2.72.1 '@surma/rollup-plugin-off-main-thread': 2.2.3 ajv: 8.11.0 common-tags: 1.8.2 fast-json-stable-stringify: 2.1.0 fs-extra: 9.1.0 - glob: 7.2.3 + glob: 7.2.0 lodash: 4.17.21 pretty-bytes: 5.6.0 - rollup: 2.74.1 - rollup-plugin-terser: 7.0.2_rollup@2.74.1 + rollup: 2.72.1 + rollup-plugin-terser: 7.0.2_rollup@2.72.1 source-map: 0.8.0-beta.0 stringify-object: 3.3.0 strip-comments: 2.0.1