-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: add new suite for inlineStylesheets configuration
- Loading branch information
Showing
8 changed files
with
467 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,285 @@ | ||
import { expect } from 'chai'; | ||
import * as cheerio from 'cheerio'; | ||
import { loadFixture } from './test-utils.js'; | ||
import testAdapter from './test-adapter.js'; | ||
|
||
describe('Setting inlineStylesheets to never in static output', () => { | ||
let fixture; | ||
|
||
before(async () => { | ||
fixture = await loadFixture({ | ||
root: './fixtures/css-inline-stylesheets/', | ||
output: 'static', | ||
experimental: { | ||
inlineStylesheets: 'never', | ||
}, | ||
}); | ||
await fixture.build(); | ||
}); | ||
|
||
it('Does not render any <style> tags', async () => { | ||
const html = await fixture.readFile('/index.html'); | ||
const $ = cheerio.load(html); | ||
|
||
expect($('style').toArray()).to.be.empty; | ||
}); | ||
|
||
describe('Inspect linked stylesheets', () => { | ||
// object, so it can be passed by reference | ||
const allStyles = {}; | ||
|
||
before(async () => { | ||
allStyles.value = await stylesFromStaticOutput(fixture); | ||
}); | ||
|
||
commonExpectations(allStyles); | ||
}); | ||
}); | ||
|
||
describe('Setting inlineStylesheets to never in server output', () => { | ||
let app; | ||
|
||
before(async () => { | ||
const fixture = await loadFixture({ | ||
root: './fixtures/css-inline-stylesheets/', | ||
output: 'server', | ||
adapter: testAdapter(), | ||
experimental: { | ||
inlineStylesheets: 'never', | ||
}, | ||
}); | ||
await fixture.build(); | ||
app = await fixture.loadTestAdapterApp(); | ||
}); | ||
|
||
it('Does not render any <style> tags', async () => { | ||
const request = new Request('http://example.com/'); | ||
const response = await app.render(request); | ||
const html = await response.text(); | ||
const $ = cheerio.load(html); | ||
|
||
expect($('style').toArray()).to.be.empty; | ||
}); | ||
|
||
describe('Inspect linked stylesheets', () => { | ||
const allStyles = {}; | ||
|
||
before(async () => { | ||
allStyles.value = await stylesFromServer(app); | ||
}); | ||
|
||
commonExpectations(allStyles); | ||
}); | ||
}); | ||
|
||
describe('Setting inlineStylesheets to auto in static output', () => { | ||
let fixture; | ||
|
||
before(async () => { | ||
fixture = await loadFixture({ | ||
root: './fixtures/css-inline-stylesheets/', | ||
output: 'static', | ||
experimental: { | ||
inlineStylesheets: 'auto', | ||
}, | ||
vite: { | ||
build: { | ||
assetsInlineLimit: 512, | ||
}, | ||
}, | ||
}); | ||
await fixture.build(); | ||
}); | ||
|
||
it('Renders some <style> and some <link> tags', async () => { | ||
const html = await fixture.readFile('/index.html'); | ||
const $ = cheerio.load(html); | ||
|
||
// the count of style/link tags depends on our css chunking logic | ||
// this test should be updated if it changes | ||
expect($('style')).to.have.lengthOf(3); | ||
expect($('link[rel=stylesheet]')).to.have.lengthOf(1); | ||
}); | ||
|
||
describe('Inspect linked and inlined stylesheets', () => { | ||
const allStyles = {}; | ||
|
||
before(async () => { | ||
allStyles.value = await stylesFromStaticOutput(fixture); | ||
}); | ||
|
||
commonExpectations(allStyles); | ||
}); | ||
}); | ||
|
||
describe('Setting inlineStylesheets to auto in server output', () => { | ||
let app; | ||
|
||
before(async () => { | ||
const fixture = await loadFixture({ | ||
root: './fixtures/css-inline-stylesheets/', | ||
output: 'server', | ||
adapter: testAdapter(), | ||
experimental: { | ||
inlineStylesheets: 'auto', | ||
}, | ||
vite: { | ||
build: { | ||
assetsInlineLimit: 512, | ||
}, | ||
}, | ||
}); | ||
await fixture.build(); | ||
app = await fixture.loadTestAdapterApp(); | ||
}); | ||
|
||
it('Renders some <style> and some <link> tags', async () => { | ||
const request = new Request('http://example.com/'); | ||
const response = await app.render(request); | ||
const html = await response.text(); | ||
const $ = cheerio.load(html); | ||
|
||
// the count of style/link tags depends on our css chunking logic | ||
// this test should be updated if it changes | ||
expect($('style')).to.have.lengthOf(3); | ||
expect($('link[rel=stylesheet]')).to.have.lengthOf(1); | ||
}); | ||
|
||
describe('Inspect linked and inlined stylesheets', () => { | ||
const allStyles = {}; | ||
|
||
before(async () => { | ||
allStyles.value = await stylesFromServer(app); | ||
}); | ||
|
||
commonExpectations(allStyles); | ||
}); | ||
}); | ||
|
||
describe('Setting inlineStylesheets to always in static output', () => { | ||
let fixture; | ||
|
||
before(async () => { | ||
fixture = await loadFixture({ | ||
root: './fixtures/css-inline-stylesheets/', | ||
output: 'static', | ||
experimental: { | ||
inlineStylesheets: 'always', | ||
}, | ||
}); | ||
await fixture.build(); | ||
}); | ||
|
||
it('Does not render any <link> tags', async () => { | ||
const html = await fixture.readFile('/index.html'); | ||
const $ = cheerio.load(html); | ||
|
||
expect($('link[rel=stylesheet]').toArray()).to.be.empty; | ||
}); | ||
|
||
describe('Inspect inlined stylesheets', () => { | ||
const allStyles = {}; | ||
|
||
before(async () => { | ||
allStyles.value = await stylesFromStaticOutput(fixture); | ||
}); | ||
|
||
commonExpectations(allStyles); | ||
}); | ||
}); | ||
|
||
describe('Setting inlineStylesheets to always in server output', () => { | ||
let app; | ||
|
||
before(async () => { | ||
const fixture = await loadFixture({ | ||
root: './fixtures/css-inline-stylesheets/', | ||
output: 'server', | ||
adapter: testAdapter(), | ||
experimental: { | ||
inlineStylesheets: 'always', | ||
}, | ||
}); | ||
await fixture.build(); | ||
app = await fixture.loadTestAdapterApp(); | ||
}); | ||
|
||
it('Does not render any <link> tags', async () => { | ||
const request = new Request('http://example.com/'); | ||
const response = await app.render(request); | ||
const html = await response.text(); | ||
const $ = cheerio.load(html); | ||
|
||
expect($('link[rel=stylesheet]').toArray()).to.be.empty; | ||
}); | ||
|
||
describe('Inspect inlined stylesheets', () => { | ||
const allStyles = {}; | ||
|
||
before(async () => { | ||
allStyles.value = await stylesFromServer(app); | ||
}); | ||
|
||
commonExpectations(allStyles); | ||
}); | ||
}); | ||
|
||
async function stylesFromStaticOutput(fixture) { | ||
const html = await fixture.readFile('/index.html'); | ||
const $ = cheerio.load(html); | ||
|
||
const links = $('link[rel=stylesheet]'); | ||
const hrefs = links.map((_, linkEl) => linkEl.attribs.href).toArray(); | ||
const allLinkedStylesheets = await Promise.all(hrefs.map((href) => fixture.readFile(href))); | ||
const allLinkedStyles = allLinkedStylesheets.join(''); | ||
|
||
const styles = $('style'); | ||
const allInlinedStylesheets = styles.map((_, styleEl) => styleEl.children[0].data).toArray(); | ||
const allInlinedStyles = allInlinedStylesheets.join(''); | ||
|
||
return allLinkedStyles + allInlinedStyles; | ||
} | ||
|
||
async function stylesFromServer(app) { | ||
const request = new Request('http://example.com/'); | ||
const response = await app.render(request); | ||
const html = await response.text(); | ||
const $ = cheerio.load(html); | ||
|
||
const links = $('link[rel=stylesheet]'); | ||
const hrefs = links.map((_, linkEl) => linkEl.attribs.href).toArray(); | ||
const allLinkedStylesheets = await Promise.all( | ||
hrefs.map(async (href) => { | ||
const cssRequest = new Request(`http://example.com${href}`); | ||
const cssResponse = await app.render(cssRequest); | ||
return await cssResponse.text(); | ||
}) | ||
); | ||
const allLinkedStyles = allLinkedStylesheets.join(''); | ||
|
||
const styles = $('style'); | ||
const allInlinedStylesheets = styles.map((_, styleEl) => styleEl.children[0].data).toArray(); | ||
const allInlinedStyles = allInlinedStylesheets.join(''); | ||
return allLinkedStyles + allInlinedStyles; | ||
} | ||
|
||
function commonExpectations(allStyles) { | ||
it('Includes all authored css', () => { | ||
// authored in imported.css | ||
expect(allStyles.value).to.include('.bg-lightcoral'); | ||
|
||
// authored in index.astro | ||
expect(allStyles.value).to.include('#welcome'); | ||
|
||
// authored in components/Button.astro | ||
expect(allStyles.value).to.include('.variant-outline'); | ||
|
||
// authored in layouts/Layout.astro | ||
expect(allStyles.value).to.include('Menlo'); | ||
}); | ||
|
||
it('Styles used both in content layout and directly in page are included only once', () => { | ||
// authored in components/Button.astro | ||
expect(allStyles.value.match(/cubic-bezier/g)).to.have.lengthOf(1); | ||
}); | ||
} |
8 changes: 8 additions & 0 deletions
8
packages/astro/test/fixtures/css-inline-stylesheets/package.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"name": "@test/css-inline-stylesheets", | ||
"version": "0.0.0", | ||
"private": true, | ||
"dependencies": { | ||
"astro": "workspace:*" | ||
} | ||
} |
86 changes: 86 additions & 0 deletions
86
packages/astro/test/fixtures/css-inline-stylesheets/src/components/Button.astro
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
--- | ||
const { class: className = '', style, href } = Astro.props; | ||
const { variant = 'primary' } = Astro.props; | ||
--- | ||
|
||
<span class:list={[`link pixel variant-${variant}`, className]} > | ||
<a {href}> | ||
<span><slot /></span> | ||
</a> | ||
</span> | ||
|
||
<style> | ||
.link { | ||
--border-radius: 8; | ||
--duration: 200ms; | ||
--delay: 30ms; | ||
--background: linear-gradient(180deg, var(--link-color-stop-a), var(--link-color-stop-b)); | ||
display: flex; | ||
color: white; | ||
font-size: 1.25rem; | ||
width: max-content; | ||
} | ||
a { | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
padding: 0.67rem 1.25rem; | ||
width: 100%; | ||
height: 100%; | ||
text-decoration: none; | ||
color: inherit !important; | ||
/* Indicates the button boundaries for forced colors users in older browsers */ | ||
outline: 1px solid transparent; | ||
} | ||
|
||
@media (forced-colors: active) { | ||
a { | ||
border: 1px solid LinkText; | ||
} | ||
} | ||
|
||
a > :global(* + *) { | ||
margin-inline-start: 0.25rem; | ||
} | ||
|
||
.variant-primary { | ||
--variant: primary; | ||
--background: linear-gradient(180deg, var(--link-color-stop-a), var(--link-color-stop-b)); | ||
} | ||
.variant-primary:hover, | ||
.variant-primary:focus-within { | ||
--link-color-stop-a: #6d39ff; | ||
--link-color-stop-b: #af43ff; | ||
} | ||
.variant-primary:active { | ||
--link-color-stop-a: #5f31e1; | ||
--link-color-stop-b: #a740f3; | ||
} | ||
|
||
.variant-outline { | ||
--variant: outline; | ||
--background: none; | ||
color: var(--background); | ||
} | ||
.variant-outline > a::before { | ||
position: absolute; | ||
top: 0; | ||
right: calc(var(--pixel-size) * 1px); | ||
bottom: calc(var(--pixel-size) * 1px); | ||
left: calc(var(--pixel-size) * 1px); | ||
content: ''; | ||
display: block; | ||
transform-origin: bottom center; | ||
background: linear-gradient(to top, var(--background), rgba(255, 255, 255, 0)); | ||
opacity: 0.3; | ||
transform: scaleY(0); | ||
transition: transform 200ms cubic-bezier(0.22, 1, 0.36, 1); | ||
} | ||
.variant-outline:hover > a::before, | ||
.variant-outline:focus-within > a::before { | ||
transform: scaleY(1); | ||
} | ||
.variant-outline:active > a::before { | ||
transform: scaleY(1); | ||
} | ||
</style> |
15 changes: 15 additions & 0 deletions
15
packages/astro/test/fixtures/css-inline-stylesheets/src/content/en/endeavour.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--- | ||
title: Endeavour | ||
description: 'Learn about the Endeavour NASA space shuttle.' | ||
publishedDate: 'Sun Jul 11 2021 00:00:00 GMT-0400 (Eastern Daylight Time)' | ||
layout: '../../layouts/Layout.astro' | ||
tags: [space, 90s] | ||
--- | ||
|
||
**Source:** [Wikipedia](https://en.wikipedia.org/wiki/Space_Shuttle_Endeavour) | ||
|
||
Space Shuttle Endeavour (Orbiter Vehicle Designation: OV-105) is a retired orbiter from NASA's Space Shuttle program and the fifth and final operational Shuttle built. It embarked on its first mission, STS-49, in May 1992 and its 25th and final mission, STS-134, in May 2011. STS-134 was expected to be the final mission of the Space Shuttle program, but with the authorization of STS-135, Atlantis became the last shuttle to fly. | ||
|
||
The United States Congress approved the construction of Endeavour in 1987 to replace the Space Shuttle Challenger, which was destroyed in 1986. | ||
|
||
NASA chose, on cost grounds, to build much of Endeavour from spare parts rather than refitting the Space Shuttle Enterprise, and used structural spares built during the construction of Discovery and Atlantis in its assembly. |
Oops, something went wrong.