From 9ecf99b75763ed08e19f3115c01a5e58aeaf529c Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Sat, 9 Nov 2024 11:32:15 +0100 Subject: test: verify the generated image links are working (#3127) --- test/integration/modules/image.spec.ts | 119 ++++++++++++++++++++++++++++++ test/modules/image.spec.ts | 129 +++++++++++++++++++-------------- 2 files changed, 192 insertions(+), 56 deletions(-) create mode 100644 test/integration/modules/image.spec.ts (limited to 'test') diff --git a/test/integration/modules/image.spec.ts b/test/integration/modules/image.spec.ts new file mode 100644 index 00000000..0901b99b --- /dev/null +++ b/test/integration/modules/image.spec.ts @@ -0,0 +1,119 @@ +/* + * Integration tests for the image methods ensuring that the returned urls work. + */ +import https from 'node:https'; +import { resolve as urlResolve } from 'node:url'; +import { describe, expect, it } from 'vitest'; +import { faker } from '../../../src'; + +/** + * Checks that the given address is a working https address. + * + * An address is considered working, if it: + * + * - is a string + * - starts with https + * - is a proper url + * - returns a http-200 (after redirects) + * + * There is a separate unit test file for checking if the returned URL matches the expectations (domain, parameters, etc.). + * + * @param address The address to check. + */ +async function assertWorkingUrl(address: string): Promise { + expect(address).toBeTypeOf('string'); + expect(address).toMatch(/^https:\/\//); + expect(() => new URL(address)).not.toThrow(); + + await expect( + new Promise((resolve, reject) => { + https + .get(address, ({ statusCode, headers: { location } }) => { + if (statusCode == null) { + reject(new Error(`No StatusCode, expected 200`)); + } else if (statusCode === 200) { + resolve(true); + } else if (statusCode >= 300 && statusCode < 400 && location) { + const newAddress = urlResolve(address, location); + assertWorkingUrl(newAddress) + .then(() => resolve(true)) + .catch((error: unknown) => { + reject( + new Error(`Failed to resolve redirect to '${location}'`, { + cause: error, + }) + ); + }); + } else { + reject( + new Error( + `Bad StatusCode ${statusCode} expected 200 for '${location}'` + ) + ); + } + }) + .on('error', (error: unknown) => { + reject(new Error(`Failed to get '${address}'`, { cause: error })); + }); + }) + ).resolves.toBe(true); +} + +describe('image', () => { + describe('avatar', () => { + it('should return a random avatar url', async () => { + const actual = faker.image.avatar(); + await assertWorkingUrl(actual); + }); + }); + + describe('avatarGitHub', () => { + it('should return a random avatar url from GitHub', async () => { + const actual = faker.image.avatarGitHub(); + await assertWorkingUrl(actual); + }); + }); + + describe('url', () => { + it('should return a random image url', async () => { + const actual = faker.image.url(); + await assertWorkingUrl(actual); + }); + + it('should return a random image url with a width', async () => { + const actual = faker.image.url({ width: 100 }); + await assertWorkingUrl(actual); + }); + + it('should return a random image url with a height', async () => { + const actual = faker.image.url({ height: 100 }); + await assertWorkingUrl(actual); + }); + + it('should return a random image url with a width and height', async () => { + const actual = faker.image.url({ width: 128, height: 64 }); + await assertWorkingUrl(actual); + }); + }); + + describe('urlLoremFlickr', () => { + it('should return a random image url from LoremFlickr', async () => { + const actual = faker.image.urlLoremFlickr(); + await assertWorkingUrl(actual); + }); + }); + + describe('urlPicsumPhotos', () => { + it('should return a random image url from PicsumPhotos', async () => { + const actual = faker.image.urlPicsumPhotos(); + await assertWorkingUrl(actual); + }); + }); + + describe('urlPlaceholder', () => { + it('should return a random image url from Placeholder', async () => { + const actual = faker.image.urlPlaceholder(); + await assertWorkingUrl(actual); + }); + }); +}); diff --git a/test/modules/image.spec.ts b/test/modules/image.spec.ts index 8624a965..36be582d 100644 --- a/test/modules/image.spec.ts +++ b/test/modules/image.spec.ts @@ -3,6 +3,25 @@ import { describe, expect, it } from 'vitest'; import { faker } from '../../src'; import { seededTests } from '../support/seeded-runs'; +/** + * Checks that the given address is a valid https address. + * + * An address is considered valid, if it: + * + * - is a string + * - starts with https + * - is a proper url + * + * There is a separate integretation test file for checking if the address is reachable. + * + * @param address The address to check. + */ +function assertValidUrl(address: string): void { + expect(address).toBeTypeOf('string'); + expect(address).toMatch(/^https:\/\//); + expect(() => new URL(address)).not.toThrow(); +} + describe('image', () => { seededTests(faker, 'image', (t) => { t.itEach('avatar', 'avatarGitHub', 'avatarLegacy'); @@ -93,85 +112,78 @@ describe('image', () => { describe('avatar', () => { it('should return a random avatar url', () => { - const avatarUrl = faker.image.avatar(); + const actual = faker.image.avatar(); - expect(avatarUrl).toBeTypeOf('string'); - expect(avatarUrl).toMatch(/^https:\/\//); - expect(() => new URL(avatarUrl)).not.toThrow(); + assertValidUrl(actual); }); }); describe('avatarGitHub', () => { it('should return a random avatar url from GitHub', () => { - const avatarUrl = faker.image.avatarGitHub(); + const actual = faker.image.avatarGitHub(); - expect(avatarUrl).toBeTypeOf('string'); - expect(avatarUrl).toMatch( + expect(actual).toBeTypeOf('string'); + expect(actual).toMatch( /^https:\/\/avatars\.githubusercontent\.com\/u\/\d+$/ ); + assertValidUrl(actual); }); }); describe('avatarLegacy', () => { it('should return a random avatar url from cloudflare-ipfs', () => { // eslint-disable-next-line @typescript-eslint/no-deprecated - const avatarUrl = faker.image.avatarLegacy(); + const actual = faker.image.avatarLegacy(); - expect(avatarUrl).toBeTypeOf('string'); - expect(avatarUrl).toMatch( + expect(actual).toBeTypeOf('string'); + expect(actual).toMatch( /^https:\/\/cloudflare-ipfs\.com\/ipfs\/Qmd3W5DuhgHirLHGVixi6V76LhCkZUz6pnFt5AJBiyvHye\/avatar\/\d{1,4}\.jpg$/ ); + // The links aren't working anymore - there is nothing we can do about it + // assertWebAddress(avatarUrl); }); }); describe('url', () => { it('should return a random image url', () => { - const imageUrl = faker.image.url(); + const actual = faker.image.url(); - expect(imageUrl).toBeTypeOf('string'); - expect(imageUrl).toMatch(/^https:\/\//); - expect(() => new URL(imageUrl)).not.toThrow(); + assertValidUrl(actual); }); it('should return a random image url with a width', () => { const width = 100; - const imageUrl = faker.image.url({ width }); + const actual = faker.image.url({ width }); - expect(imageUrl).toBeTypeOf('string'); - expect(imageUrl).toMatch(/^https:\/\//); - expect(() => new URL(imageUrl)).not.toThrow(); - expect(imageUrl).include(`${width}`); + assertValidUrl(actual); + expect(actual).include(`${width}`); }); it('should return a random image url with a height', () => { const height = 100; - const imageUrl = faker.image.url({ height }); + const actual = faker.image.url({ height }); - expect(imageUrl).toBeTypeOf('string'); - expect(imageUrl).toMatch(/^https:\/\//); - expect(() => new URL(imageUrl)).not.toThrow(); - expect(imageUrl).include(`${height}`); + assertValidUrl(actual); + expect(actual).include(`${height}`); }); it('should return a random image url with a width and height', () => { const width = 128; const height = 64; - const imageUrl = faker.image.url({ width, height }); + const actual = faker.image.url({ width, height }); - expect(imageUrl).toBeTypeOf('string'); - expect(imageUrl).toMatch(/^https:\/\//); - expect(() => new URL(imageUrl)).not.toThrow(); - expect(imageUrl).include(`${width}`); - expect(imageUrl).include(`${height}`); + assertValidUrl(actual); + expect(actual).include(`${width}`); + expect(actual).include(`${height}`); }); }); describe('urlLoremFlickr', () => { it('should return a random image url from LoremFlickr', () => { - const imageUrl = faker.image.urlLoremFlickr(); + const actual = faker.image.urlLoremFlickr(); - expect(imageUrl).toBeTypeOf('string'); - expect(imageUrl).toMatch( + assertValidUrl(actual); + expect(actual).toMatch( /^https:\/\/loremflickr\.com\/\d+\/\d+\?lock=\d+$/ ); }); @@ -179,10 +191,10 @@ describe('image', () => { describe('urlPicsumPhotos', () => { it('should return a random image url from PicsumPhotos', () => { - const imageUrl = faker.image.urlPicsumPhotos(); + const actual = faker.image.urlPicsumPhotos(); - expect(imageUrl).toBeTypeOf('string'); - expect(imageUrl).toMatch( + assertValidUrl(actual); + expect(actual).toMatch( /^https:\/\/picsum\.photos\/seed\/[0-9a-zA-Z]+\/\d+\/\d+(\?(grayscale&?)?(blur=\d+)?)?$/ ); }); @@ -190,10 +202,10 @@ describe('image', () => { describe('urlPlaceholder', () => { it('should return a random image url from Placeholder', () => { - const imageUrl = faker.image.urlPlaceholder(); + const actual = faker.image.urlPlaceholder(); - expect(imageUrl).toBeTypeOf('string'); - expect(imageUrl).toMatch( + assertValidUrl(actual); + expect(actual).toMatch( /^https:\/\/via\.placeholder\.com\/\d+x\d+\/[0-9a-fA-F]{6}\/[0-9a-fA-F]{6}\.[a-z]{3,4}\?text=.+$/ ); }); @@ -201,42 +213,47 @@ describe('image', () => { describe('dataUri', () => { it('should return an image data uri', () => { - const dataUri = faker.image.dataUri(); - expect(dataUri).toMatch(/^data:image\/svg\+xml;/); - expect(dataUri).toSatisfy(isDataURI); + const actual = faker.image.dataUri(); + + expect(actual).toMatch(/^data:image\/svg\+xml;/); + expect(actual).toSatisfy(isDataURI); }); it('should return an uri-encoded image data uri', () => { - const dataUri = faker.image.dataUri({ type: 'svg-uri' }); - expect(dataUri).toMatch(/^data:image\/svg\+xml;charset=UTF-8,/); - expect(dataUri).toSatisfy(isDataURI); + const actual = faker.image.dataUri({ type: 'svg-uri' }); + + expect(actual).toMatch(/^data:image\/svg\+xml;charset=UTF-8,/); + expect(actual).toSatisfy(isDataURI); }); it('should return a base64 image data uri', () => { - const dataUri = faker.image.dataUri({ type: 'svg-base64' }); - expect(dataUri).toMatch(/^data:image\/svg\+xml;base64,/); - expect(dataUri).toSatisfy(isDataURI); + const actual = faker.image.dataUri({ type: 'svg-base64' }); + + expect(actual).toMatch(/^data:image\/svg\+xml;base64,/); + expect(actual).toSatisfy(isDataURI); }); it('should return an image data uri with fixed size', () => { - const dataUri = faker.image.dataUri({ + const actual = faker.image.dataUri({ width: 200, height: 300, type: 'svg-uri', // required for the regex check }); - expect(dataUri).toMatch(/^data:image\/svg\+xml;charset=UTF-8,/); - expect(dataUri).toMatch(/width%3D%22200%22%20height%3D%22300/); - expect(dataUri).toSatisfy(isDataURI); + + expect(actual).toMatch(/^data:image\/svg\+xml;charset=UTF-8,/); + expect(actual).toMatch(/width%3D%22200%22%20height%3D%22300/); + expect(actual).toSatisfy(isDataURI); }); it('should return an image data uri with a fixed background color', () => { - const dataUri = faker.image.dataUri({ + const actual = faker.image.dataUri({ color: 'red', type: 'svg-uri', // required for the regex check }); - expect(dataUri).toMatch(/^data:image\/svg\+xml;charset=UTF-8,/); - expect(dataUri).toMatch(/fill%3D%22red/); - expect(dataUri).toSatisfy(isDataURI); + + expect(actual).toMatch(/^data:image\/svg\+xml;charset=UTF-8,/); + expect(actual).toMatch(/fill%3D%22red/); + expect(actual).toSatisfy(isDataURI); }); }); }); -- cgit v1.2.3