astro/packages/integrations/image/test/image-ssg.test.js
Tony Sullivan e8593e7ead
Adds an @astrojs/image integration for optimizing images (#3694)
* initial commit

* WIP: starting to define interfaces for images and transformers

* WIP: basic sharp service to test out the API setup

* adding a few tests for sharp.toImageSrc

* Adding tests for sharp.parseImageSrc

* hooking up basic SSR support

* updating image services to return width/height

* simplifying config setup for v1

* hooking up basic SSR + SSG support (dev & build)

* refactor: a bit of code cleanup and commenting

* WIP: migrating local files to ESM + vite plugin

* WIP: starting to hook up user-provided loaderEntryPoints

* chore: update lock file

* chore: update merged lockfile

* refactor: code cleanup and type docs

* pulling over the README template for first-party integrations

* moving metadata out to the loader

* updating the test for the refactored import

* revert: remove unrelated webapi formatting

* revert: remove unrelated change

* fixing up the existing sharp tests

* fix: vite plugin wasn't dynamically loading the image service properly

* refactor: minor API renaming, removing last hard-coded use of sharp loader

* don't manipulate src for hosted image services

* Adding support for automatically calculating dimensions by aspect ratio, if needed

* a few bug fixes + renaming the aspect ratio search param to "ar"

* Adding ETag support, removing need for loaders to parse file metadata

* using the battle tested `etag` package

* Adding support for dynamically calculating partial sizes

* refactor: moving to the packages/integrations dir, Astro Labs TBD later

* refactor: renaming parse/serialize functions

* Adding tests for SSG image optimizations

* refactor: clean up outdated names related to ImageProps

* nit: reusing cached SSG filename

* chore: update pnpm lock file

* handling file URLs when resolving local image imports

* updating image file resolution to use file URLs

* increasing test timeout for image build tests

* fixing eslint error in sharp test

* adding slash for windows compat in src URLs

* chore: update lockfile after merge

* Adding README content

* adding a readme call to action for configuration options

* review: A few of the quick updates from the PR review

* hack: adds a one-off check to allow query params for the _image route

* Adds support for src={import("...")}, and named component exports

* adding SSR tests

* nit: adding a bit more comments

* limiting the query params in SSG dev to the images integration
2022-07-01 15:47:48 +00:00

126 lines
3.6 KiB
JavaScript

import { expect } from 'chai';
import * as cheerio from 'cheerio';
import path from 'path';
import sizeOf from 'image-size';
import { loadFixture } from './test-utils.js';
let fixture;
describe('SSG images', function () {
before(async () => {
fixture = await loadFixture({ root: './fixtures/basic-image/' });
});
function verifyImage(pathname, expected) {
const dist = path.join('test/fixtures/basic-image/dist', pathname);
const result = sizeOf(dist);
expect(result).to.deep.equal(expected);
}
describe('build', () => {
let $;
let html;
before(async () => {
await fixture.build();
html = await fixture.readFile('/index.html');
$ = cheerio.load(html);
});
describe('Local images', () => {
it('includes src, width, and height attributes', () => {
const image = $('#social-jpg');
expect(image.attr('src')).to.equal('/_image/assets/social_506x253.jpg');
expect(image.attr('width')).to.equal('506');
expect(image.attr('height')).to.equal('253');
});
it('built the optimized image', () => {
verifyImage('_image/assets/social_506x253.jpg', { width: 506, height: 253, type: 'jpg' });
});
it('dist includes original image', () => {
verifyImage('assets/social.jpg', { width: 2024, height: 1012, type: 'jpg' });
});
});
describe('Remote images', () => {
it('includes src, width, and height attributes', () => {
const image = $('#google');
expect(image.attr('src')).to.equal('/_image/googlelogo_color_272x92dp_544x184.webp');
expect(image.attr('width')).to.equal('544');
expect(image.attr('height')).to.equal('184');
});
it('built the optimized image', () => {
verifyImage('_image/googlelogo_color_272x92dp_544x184.webp', { width: 544, height: 184, type: 'webp' });
});
});
});
describe('dev', () => {
let devServer;
let $;
before(async () => {
devServer = await fixture.startDevServer();
const html = await fixture.fetch('/').then((res) => res.text());
$ = cheerio.load(html);
});
after(async () => {
await devServer.stop();
});
describe('Local images', () => {
it('includes src, width, and height attributes', () => {
const image = $('#social-jpg');
const src = image.attr('src');
const [route, params] = src.split('?');
expect(route).to.equal('/_image');
const searchParams = new URLSearchParams(params);
expect(searchParams.get('f')).to.equal('jpg');
expect(searchParams.get('w')).to.equal('506');
expect(searchParams.get('h')).to.equal('253');
// TODO: possible to avoid encoding the full image path?
expect(searchParams.get('href').endsWith('/assets/social.jpg')).to.equal(true);
});
it('returns the optimized image', async () => {
const image = $('#social-jpg');
const res = await fixture.fetch(image.attr('src'));
expect(res.status).to.equal(200);
expect(res.headers.get('Content-Type')).to.equal('image/jpeg');
// TODO: verify image file? It looks like sizeOf doesn't support ArrayBuffers
});
});
describe('Remote images', () => {
it('includes src, width, and height attributes', () => {
const image = $('#google');
const src = image.attr('src');
const [route, params] = src.split('?');
expect(route).to.equal('/_image');
const searchParams = new URLSearchParams(params);
expect(searchParams.get('f')).to.equal('webp');
expect(searchParams.get('w')).to.equal('544');
expect(searchParams.get('h')).to.equal('184');
expect(searchParams.get('href')).to.equal('https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png');
});
});
});
});