diff --git a/packages/integrations/image/test/image-ssg.test.js b/packages/integrations/image/test/image-ssg.test.js index 3d3fc66e4..52daf8f5d 100644 --- a/packages/integrations/image/test/image-ssg.test.js +++ b/packages/integrations/image/test/image-ssg.test.js @@ -20,75 +20,50 @@ describe('SSG images - dev', function () { await devServer.stop(); }); - describe('Local images', () => { - it('includes attributes', () => { - const image = $('#social-jpg'); + [ + { + title: 'Local images', + id: '#social-jpg', + url: '/@astroimage/assets/social.jpg', + query: { f: 'jpg', w: '506', h: '253' } + }, + { + title: 'Inline imports', + id: '#inline', + url: '/@astroimage/assets/social.jpg', + query: { f: 'jpg', w: '506', h: '253' } + }, + { + title: 'Remote images', + id: '#google', + url: '/_image', + query: { + f: 'webp', + w: '544', + h: '184', + href: 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png' + } + }, + { + title: 'Public images', + id: '#hero', + url: '/_image', + query: { f: 'webp', w: '768', h: '414', href: '/hero.jpg' } + } + ].forEach(({ title, id, url, query }) => { + it(title, () => { + const image = $(id); const src = image.attr('src'); const [route, params] = src.split('?'); - expect(route).to.equal('/@astroimage/assets/social.jpg'); + expect(route).to.equal(url); 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'); - }); - }); - - describe('Local images with inline imports', () => { - it('includes attributes', () => { - const image = $('#inline'); - - const src = image.attr('src'); - const [route, params] = src.split('?'); - - expect(route).to.equal('/@astroimage/assets/social.jpg'); - - 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'); - }); - }); - - describe('Remote images', () => { - it('includes 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' - ); - }); - }); - - describe('/public images', () => { - it('includes attributes', () => { - const image = $('#hero'); - - const src = image.attr('src'); - const [route, params] = src.split('?'); - - expect(route).to.equal('/_image'); - - const searchParams = new URLSearchParams(params); - - expect(searchParams.get('href')).to.equal('/hero.jpg'); - expect(searchParams.get('f')).to.equal('webp'); - expect(searchParams.get('w')).to.equal('768'); - expect(searchParams.get('h')).to.equal('414'); + for (const [key, value] of Object.entries(query)) { + expect(searchParams.get(key)).to.equal(value); + } }); }); }); @@ -109,75 +84,50 @@ describe('SSG images with subpath - dev', function () { await devServer.stop(); }); - describe('Local images', () => { - it('includes attributes', () => { - const image = $('#social-jpg'); + [ + { + title: 'Local images', + id: '#social-jpg', + url: '/@astroimage/assets/social.jpg', + query: { f: 'jpg', w: '506', h: '253' } + }, + { + title: 'Inline imports', + id: '#inline', + url: '/@astroimage/assets/social.jpg', + query: { f: 'jpg', w: '506', h: '253' } + }, + { + title: 'Remote images', + id: '#google', + url: '/_image', + query: { + f: 'webp', + w: '544', + h: '184', + href: 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png' + } + }, + { + title: 'Public images', + id: '#hero', + url: '/_image', + query: { f: 'webp', w: '768', h: '414', href: '/hero.jpg' } + } + ].forEach(({ title, id, url, query }) => { + it(title, () => { + const image = $(id); const src = image.attr('src'); const [route, params] = src.split('?'); - expect(route).to.equal('/@astroimage/assets/social.jpg'); + expect(route).to.equal(url); 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'); - }); - }); - - describe('Local images with inline imports', () => { - it('includes attributes', () => { - const image = $('#inline'); - - const src = image.attr('src'); - const [route, params] = src.split('?'); - - expect(route).to.equal('/@astroimage/assets/social.jpg'); - - 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'); - }); - }); - - describe('Remote images', () => { - it('includes 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' - ); - }); - }); - - describe('/public images', () => { - it('includes attributes', () => { - const image = $('#hero'); - - const src = image.attr('src'); - const [route, params] = src.split('?'); - - expect(route).to.equal('/_image'); - - const searchParams = new URLSearchParams(params); - - expect(searchParams.get('href')).to.equal('/hero.jpg'); - expect(searchParams.get('f')).to.equal('webp'); - expect(searchParams.get('w')).to.equal('768'); - expect(searchParams.get('h')).to.equal('414'); + for (const [key, value] of Object.entries(query)) { + expect(searchParams.get(key)).to.equal(value); + } }); }); }); @@ -202,78 +152,42 @@ describe('SSG images - build', function () { expect(result).to.deep.equal(expected); } - describe('Local images', () => { - it('includes attributes', () => { - const image = $('#social-jpg'); + [ + { + title: 'Local images', + id: '#social-jpg', + regex: /^\/social.\w{8}_\w{4,10}.jpg/, + size: { width: 506, height: 253, type: 'jpg' } + }, + { + title: 'Inline imports', + id: '#inline', + regex: /^\/social.\w{8}_\w{4,10}.jpg/, + size: { width: 506, height: 253, type: 'jpg' } + }, + { + title: 'Remote images', + id: '#google', + regex: /^\/googlelogo_color_272x92dp_\w{4,10}.webp/, + size: { width: 544, height: 184, type: 'webp' } + }, + { + title: 'Public images', + id: '#hero', + regex: /^\/hero_\w{4,10}.webp/, + size: { width: 768, height: 414, type: 'webp' } + } + ].forEach(({ title, id, regex, size }) => { + it(title, () => { + const image = $(id); - expect(image.attr('src')).to.equal('/social.cece8c77_1zwatP.jpg'); - expect(image.attr('width')).to.equal('506'); - expect(image.attr('height')).to.equal('253'); - }); - - it('built the optimized image', () => { - verifyImage('social.cece8c77_1zwatP.jpg', { width: 506, height: 253, type: 'jpg' }); - }); - }); - - describe('Inline imports', () => { - it('includes attributes', () => { - const image = $('#inline'); - - expect(image.attr('src')).to.equal('/social.cece8c77_Z2tF99.jpg'); - expect(image.attr('width')).to.equal('506'); - expect(image.attr('height')).to.equal('253'); - }); - - it('built the optimized image', () => { - verifyImage('social.cece8c77_Z2tF99.jpg', { width: 506, height: 253, type: 'jpg' }); - }); - }); - - describe('Remote images', () => { - // Hard-coding in the test! These should never change since the hash is based - // on the static `src` string - const HASH = 'Z1RBHqs'; - const HASH_WITH_QUERY = 'Z17oujH'; - - it('includes attributes', () => { - const image = $('#google'); - - expect(image.attr('src')).to.equal(`/googlelogo_color_272x92dp_${HASH}.webp`); - expect(image.attr('width')).to.equal('544'); - expect(image.attr('height')).to.equal('184'); - }); - - it('built the optimized image', () => { - verifyImage(`/googlelogo_color_272x92dp_${HASH}.webp`, { - width: 544, - height: 184, - type: 'webp', - }); - }); - - it('removes query strings', () => { - verifyImage(`/googlelogo_color_272x92dp_${HASH_WITH_QUERY}.webp`, { - width: 544, - height: 184, - type: 'webp', - }); - }); - }); - - describe('/public images', () => { - it('includes attributes', () => { - const image = $('#hero'); - - expect(image.attr('src')).to.equal('/hero_Z2k1JGN.webp'); - expect(image.attr('width')).to.equal('768'); - expect(image.attr('height')).to.equal('414'); - }); - - it('built the optimized image', () => { - verifyImage('hero_Z2k1JGN.webp', { width: 768, height: 414, type: 'webp' }); - }); - }); + expect(image.attr('src')).to.match(regex); + expect(image.attr('width')).to.equal(size.width.toString()); + expect(image.attr('height')).to.equal(size.height.toString()); + + verifyImage(image.attr('src'), size); + }) + }) }); describe('SSG images with subpath - build', function () { @@ -296,76 +210,40 @@ describe('SSG images with subpath - build', function () { expect(result).to.deep.equal(expected); } - describe('Local images', () => { - it('includes attributes', () => { - const image = $('#social-jpg'); + [ + { + title: 'Local images', + id: '#social-jpg', + regex: /^\/docs\/social.\w{8}_\w{4,10}.jpg/, + size: { width: 506, height: 253, type: 'jpg' } + }, + { + title: 'Inline imports', + id: '#inline', + regex: /^\/docs\/social.\w{8}_\w{4,10}.jpg/, + size: { width: 506, height: 253, type: 'jpg' } + }, + { + title: 'Remote images', + id: '#google', + regex: /^\/docs\/googlelogo_color_272x92dp_\w{4,10}.webp/, + size: { width: 544, height: 184, type: 'webp' } + }, + { + title: 'Public images', + id: '#hero', + regex: /^\/docs\/hero_\w{4,10}.webp/, + size: { width: 768, height: 414, type: 'webp' } + } + ].forEach(({ title, id, regex, size }) => { + it(title, () => { + const image = $(id); - expect(image.attr('src')).to.equal('/docs/social.cece8c77_iK4oy.jpg'); - expect(image.attr('width')).to.equal('506'); - expect(image.attr('height')).to.equal('253'); - }); - - it('built the optimized image', () => { - verifyImage('social.cece8c77_iK4oy.jpg', { width: 506, height: 253, type: 'jpg' }); - }); - }); - - describe('Inline imports', () => { - it('includes attributes', () => { - const image = $('#inline'); - - expect(image.attr('src')).to.equal('/docs/social.cece8c77_1YIUw1.jpg'); - expect(image.attr('width')).to.equal('506'); - expect(image.attr('height')).to.equal('253'); - }); - - it('built the optimized image', () => { - verifyImage('social.cece8c77_1YIUw1.jpg', { width: 506, height: 253, type: 'jpg' }); - }); - }); - - describe('Remote images', () => { - // Hard-coding in the test! These should never change since the hash is based - // on the static `src` string - const HASH = 'Z1RBHqs'; - const HASH_WITH_QUERY = 'Z17oujH'; - - it('includes attributes', () => { - const image = $('#google'); - - expect(image.attr('src')).to.equal(`/docs/googlelogo_color_272x92dp_${HASH}.webp`); - expect(image.attr('width')).to.equal('544'); - expect(image.attr('height')).to.equal('184'); - }); - - it('built the optimized image', () => { - verifyImage(`/googlelogo_color_272x92dp_${HASH}.webp`, { - width: 544, - height: 184, - type: 'webp', - }); - }); - - it('removes query strings', () => { - verifyImage(`/googlelogo_color_272x92dp_${HASH_WITH_QUERY}.webp`, { - width: 544, - height: 184, - type: 'webp', - }); - }); - }); - - describe('/public images', () => { - it('includes attributes', () => { - const image = $('#hero'); - - expect(image.attr('src')).to.equal('/docs/hero_Z2k1JGN.webp'); - expect(image.attr('width')).to.equal('768'); - expect(image.attr('height')).to.equal('414'); - }); - - it('built the optimized image', () => { - verifyImage('hero_Z2k1JGN.webp', { width: 768, height: 414, type: 'webp' }); - }); + expect(image.attr('src')).to.match(regex); + expect(image.attr('width')).to.equal(size.width.toString()); + expect(image.attr('height')).to.equal(size.height.toString()); + + verifyImage(image.attr('src').replace('/docs', ''), size); + }) }); }); diff --git a/packages/integrations/image/test/image-ssr-build.test.js b/packages/integrations/image/test/image-ssr-build.test.js index 796843d8b..333b13f7b 100644 --- a/packages/integrations/image/test/image-ssr-build.test.js +++ b/packages/integrations/image/test/image-ssr-build.test.js @@ -3,7 +3,7 @@ import * as cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; import testAdapter from '../../../astro/test/test-adapter.js'; -describe('SSR images - build', function () { +describe('SSR images - build', async function () { let fixture; before(async () => { @@ -14,9 +14,50 @@ describe('SSR images - build', function () { }); await fixture.build(); }); - - describe('Local images', () => { - it('includes src, width, and height attributes', async () => { + + [ + { + title: 'Local images', + id: '#social-jpg', + url: '/_image', + query: { f: 'jpg', w: '506', h: '253', href: /^\/assets\/social.\w{8}.jpg/ } + }, + { + title: 'Inline imports', + id: '#inline', + url: '/_image', + query: { f: 'jpg', w: '506', h: '253', href: /^\/assets\/social.\w{8}.jpg/ } + }, + { + title: 'Remote images', + id: '#google', + url: '/_image', + query: { + f: 'webp', + w: '544', + h: '184', + href: 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png' + } + }, + { + title: 'Remote images with search', + id: '#query', + url: '/_image', + query: { + f: 'webp', + w: '544', + h: '184', + href: 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png?token=abc' + } + }, + { + title: 'Public images', + id: '#hero', + url: '/_image', + query: { f: 'webp', w: '768', h: '414', href: '/hero.jpg' } + } + ].forEach(({ title, id, url, query }) => { + it(title, async () => { const app = await fixture.loadTestAdapterApp(); const request = new Request('http://example.com/'); @@ -24,124 +65,22 @@ describe('SSR images - build', function () { const html = await response.text(); const $ = cheerio.load(html); - const image = $('#social-jpg'); + const image = $(id); const src = image.attr('src'); const [route, params] = src.split('?'); - expect(route).to.equal('/_image'); + expect(route).to.equal(url); 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')).to.equal('/assets/social.cece8c77.jpg'); - }); - }); - - describe('Inline imports', () => { - it('includes src, width, and height attributes', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - const image = $('#inline'); - - 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')).to.equal('/assets/social.cece8c77.jpg'); - }); - }); - - describe('Remote images', () => { - it('includes src, width, and height attributes', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - 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' - ); - }); - - it('keeps remote image query params', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - const image = $('#query'); - - 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?token=abc' - ); - }); - }); - - describe('/public images', () => { - it('includes src, width, and height attributes', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - const image = $('#hero'); - - 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('768'); - expect(searchParams.get('h')).to.equal('414'); - // TODO: possible to avoid encoding the full image path? - expect(searchParams.get('href')).to.equal('/hero.jpg'); + for (const [key, value] of Object.entries(query)) { + if (typeof value === 'string') { + expect(searchParams.get(key)).to.equal(value); + } else { + expect(searchParams.get(key)).to.match(value); + } + } }); }); }); @@ -159,8 +98,49 @@ describe('SSR images with subpath - build', function () { await fixture.build(); }); - describe('Local images', () => { - it('includes src, width, and height attributes', async () => { + [ + { + title: 'Local images', + id: '#social-jpg', + url: '/_image', + query: { f: 'jpg', w: '506', h: '253', href: /^\/docs\/assets\/social.\w{8}.jpg/ } + }, + { + title: 'Inline imports', + id: '#inline', + url: '/_image', + query: { f: 'jpg', w: '506', h: '253', href: /^\/docs\/assets\/social.\w{8}.jpg/ } + }, + { + title: 'Remote images', + id: '#google', + url: '/_image', + query: { + f: 'webp', + w: '544', + h: '184', + href: 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png' + } + }, + { + title: 'Remote images with search', + id: '#query', + url: '/_image', + query: { + f: 'webp', + w: '544', + h: '184', + href: 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png?token=abc' + } + }, + { + title: 'Public images', + id: '#hero', + url: '/_image', + query: { f: 'webp', w: '768', h: '414', href: '/hero.jpg' } + } + ].forEach(({ title, id, url, query }) => { + it(title, async () => { const app = await fixture.loadTestAdapterApp(); const request = new Request('http://example.com/'); @@ -168,124 +148,22 @@ describe('SSR images with subpath - build', function () { const html = await response.text(); const $ = cheerio.load(html); - const image = $('#social-jpg'); + const image = $(id); const src = image.attr('src'); const [route, params] = src.split('?'); - expect(route).to.equal('/_image'); + expect(route).to.equal(url); 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')).to.equal('/docs/assets/social.cece8c77.jpg'); - }); - }); - - describe('Inline imports', () => { - it('includes src, width, and height attributes', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - const image = $('#inline'); - - 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')).to.equal('/docs/assets/social.cece8c77.jpg'); - }); - }); - - describe('Remote images', () => { - it('includes src, width, and height attributes', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - 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' - ); - }); - - it('keeps remote image query params', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - const image = $('#query'); - - 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?token=abc' - ); - }); - }); - - describe('/public images', () => { - it('includes src, width, and height attributes', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - const image = $('#hero'); - - 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('768'); - expect(searchParams.get('h')).to.equal('414'); - // TODO: possible to avoid encoding the full image path? - expect(searchParams.get('href')).to.equal('/hero.jpg'); + for (const [key, value] of Object.entries(query)) { + if (typeof value === 'string') { + expect(searchParams.get(key)).to.equal(value); + } else { + expect(searchParams.get(key)).to.match(value); + } + } }); }); }); diff --git a/packages/integrations/image/test/image-ssr-dev.test.js b/packages/integrations/image/test/image-ssr-dev.test.js index 03f105106..b4d716e72 100644 --- a/packages/integrations/image/test/image-ssr-dev.test.js +++ b/packages/integrations/image/test/image-ssr-dev.test.js @@ -24,115 +24,64 @@ describe('SSR images - dev', function () { await devServer.stop(); }); - describe('Local images', () => { - it('includes src, width, and height attributes', () => { - const image = $('#social-jpg'); + [ + { + title: 'Local images', + id: '#social-jpg', + url: '/@astroimage/assets/social.jpg', + query: { f: 'jpg', w: '506', h: '253' }, + contentType: 'image/jpeg', + }, + { + title: 'Inline imports', + id: '#inline', + url: '/@astroimage/assets/social.jpg', + query: { f: 'jpg', w: '506', h: '253' }, + contentType: 'image/jpeg', + }, + { + title: 'Remote images', + id: '#google', + url: '/_image', + query: { + f: 'webp', + w: '544', + h: '184', + href: 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png' + }, + contentType: 'image/webp', + }, + { + title: 'Public images', + id: '#hero', + url: '/_image', + query: { + f: 'webp', + w: '768', + h: '414', + href: '/hero.jpg' + }, + contentType: 'image/webp', + } + ].forEach(({ title, id, url, query, contentType }) => { + it(title, async () => { + const image = $(id); const src = image.attr('src'); const [route, params] = src.split('?'); - expect(route).to.equal('/@astroimage/assets/social.jpg'); + expect(route).to.equal(url); 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'); - }); - - it('returns the optimized image', async () => { - const image = $('#social-jpg'); + for (const [key, value] of Object.entries(query)) { + expect(searchParams.get(key)).to.equal(value); + } 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('Inline imports', () => { - it('includes src, width, and height attributes', () => { - const image = $('#inline'); - - const src = image.attr('src'); - const [route, params] = src.split('?'); - - expect(route).to.equal('/@astroimage/assets/social.jpg'); - - 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'); - }); - }); - - 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' - ); - }); - - it('keeps remote image query params', () => { - const image = $('#query'); - - 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?token=abc' - ); - }); - }); - - describe('/public images', () => { - it('includes src, width, and height attributes', () => { - const image = $('#hero'); - - 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('768'); - expect(searchParams.get('h')).to.equal('414'); - expect(searchParams.get('href')).to.equal('/hero.jpg'); - }); - - it('returns the optimized image', async () => { - const image = $('#hero'); - - const res = await fixture.fetch(image.attr('src')); - - expect(res.status).to.equal(200); - expect(res.headers.get('Content-Type')).to.equal('image/webp'); - - // TODO: verify image file? It looks like sizeOf doesn't support ArrayBuffers + expect(res.headers.get('Content-Type')).to.equal(contentType); }); }); }); @@ -159,115 +108,64 @@ describe('SSR images with subpath - dev', function () { await devServer.stop(); }); - describe('Local images', () => { - it('includes src, width, and height attributes', () => { - const image = $('#social-jpg'); + [ + { + title: 'Local images', + id: '#social-jpg', + url: '/@astroimage/assets/social.jpg', + query: { f: 'jpg', w: '506', h: '253' }, + contentType: 'image/jpeg', + }, + { + title: 'Inline imports', + id: '#inline', + url: '/@astroimage/assets/social.jpg', + query: { f: 'jpg', w: '506', h: '253' }, + contentType: 'image/jpeg', + }, + { + title: 'Remote images', + id: '#google', + url: '/_image', + query: { + f: 'webp', + w: '544', + h: '184', + href: 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png' + }, + contentType: 'image/webp', + }, + { + title: 'Public images', + id: '#hero', + url: '/_image', + query: { + f: 'webp', + w: '768', + h: '414', + href: '/hero.jpg' + }, + contentType: 'image/webp', + } + ].forEach(({ title, id, url, query, contentType }) => { + it(title, async () => { + const image = $(id); const src = image.attr('src'); const [route, params] = src.split('?'); - expect(route).to.equal('/@astroimage/assets/social.jpg'); + expect(route).to.equal(url); 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'); - }); - - it('returns the optimized image', async () => { - const image = $('#social-jpg'); + for (const [key, value] of Object.entries(query)) { + expect(searchParams.get(key)).to.equal(value); + } 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('Inline imports', () => { - it('includes src, width, and height attributes', () => { - const image = $('#inline'); - - const src = image.attr('src'); - const [route, params] = src.split('?'); - - expect(route).to.equal('/@astroimage/assets/social.jpg'); - - 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'); - }); - }); - - 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' - ); - }); - - it('keeps remote image query params', () => { - const image = $('#query'); - - 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?token=abc' - ); - }); - }); - - describe('/public images', () => { - it('includes src, width, and height attributes', () => { - const image = $('#hero'); - - 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('768'); - expect(searchParams.get('h')).to.equal('414'); - expect(searchParams.get('href')).to.equal('/hero.jpg'); - }); - - it('returns the optimized image', async () => { - const image = $('#hero'); - - const res = await fixture.fetch(image.attr('src')); - - expect(res.status).to.equal(200); - expect(res.headers.get('Content-Type')).to.equal('image/webp'); - - // TODO: verify image file? It looks like sizeOf doesn't support ArrayBuffers + expect(res.headers.get('Content-Type')).to.equal(contentType); }); }); }); diff --git a/packages/integrations/image/test/picture-ssg.test.js b/packages/integrations/image/test/picture-ssg.test.js index 6b33212a5..1acb1a1b5 100644 --- a/packages/integrations/image/test/picture-ssg.test.js +++ b/packages/integrations/image/test/picture-ssg.test.js @@ -2,6 +2,7 @@ import { expect } from 'chai'; import * as cheerio from 'cheerio'; import fs from 'fs'; import sizeOf from 'image-size'; +import path from 'path'; import { fileURLToPath } from 'url'; import { loadFixture } from './test-utils.js'; @@ -21,110 +22,59 @@ describe('SSG pictures - dev', function () { await devServer.stop(); }); - describe('Local images', () => { - it('includes sources', () => { - const sources = $('#social-jpg source'); - + [ + { + title: 'Local images', + id: '#social-jpg', + url: '/@astroimage/assets/social.jpg', + query: { f: 'jpg', w: '506', h: '253' }, + alt: 'Social image' + }, + { + title: 'Inline imports', + id: '#inline', + url: '/@astroimage/assets/social.jpg', + query: { f: 'jpg', w: '506', h: '253' }, + alt: 'Inline social image' + }, + { + title: 'Remote images', + id: '#google', + url: '/_image', + query: { + f: 'png', + w: '544', + h: '184', + href: 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png' + }, + alt: 'Google logo' + }, + { + title: 'Public images', + id: '#hero', + url: '/_image', + query: { f: 'jpg', w: '768', h: '414', href: '/hero.jpg' }, + alt: 'Hero image' + }, + ].forEach(({ title, id, url, query, alt }) => { + it(title, () => { + const sources = $(`${id} source`); expect(sources.length).to.equal(3); - // TODO: better coverage to verify source props - }); - - it('includes attributes', () => { - const image = $('#social-jpg img'); - + const image = $(`${id} img`); + const src = image.attr('src'); const [route, params] = src.split('?'); - expect(route).to.equal('/@astroimage/assets/social.jpg'); + expect(route).to.equal(url); 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'); - expect(image.attr('alt')).to.equal('Social image'); - }); - }); + for (const [key, value] of Object.entries(query)) { + expect(searchParams.get(key)).to.equal(value); + } - describe('Local images with inline imports', () => { - it('includes sources', () => { - const sources = $('#inline source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes attributes', () => { - const image = $('#inline img'); - - const src = image.attr('src'); - const [route, params] = src.split('?'); - - expect(route).to.equal('/@astroimage/assets/social.jpg'); - - 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'); - expect(image.attr('alt')).to.equal('Inline social image'); - }); - }); - - describe('Remote images', () => { - it('includes sources', () => { - const sources = $('#google source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes attributes', () => { - const image = $('#google img'); - - 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('png'); - 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' - ); - expect(image.attr('alt')).to.equal('Google logo'); - }); - }); - - describe('/public images', () => { - it('includes sources', () => { - const sources = $('#hero source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes attributes', () => { - const image = $('#hero img'); - - 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('768'); - expect(searchParams.get('h')).to.equal('414'); - expect(image.attr('alt')).to.equal('Hero image'); + expect(image.attr('alt')).to.equal(alt); }); }); }); @@ -145,110 +95,59 @@ describe('SSG pictures with subpath - dev', function () { await devServer.stop(); }); - describe('Local images', () => { - it('includes sources', () => { - const sources = $('#social-jpg source'); - + [ + { + title: 'Local images', + id: '#social-jpg', + url: '/@astroimage/assets/social.jpg', + query: { f: 'jpg', w: '506', h: '253' }, + alt: 'Social image' + }, + { + title: 'Inline imports', + id: '#inline', + url: '/@astroimage/assets/social.jpg', + query: { f: 'jpg', w: '506', h: '253' }, + alt: 'Inline social image' + }, + { + title: 'Remote images', + id: '#google', + url: '/_image', + query: { + f: 'png', + w: '544', + h: '184', + href: 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png' + }, + alt: 'Google logo' + }, + { + title: 'Public images', + id: '#hero', + url: '/_image', + query: { f: 'jpg', w: '768', h: '414', href: '/hero.jpg' }, + alt: 'Hero image' + }, + ].forEach(({ title, id, url, query, alt }) => { + it(title, () => { + const sources = $(`${id} source`); expect(sources.length).to.equal(3); - // TODO: better coverage to verify source props - }); - - it('includes attributes', () => { - const image = $('#social-jpg img'); - + const image = $(`${id} img`); + const src = image.attr('src'); const [route, params] = src.split('?'); - expect(route).to.equal('/@astroimage/assets/social.jpg'); + expect(route).to.equal(url); 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'); - expect(image.attr('alt')).to.equal('Social image'); - }); - }); + for (const [key, value] of Object.entries(query)) { + expect(searchParams.get(key)).to.equal(value); + } - describe('Local images with inline imports', () => { - it('includes sources', () => { - const sources = $('#inline source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes attributes', () => { - const image = $('#inline img'); - - const src = image.attr('src'); - const [route, params] = src.split('?'); - - expect(route).to.equal('/@astroimage/assets/social.jpg'); - - 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'); - expect(image.attr('alt')).to.equal('Inline social image'); - }); - }); - - describe('Remote images', () => { - it('includes sources', () => { - const sources = $('#google source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes attributes', () => { - const image = $('#google img'); - - 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('png'); - 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' - ); - expect(image.attr('alt')).to.equal('Google logo'); - }); - }); - - describe('/public images', () => { - it('includes sources', () => { - const sources = $('#hero source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes attributes', () => { - const image = $('#hero img'); - - 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('768'); - expect(searchParams.get('h')).to.equal('414'); - expect(image.attr('alt')).to.equal('Hero image'); + expect(image.attr('alt')).to.equal(alt); }); }); }); @@ -279,144 +178,66 @@ describe('SSG pictures - build', function () { } } - describe('Local images', () => { - it('includes sources', () => { - const sources = $('#social-jpg source'); + [ + { + title: 'Local images', + id: '#social-jpg', + regex: /^\/social.\w{8}_\w{4,10}.jpg/, + size: { width: 506, height: 253, type: 'jpg' }, + alt: 'Social image' + }, + { + title: 'Inline images', + id: '#inline', + regex: /^\/social.\w{8}_\w{4,10}.jpg/, + size: { width: 506, height: 253, type: 'jpg' }, + alt: 'Inline social image' + }, + { + title: 'Remote images', + id: '#google', + regex: /^\/googlelogo_color_272x92dp_\w{4,10}.png/, + size: { width: 544, height: 184, type: 'png' }, + alt: 'Google logo' + }, + { + title: 'Public images', + id: '#hero', + regex: /^\/hero_\w{4,10}.jpg/, + size: { width: 768, height: 414, type: 'jpg' }, + alt: 'Hero image' + } + ] + .forEach(({ title, id,regex, size, alt }) => { + it(title, () => { + const sources = $(`${id} source`); + expect(sources.length).to.equal(3); + + const image = $(`${id} img`); + + expect(image.attr('src')).to.match(regex); + expect(image.attr('width')).to.equal(size.width.toString()); + expect(image.attr('height')).to.equal(size.height.toString()); + expect(image.attr('alt')).to.equal(alt); + + verifyImage(image.attr('src'), size); - expect(sources.length).to.equal(3); + sources.each((_, el) => { + const source = $(el); + const srcset = source.attr('srcset'); - // TODO: better coverage to verify source props - }); + for (const src of srcset.split(',')) { + const [pathname, width] = src.split(' '); + const widthNum = parseInt(width.substring(0, width.length - 1)); - it('includes attributes', () => { - const image = $('#social-jpg img'); - - expect(image.attr('src')).to.equal('/social.cece8c77_isw36.jpg'); - expect(image.attr('width')).to.equal('506'); - expect(image.attr('height')).to.equal('253'); - expect(image.attr('alt')).to.equal('Social image'); - }); - - it('built the optimized image', () => { - verifyImage('social.cece8c77_Z1qCkLW.avif', { width: 253, height: 127, type: 'avif' }); - verifyImage('social.cece8c77_ZHhvOb.webp', { width: 253, height: 127, type: 'webp' }); - verifyImage('social.cece8c77_ZwfMjf.jpg', { width: 253, height: 127, type: 'jpg' }); - verifyImage('social.cece8c77_6t5Xo.avif', { width: 506, height: 253, type: 'avif' }); - verifyImage('social.cece8c77_ONTVa.webp', { width: 506, height: 253, type: 'webp' }); - verifyImage('social.cece8c77_isw36.jpg', { width: 506, height: 253, type: 'jpg' }); - }); - }); - - describe('Inline imports', () => { - it('includes sources', () => { - const sources = $('#inline source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes attributes', () => { - const image = $('#inline img'); - - expect(image.attr('src')).to.equal('/social.cece8c77_isw36.jpg'); - expect(image.attr('width')).to.equal('506'); - expect(image.attr('height')).to.equal('253'); - expect(image.attr('alt')).to.equal('Inline social image'); - }); - - it('built the optimized image', () => { - verifyImage('social.cece8c77_Z1qCkLW.avif', { width: 253, height: 127, type: 'avif' }); - verifyImage('social.cece8c77_ZHhvOb.webp', { width: 253, height: 127, type: 'webp' }); - verifyImage('social.cece8c77_ZwfMjf.jpg', { width: 253, height: 127, type: 'jpg' }); - verifyImage('social.cece8c77_6t5Xo.avif', { width: 506, height: 253, type: 'avif' }); - verifyImage('social.cece8c77_ONTVa.webp', { width: 506, height: 253, type: 'webp' }); - verifyImage('social.cece8c77_isw36.jpg', { width: 506, height: 253, type: 'jpg' }); - }); - }); - - describe('Remote images', () => { - // Hard-coding in the test! This should never change since the hash is based - // on the static `src` string - const HASH = 'ZWW1pg'; - - it('includes sources', () => { - const sources = $('#google source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes attributes', () => { - const image = $('#google img'); - - expect(image.attr('src')).to.equal(`/googlelogo_color_272x92dp_${HASH}.png`); - expect(image.attr('width')).to.equal('544'); - expect(image.attr('height')).to.equal('184'); - expect(image.attr('alt')).to.equal('Google logo'); - }); - - it('built the optimized image', () => { - verifyImage(`googlelogo_color_272x92dp_1YsbPJ.avif`, { - width: 272, - height: 92, - type: 'avif', + verifyImage(pathname, { + width: widthNum, + height: widthNum === size.width ? size.height : Math.round(size.height / 2), + type: path.extname(pathname).substring(1) + }) + } + }) }); - verifyImage(`googlelogo_color_272x92dp_1OJIxd.webp`, { - width: 272, - height: 92, - type: 'webp', - }); - verifyImage(`googlelogo_color_272x92dp_ZaELrV.png`, { - width: 272, - height: 92, - type: 'png', - }); - verifyImage(`googlelogo_color_272x92dp_I7OBe.avif`, { - width: 544, - height: 184, - type: 'avif', - }); - verifyImage(`googlelogo_color_272x92dp_ReA0T.webp`, { - width: 544, - height: 184, - type: 'webp', - }); - verifyImage(`googlelogo_color_272x92dp_ZWW1pg.png`, { - width: 544, - height: 184, - type: 'png', - }); - }); - }); - - describe('/public images', () => { - it('includes sources', () => { - const sources = $('#hero source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes attributes', () => { - const image = $('#hero img'); - - expect(image.attr('src')).to.equal('/hero_1ql1f0.jpg'); - expect(image.attr('width')).to.equal('768'); - expect(image.attr('height')).to.equal('414'); - expect(image.attr('alt')).to.equal('Hero image'); - }); - - it('built the optimized image', () => { - verifyImage('hero_ZOXU0F.avif', { width: 384, height: 207, type: 'avif' }); - verifyImage('hero_ZFR9B0.webp', { width: 384, height: 207, type: 'webp' }); - verifyImage('hero_Z1rYjFx.jpg', { width: 384, height: 207, type: 'jpg' }); - verifyImage('hero_Z1kkIMd.avif', { width: 768, height: 414, type: 'avif' }); - verifyImage('hero_Z1bdXnx.webp', { width: 768, height: 414, type: 'webp' }); - verifyImage('hero_Z1Wl8s5.jpg', { width: 768, height: 414, type: 'jpg' }); - }); }); }); @@ -446,143 +267,65 @@ describe('SSG pictures with subpath - build', function () { } } - describe('Local images', () => { - it('includes sources', () => { - const sources = $('#social-jpg source'); + [ + { + title: 'Local images', + id: '#social-jpg', + regex: /^\/docs\/social.\w{8}_\w{4,10}.jpg/, + size: { width: 506, height: 253, type: 'jpg' }, + alt: 'Social image' + }, + { + title: 'Inline images', + id: '#inline', + regex: /^\/docs\/social.\w{8}_\w{4,10}.jpg/, + size: { width: 506, height: 253, type: 'jpg' }, + alt: 'Inline social image' + }, + { + title: 'Remote images', + id: '#google', + regex: /^\/docs\/googlelogo_color_272x92dp_\w{4,10}.png/, + size: { width: 544, height: 184, type: 'png' }, + alt: 'Google logo' + }, + { + title: 'Public images', + id: '#hero', + regex: /^\/docs\/hero_\w{4,10}.jpg/, + size: { width: 768, height: 414, type: 'jpg' }, + alt: 'Hero image' + } + ] + .forEach(({ title, id,regex, size, alt }) => { + it(title, () => { + const sources = $(`${id} source`); + expect(sources.length).to.equal(3); + + const image = $(`${id} img`); + + expect(image.attr('src')).to.match(regex); + expect(image.attr('width')).to.equal(size.width.toString()); + expect(image.attr('height')).to.equal(size.height.toString()); + expect(image.attr('alt')).to.equal(alt); + + verifyImage(image.attr('src').replace('/docs', ''), size); - expect(sources.length).to.equal(3); + sources.each((_, el) => { + const source = $(el); + const srcset = source.attr('srcset'); - // TODO: better coverage to verify source props - }); + for (const src of srcset.split(',')) { + const [pathname, width] = src.split(' '); + const widthNum = parseInt(width.substring(0, width.length - 1)) - it('includes attributes', () => { - const image = $('#social-jpg img'); - - expect(image.attr('src')).to.equal('/docs/social.cece8c77_VWX3S.jpg'); - expect(image.attr('width')).to.equal('506'); - expect(image.attr('height')).to.equal('253'); - expect(image.attr('alt')).to.equal('Social image'); - }); - - it('built the optimized image', () => { - verifyImage('social.cece8c77_2wbTqo.avif', { width: 253, height: 127, type: 'avif' }); - verifyImage('social.cece8c77_Z1OEppL.webp', { width: 253, height: 127, type: 'webp' }); - verifyImage('social.cece8c77_Z1xuFVD.jpg', { width: 253, height: 127, type: 'jpg' }); - verifyImage('social.cece8c77_Z10SMCc.avif', { width: 506, height: 253, type: 'avif' }); - verifyImage('social.cece8c77_ZhxXEq.webp', { width: 506, height: 253, type: 'webp' }); - verifyImage('social.cece8c77_Z1ks7l5.jpg', { width: 506, height: 253, type: 'jpg' }); - }); - }); - - describe('Inline imports', () => { - it('includes sources', () => { - const sources = $('#inline source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes attributes', () => { - const image = $('#inline img'); - - expect(image.attr('src')).to.equal('/docs/social.cece8c77_VWX3S.jpg'); - expect(image.attr('width')).to.equal('506'); - expect(image.attr('height')).to.equal('253'); - expect(image.attr('alt')).to.equal('Inline social image'); - }); - - it('built the optimized image', () => { - verifyImage('social.cece8c77_2wbTqo.avif', { width: 253, height: 127, type: 'avif' }); - verifyImage('social.cece8c77_Z1OEppL.webp', { width: 253, height: 127, type: 'webp' }); - verifyImage('social.cece8c77_Z1xuFVD.jpg', { width: 253, height: 127, type: 'jpg' }); - verifyImage('social.cece8c77_Z10SMCc.avif', { width: 506, height: 253, type: 'avif' }); - verifyImage('social.cece8c77_ZhxXEq.webp', { width: 506, height: 253, type: 'webp' }); - verifyImage('social.cece8c77_Z1ks7l5.jpg', { width: 506, height: 253, type: 'jpg' }); - }); - }); - - describe('Remote images', () => { - // Hard-coding in the test! This should never change since the hash is based - // on the static `src` string - const HASH = 'ZWW1pg'; - - it('includes sources', () => { - const sources = $('#google source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes attributes', () => { - const image = $('#google img'); - - expect(image.attr('src')).to.equal(`/docs/googlelogo_color_272x92dp_${HASH}.png`); - expect(image.attr('width')).to.equal('544'); - expect(image.attr('height')).to.equal('184'); - expect(image.attr('alt')).to.equal('Google logo'); - }); - - it('built the optimized image', () => { - verifyImage(`googlelogo_color_272x92dp_1YsbPJ.avif`, { - width: 272, - height: 92, - type: 'avif', + verifyImage(pathname.replace('/docs', ''), { + width: widthNum, + height: widthNum === size.width ? size.height : Math.round(size.height / 2), + type: path.extname(pathname).substring(1) + }) + } + }) }); - verifyImage(`googlelogo_color_272x92dp_1OJIxd.webp`, { - width: 272, - height: 92, - type: 'webp', - }); - verifyImage(`googlelogo_color_272x92dp_ZaELrV.png`, { - width: 272, - height: 92, - type: 'png', - }); - verifyImage(`googlelogo_color_272x92dp_I7OBe.avif`, { - width: 544, - height: 184, - type: 'avif', - }); - verifyImage(`googlelogo_color_272x92dp_ReA0T.webp`, { - width: 544, - height: 184, - type: 'webp', - }); - verifyImage(`googlelogo_color_272x92dp_ZWW1pg.png`, { - width: 544, - height: 184, - type: 'png', - }); - }); - }); - - describe('/public images', () => { - it('includes sources', () => { - const sources = $('#hero source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes attributes', () => { - const image = $('#hero img'); - - expect(image.attr('src')).to.equal('/docs/hero_1ql1f0.jpg'); - expect(image.attr('width')).to.equal('768'); - expect(image.attr('height')).to.equal('414'); - expect(image.attr('alt')).to.equal('Hero image'); - }); - - it('built the optimized image', () => { - verifyImage('hero_ZOXU0F.avif', { width: 384, height: 207, type: 'avif' }); - verifyImage('hero_ZFR9B0.webp', { width: 384, height: 207, type: 'webp' }); - verifyImage('hero_Z1rYjFx.jpg', { width: 384, height: 207, type: 'jpg' }); - verifyImage('hero_Z1kkIMd.avif', { width: 768, height: 414, type: 'avif' }); - verifyImage('hero_Z1bdXnx.webp', { width: 768, height: 414, type: 'webp' }); - verifyImage('hero_Z1Wl8s5.jpg', { width: 768, height: 414, type: 'jpg' }); - }); }); }); diff --git a/packages/integrations/image/test/picture-ssr-build.test.js b/packages/integrations/image/test/picture-ssr-build.test.js index 59bcbf10f..286037b58 100644 --- a/packages/integrations/image/test/picture-ssr-build.test.js +++ b/packages/integrations/image/test/picture-ssr-build.test.js @@ -15,8 +15,42 @@ describe('SSR pictures - build', function () { await fixture.build(); }); - describe('Local images', () => { - it('includes sources', async () => { + [ + { + title: 'Local images', + id: '#social-jpg', + url: '/_image', + query: { f: 'jpg', w: '506', h: '253', href: /^\/assets\/social.\w{8}.jpg/ }, + alt: 'Social image' + }, + { + title: 'Inline imports', + id: '#inline', + url: '/_image', + query: { f: 'jpg', w: '506', h: '253', href: /^\/assets\/social.\w{8}.jpg/ }, + alt: 'Inline social image' + }, + { + title: 'Remote images', + id: '#google', + url: '/_image', + query: { + f: 'png', + w: '544', + h: '184', + href: 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png' + }, + alt: 'Google logo' + }, + { + title: 'Public images', + id: '#hero', + url: '/_image', + query: { f: 'jpg', w: '768', h: '414', href: '/hero.jpg' }, + alt: 'Hero image' + } + ].forEach(({ title, id, url, query }) => { + it(title, async () => { const app = await fixture.loadTestAdapterApp(); const request = new Request('http://example.com/'); @@ -24,162 +58,26 @@ describe('SSR pictures - build', function () { const html = await response.text(); const $ = cheerio.load(html); - const sources = $('#social-jpg source'); + const sources = $(`${id} source`); expect(sources.length).to.equal(3); - // TODO: better coverage to verify source props - }); - - it('includes attributes', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - const image = $('#social-jpg img'); + const image = $(`${id} img`); const src = image.attr('src'); const [route, params] = src.split('?'); - expect(route).to.equal('/_image'); + expect(route).to.equal(url); 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'); - expect(searchParams.get('href')).to.equal('/assets/social.cece8c77.jpg'); - expect(image.attr('alt')).to.equal('Social image'); - }); - }); - - describe('Inline imports', () => { - it('includes sources', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - const sources = $('#inline source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes attributes', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - const image = $('#inline img'); - - 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')).to.equal('/assets/social.cece8c77.jpg'); - expect(image.attr('alt')).to.equal('Inline social image'); - }); - }); - - describe('Remote images', () => { - it('includes sources', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - const sources = $('#google source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes attributes', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - const image = $('#google img'); - - 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('png'); - expect(searchParams.get('w')).to.equal('544'); - expect(searchParams.get('h')).to.equal('184'); - // TODO: possible to avoid encoding the full image path? - expect(searchParams.get('href')).to.equal( - 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png' - ); - expect(image.attr('alt')).to.equal('Google logo'); - }); - }); - - describe('/public images', () => { - it('includes sources', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - const sources = $('#hero source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes attributes', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - const image = $('#hero img'); - - 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('768'); - expect(searchParams.get('h')).to.equal('414'); - expect(searchParams.get('href')).to.equal('/hero.jpg'); - expect(image.attr('alt')).to.equal('Hero image'); + for (const [key, value] of Object.entries(query)) { + if (typeof value === 'string') { + expect(searchParams.get(key)).to.equal(value); + } else { + expect(searchParams.get(key)).to.match(value); + } + } }); }); }); @@ -197,8 +95,42 @@ describe('SSR pictures with subpath - build', function () { await fixture.build(); }); - describe('Local images', () => { - it('includes sources', async () => { + [ + { + title: 'Local images', + id: '#social-jpg', + url: '/_image', + query: { f: 'jpg', w: '506', h: '253', href: /^\/docs\/assets\/social.\w{8}.jpg/ }, + alt: 'Social image' + }, + { + title: 'Inline imports', + id: '#inline', + url: '/_image', + query: { f: 'jpg', w: '506', h: '253', href: /^\/docs\/assets\/social.\w{8}.jpg/ }, + alt: 'Inline social image' + }, + { + title: 'Remote images', + id: '#google', + url: '/_image', + query: { + f: 'png', + w: '544', + h: '184', + href: 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png' + }, + alt: 'Google logo' + }, + { + title: 'Public images', + id: '#hero', + url: '/_image', + query: { f: 'jpg', w: '768', h: '414', href: '/hero.jpg' }, + alt: 'Hero image' + } + ].forEach(({ title, id, url, query }) => { + it(title, async () => { const app = await fixture.loadTestAdapterApp(); const request = new Request('http://example.com/'); @@ -206,162 +138,26 @@ describe('SSR pictures with subpath - build', function () { const html = await response.text(); const $ = cheerio.load(html); - const sources = $('#social-jpg source'); + const sources = $(`${id} source`); expect(sources.length).to.equal(3); - // TODO: better coverage to verify source props - }); - - it('includes attributes', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - const image = $('#social-jpg img'); + const image = $(`${id} img`); const src = image.attr('src'); const [route, params] = src.split('?'); - expect(route).to.equal('/_image'); + expect(route).to.equal(url); 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'); - expect(searchParams.get('href')).to.equal('/docs/assets/social.cece8c77.jpg'); - expect(image.attr('alt')).to.equal('Social image'); - }); - }); - - describe('Inline imports', () => { - it('includes sources', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - const sources = $('#inline source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes attributes', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - const image = $('#inline img'); - - 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')).to.equal('/docs/assets/social.cece8c77.jpg'); - expect(image.attr('alt')).to.equal('Inline social image'); - }); - }); - - describe('Remote images', () => { - it('includes sources', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - const sources = $('#google source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes attributes', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - const image = $('#google img'); - - 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('png'); - expect(searchParams.get('w')).to.equal('544'); - expect(searchParams.get('h')).to.equal('184'); - // TODO: possible to avoid encoding the full image path? - expect(searchParams.get('href')).to.equal( - 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png' - ); - expect(image.attr('alt')).to.equal('Google logo'); - }); - }); - - describe('/public images', () => { - it('includes sources', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - const sources = $('#hero source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes attributes', async () => { - const app = await fixture.loadTestAdapterApp(); - - const request = new Request('http://example.com/'); - const response = await app.render(request); - const html = await response.text(); - const $ = cheerio.load(html); - - const image = $('#hero img'); - - 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('768'); - expect(searchParams.get('h')).to.equal('414'); - expect(searchParams.get('href')).to.equal('/hero.jpg'); - expect(image.attr('alt')).to.equal('Hero image'); + for (const [key, value] of Object.entries(query)) { + if (typeof value === 'string') { + expect(searchParams.get(key)).to.equal(value); + } else { + expect(searchParams.get(key)).to.match(value); + } + } }); }); }); diff --git a/packages/integrations/image/test/picture-ssr-dev.test.js b/packages/integrations/image/test/picture-ssr-dev.test.js index ba47c5b37..6e0371cd5 100644 --- a/packages/integrations/image/test/picture-ssr-dev.test.js +++ b/packages/integrations/image/test/picture-ssr-dev.test.js @@ -24,133 +24,74 @@ describe('SSR pictures - dev', function () { await devServer.stop(); }); - describe('Local images', () => { - it('includes sources', () => { - const sources = $('#social-jpg source'); + [ + { + title: 'Local images', + id: '#social-jpg', + url: '/@astroimage/assets/social.jpg', + query: { f: 'jpg', w: '506', h: '253' }, + contentType: 'image/jpeg', + alt: 'Social image' + }, + { + title: 'Inline imports', + id: '#inline', + url: '/@astroimage/assets/social.jpg', + query: { f: 'jpg', w: '506', h: '253' }, + contentType: 'image/jpeg', + alt: 'Inline social image' + }, + { + title: 'Remote images', + id: '#google', + url: '/_image', + query: { + f: 'png', + w: '544', + h: '184', + href: 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png' + }, + contentType: 'image/png', + alt: 'Google logo' + }, + { + title: 'Public images', + id: '#hero', + url: '/_image', + query: { + f: 'jpg', + w: '768', + h: '414', + href: '/hero.jpg' + }, + contentType: 'image/jpeg', + alt: 'Hero image' + } + ].forEach(({ title, id, url, query, alt, contentType }) => { + it(title, async () => { + const sources = $(`${id} source`); expect(sources.length).to.equal(3); - // TODO: better coverage to verify source props - }); - - it('includes src, width, and height attributes', () => { - const image = $('#social-jpg img'); + const image = $(`${id} img`); const src = image.attr('src'); const [route, params] = src.split('?'); - expect(route).to.equal('/@astroimage/assets/social.jpg'); + expect(route).to.equal(url); 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'); - expect(image.attr('alt')).to.equal('Social image'); - }); + for (const [key, value] of Object.entries(query)) { + expect(searchParams.get(key)).to.equal(value); + } - it('returns the optimized image', async () => { - const image = $('#social-jpg img'); + expect(image.attr('alt')).to.equal(alt); 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('Inline imports', () => { - it('includes sources', () => { - const sources = $('#inline source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes src, width, and height attributes', () => { - const image = $('#inline img'); - - const src = image.attr('src'); - const [route, params] = src.split('?'); - - expect(route).to.equal('/@astroimage/assets/social.jpg'); - - 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'); - expect(image.attr('alt')).to.equal('Inline social image'); - }); - }); - - describe('Remote images', () => { - it('includes sources', () => { - const sources = $('#google source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes src, width, and height attributes', () => { - const image = $('#google img'); - - 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('png'); - 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' - ); - expect(image.attr('alt')).to.equal('Google logo'); - }); - }); - - describe('/public images', () => { - it('includes sources', () => { - const sources = $('#hero source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes src, width, and height attributes', () => { - const image = $('#hero img'); - - 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('768'); - expect(searchParams.get('h')).to.equal('414'); - expect(searchParams.get('href')).to.equal('/hero.jpg'); - expect(image.attr('alt')).to.equal('Hero image'); - }); - - it('returns the optimized image', async () => { - const image = $('#hero img'); - - 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 + expect(res.headers.get('Content-Type')).to.equal(contentType); }); }); }); @@ -177,133 +118,74 @@ describe('SSR pictures with subpath - dev', function () { await devServer.stop(); }); - describe('Local images', () => { - it('includes sources', () => { - const sources = $('#social-jpg source'); + [ + { + title: 'Local images', + id: '#social-jpg', + url: '/@astroimage/assets/social.jpg', + query: { f: 'jpg', w: '506', h: '253' }, + contentType: 'image/jpeg', + alt: 'Social image' + }, + { + title: 'Inline imports', + id: '#inline', + url: '/@astroimage/assets/social.jpg', + query: { f: 'jpg', w: '506', h: '253' }, + contentType: 'image/jpeg', + alt: 'Inline social image' + }, + { + title: 'Remote images', + id: '#google', + url: '/_image', + query: { + f: 'png', + w: '544', + h: '184', + href: 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png' + }, + contentType: 'image/png', + alt: 'Google logo' + }, + { + title: 'Public images', + id: '#hero', + url: '/_image', + query: { + f: 'jpg', + w: '768', + h: '414', + href: '/hero.jpg' + }, + contentType: 'image/jpeg', + alt: 'Hero image' + } + ].forEach(({ title, id, url, query, alt, contentType }) => { + it(title, async () => { + const sources = $(`${id} source`); expect(sources.length).to.equal(3); - // TODO: better coverage to verify source props - }); - - it('includes src, width, and height attributes', () => { - const image = $('#social-jpg img'); + const image = $(`${id} img`); const src = image.attr('src'); const [route, params] = src.split('?'); - expect(route).to.equal('/@astroimage/assets/social.jpg'); + expect(route).to.equal(url); 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'); - expect(image.attr('alt')).to.equal('Social image'); - }); + for (const [key, value] of Object.entries(query)) { + expect(searchParams.get(key)).to.equal(value); + } - it('returns the optimized image', async () => { - const image = $('#social-jpg img'); + expect(image.attr('alt')).to.equal(alt); 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('Inline imports', () => { - it('includes sources', () => { - const sources = $('#inline source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes src, width, and height attributes', () => { - const image = $('#inline img'); - - const src = image.attr('src'); - const [route, params] = src.split('?'); - - expect(route).to.equal('/@astroimage/assets/social.jpg'); - - 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'); - expect(image.attr('alt')).to.equal('Inline social image'); - }); - }); - - describe('Remote images', () => { - it('includes sources', () => { - const sources = $('#google source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes src, width, and height attributes', () => { - const image = $('#google img'); - - 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('png'); - 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' - ); - expect(image.attr('alt')).to.equal('Google logo'); - }); - }); - - describe('/public images', () => { - it('includes sources', () => { - const sources = $('#hero source'); - - expect(sources.length).to.equal(3); - - // TODO: better coverage to verify source props - }); - - it('includes src, width, and height attributes', () => { - const image = $('#hero img'); - - 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('768'); - expect(searchParams.get('h')).to.equal('414'); - expect(searchParams.get('href')).to.equal('/hero.jpg'); - expect(image.attr('alt')).to.equal('Hero image'); - }); - - it('returns the optimized image', async () => { - const image = $('#hero img'); - - 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 + expect(res.headers.get('Content-Type')).to.equal(contentType); }); }); }); diff --git a/packages/integrations/image/test/rotation.test.js b/packages/integrations/image/test/rotation.test.js index b31910abd..06f74d1c2 100644 --- a/packages/integrations/image/test/rotation.test.js +++ b/packages/integrations/image/test/rotation.test.js @@ -29,72 +29,38 @@ describe('Image rotation', function () { $ = cheerio.load(html); }); - describe('Landscape images', () => { - const hashes = [ - '/Landscape_0.080ebd7a_ZdTMkT.jpg', - '/Landscape_1.c92e81c9_4Eikw.jpg', - '/Landscape_2.f54c85e5_1iKxtI.jpg', - '/Landscape_3.8e20af03_Z2sFwFL.jpg', - '/Landscape_4.15f511b0_1dNJQt.jpg', - '/Landscape_5.6d88c17f_ZtLntP.jpg', - '/Landscape_6.1a88f6d8_Z1Pl4xy.jpg', - '/Landscape_7.cb1008c2_Z1JYr40.jpg', - '/Landscape_8.3d2837d2_1xTOBN.jpg', - ]; + it('Landscape images', () => { + for (let i = 0; i < 9; i++) { + const image = $(`#landscape-${i}`); + const regex = new RegExp(`\^/Landscape_${i}.\\w{8}_\\w{4,10}.jpg`); - it('includes attributes', () => { - for (let i = 0; i < 9; i++) { - const image = $(`#landscape-${i}`); + expect(image.attr('src')).to.match(regex); + expect(image.attr('width')).to.equal('1800'); + expect(image.attr('height')).to.equal('1200'); - expect(image.attr('src')).to.equal(hashes[i]); - expect(image.attr('width')).to.equal('1800'); - expect(image.attr('height')).to.equal('1200'); - } - }); - - it('built the optimized image', () => { - for (let i = 0; i < 9; i++) { - verifyImage(hashes[i], { - width: 1800, - height: 1200, - type: 'jpg', - }); - } - }); + verifyImage(image.attr('src'), { + width: 1800, + height: 1200, + type: 'jpg', + }); + } }); - describe('Portait images', () => { - const hashes = [ - '/Portrait_0.e09ae908_5e5uz.jpg', - '/Portrait_1.c7b4942e_1RJQep.jpg', - '/Portrait_2.8e8be39f_T6sr4.jpg', - '/Portrait_3.1dcc58b4_Z1uaoxA.jpg', - '/Portrait_4.2f89d418_ZLQlNB.jpg', - '/Portrait_5.b3b6cc6f_Z23Ek26.jpg', - '/Portrait_6.94e06390_ak2Ek.jpg', - '/Portrait_7.9ffdecfe_Z1S4klG.jpg', - '/Portrait_8.9d01343d_2dak03.jpg', - ]; + it('Portait images', () => { + for (let i = 0; i < 9; i++) { + const image = $(`#portrait-${i}`); + const regex = new RegExp(`\^/Portrait_${i}.\\w{8}_\\w{4,10}.jpg`); - it('includes attributes', () => { - for (let i = 0; i < 9; i++) { - const image = $(`#portrait-${i}`); + expect(image.attr('src')).to.match(regex); + expect(image.attr('width')).to.equal('1200'); + expect(image.attr('height')).to.equal('1800'); - expect(image.attr('src')).to.equal(hashes[i]); - expect(image.attr('width')).to.equal('1200'); - expect(image.attr('height')).to.equal('1800'); - } - }); - - it('built the optimized image', () => { - for (let i = 0; i < 9; i++) { - verifyImage(hashes[i], { - width: 1200, - height: 1800, - type: 'jpg', - }); - } - }); + verifyImage(image.attr('src'), { + width: 1200, + height: 1800, + type: 'jpg', + }); + } }); }); }); diff --git a/packages/integrations/image/test/with-mdx.test.js b/packages/integrations/image/test/with-mdx.test.js index 3894cf303..e92bb155e 100644 --- a/packages/integrations/image/test/with-mdx.test.js +++ b/packages/integrations/image/test/with-mdx.test.js @@ -24,76 +24,40 @@ describe('Images in MDX - build', function () { expect(result).to.deep.equal(expected); } - describe('Local images', () => { - it('includes attributes', () => { - const image = $('#social-jpg'); + [ + { + title: 'Local images', + id: '#social-jpg', + regex: /^\/social.\w{8}_\w{4,10}.jpg/, + size: { width: 506, height: 253, type: 'jpg' } + }, + { + title: 'Inline imports', + id: '#inline', + regex: /^\/social.\w{8}_\w{4,10}.jpg/, + size: { width: 506, height: 253, type: 'jpg' } + }, + { + title: 'Remote images', + id: '#google', + regex: /^\/googlelogo_color_272x92dp_\w{4,10}.webp/, + size: { width: 544, height: 184, type: 'webp' } + }, + { + title: 'Public images', + id: '#hero', + regex: /^\/hero_\w{4,10}.webp/, + size: { width: 768, height: 414, type: 'webp' } + } + ].forEach(({ title, id, regex, size }) => { + it(title, () => { + const image = $(id); - expect(image.attr('src')).to.equal('/social.cece8c77_1zwatP.jpg'); - expect(image.attr('width')).to.equal('506'); - expect(image.attr('height')).to.equal('253'); - }); + expect(image.attr('src')).to.match(regex); + expect(image.attr('width')).to.equal(size.width.toString()); + expect(image.attr('height')).to.equal(size.height.toString()); - it('built the optimized image', () => { - verifyImage('social.cece8c77_1zwatP.jpg', { width: 506, height: 253, type: 'jpg' }); - }); - }); - - describe('Inline imports', () => { - it('includes attributes', () => { - const image = $('#inline'); - - expect(image.attr('src')).to.equal('/social.cece8c77_Z2tF99.jpg'); - expect(image.attr('width')).to.equal('506'); - expect(image.attr('height')).to.equal('253'); - }); - - it('built the optimized image', () => { - verifyImage('social.cece8c77_Z2tF99.jpg', { width: 506, height: 253, type: 'jpg' }); - }); - }); - - describe('Remote images', () => { - // Hard-coding in the test! These should never change since the hash is based - // on the static `src` string - const HASH = 'Z1RBHqs'; - const HASH_WITH_QUERY = 'Z17oujH'; - - it('includes attributes', () => { - const image = $('#google'); - - expect(image.attr('src')).to.equal(`/googlelogo_color_272x92dp_${HASH}.webp`); - expect(image.attr('width')).to.equal('544'); - expect(image.attr('height')).to.equal('184'); - }); - - it('built the optimized image', () => { - verifyImage(`/googlelogo_color_272x92dp_${HASH}.webp`, { - width: 544, - height: 184, - type: 'webp', - }); - }); - - it('removes query strings', () => { - verifyImage(`/googlelogo_color_272x92dp_${HASH_WITH_QUERY}.webp`, { - width: 544, - height: 184, - type: 'webp', - }); - }); - }); - - describe('/public images', () => { - it('includes attributes', () => { - const image = $('#hero'); - - expect(image.attr('src')).to.equal('/hero_Z2k1JGN.webp'); - expect(image.attr('width')).to.equal('768'); - expect(image.attr('height')).to.equal('414'); - }); - - it('built the optimized image', () => { - verifyImage('hero_Z2k1JGN.webp', { width: 768, height: 414, type: 'webp' }); + verifyImage(image.attr('src'), size); }); }); });