From 00d4741fb8cde9c2790241654ba375fa6afa4f81 Mon Sep 17 00:00:00 2001 From: Adegoke Temitope <49331266+Devdre1909@users.noreply.github.com> Date: Mon, 8 Aug 2022 17:45:07 +0100 Subject: [PATCH] feat(image): add image via.placeholder provider (#1186) --- src/modules/image/index.ts | 3 + src/modules/image/providers/placeholder.ts | 101 ++++++++++++++++++ test/image.spec.ts | 116 +++++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 src/modules/image/providers/placeholder.ts diff --git a/src/modules/image/index.ts b/src/modules/image/index.ts index 5ca06c71cd7..08cef08ff59 100644 --- a/src/modules/image/index.ts +++ b/src/modules/image/index.ts @@ -2,6 +2,7 @@ import type { Faker } from '../..'; import type { MethodsOf } from '../../utils/types'; import { LoremPicsum } from './providers/lorempicsum'; import { Lorempixel } from './providers/lorempixel'; +import { Placeholder } from './providers/placeholder'; import { Unsplash } from './providers/unsplash'; /** @@ -13,6 +14,7 @@ export class Image { readonly lorempixel: Lorempixel; readonly unsplash: Unsplash; readonly lorempicsum: LoremPicsum; + readonly placeholder: Placeholder; constructor(private readonly faker: Faker) { // Bind `this` so namespaced is working correctly @@ -26,6 +28,7 @@ export class Image { this.lorempixel = new Lorempixel(this.faker); this.unsplash = new Unsplash(this.faker); this.lorempicsum = new LoremPicsum(this.faker); + this.placeholder = new Placeholder(this.faker); } /** diff --git a/src/modules/image/providers/placeholder.ts b/src/modules/image/providers/placeholder.ts new file mode 100644 index 00000000000..224dccfe03a --- /dev/null +++ b/src/modules/image/providers/placeholder.ts @@ -0,0 +1,101 @@ +import type { Faker } from '../../..'; + +/** + * Module to generate links to images on `https://via.placeholder.com/`. + */ +export class Placeholder { + constructor(private readonly faker: Faker) { + // Bind `this` so namespaced is working correctly + for (const name of Object.getOwnPropertyNames(Placeholder.prototype)) { + if (name === 'constructor' || typeof this[name] !== 'function') { + continue; + } + this[name] = this[name].bind(this); + } + } + + /** + * Generates a new placeholder image url. + * + * @param width The width of the image (in pixels). Defaults to `640`. + * @param height The height of the image (in pixels). Defaults to `width`. + * @param text The text of the image. + * @param format The file format of the image. Supports `png`, `jpeg`, `png`, `gif`, `webp`. + * @param backgroundColor The background color of the placeholder. Supports HEX CODE format. + * @param textColor The text color of the placeholder. Requires `backgroundColor`. Supports HEX CODE format. + * + * @example + * faker.image.placeholder.imageUrl() // https://via.placeholder.com/640x640 + * faker.image.placeholder.imageUrl(200) // https://via.placeholder.com/200x200 + * faker.image.placeholder.imageUrl(200, 100) // https://via.placeholder.com/200x100 + * faker.image.placeholder.imageUrl(200, 100, 'Fish') // https://via.placeholder.com/200x100?text=Fish + * faker.image.placeholder.imageUrl(200, 100, 'Fish', 'webp') // https://via.placeholder.com/200x100.webp?text=Fish + * faker.image.placeholder.imageUrl(200, 100, 'Fish', 'webp') // https://via.placeholder.com/200x100.webp?text=Fish + * faker.image.placeholder.imageUrl(200, 100, 'Fish', 'webp', '000000', 'ffffff) // https://via.placeholder.com/200x100/000000/FFFFFF.webp?text=Fish + * + */ + imageUrl( + width?: number, + height?: number, + text?: string, + format?: 'png' | 'jpeg' | 'jpg' | 'gif' | 'webp', + backgroundColor?: string, + textColor?: string + ): string { + width = width || 640; + height = height || width; + + let url = 'https://via.placeholder.com'; + url += `/${width}x${height}`; + + if (backgroundColor != null) { + url += `/${backgroundColor.replace('#', '').toUpperCase()}`; + + if (textColor != null) { + url += `/${textColor.replace('#', '').toUpperCase()}`; + } + } + + if (format != null) { + url += `.${format}`; + } + + if (text != null) { + const urlParam = new URLSearchParams({ text }); + url += `?${urlParam.toString()}`; + } + + return url; + } + + /** + * Generate a new placeholder image with random colors and text. + * + * @param width The width of the image (in pixels). Defaults to `640`. + * @param height The height of the image (in pixels). Defaults to `width`. + * @param format The file format of the image. Supports `png` `jpeg` `png` `gif` `webp`. + * + * @example + * faker.image.placeholder.randomUrl() // https://via.placeholder.com/640x640/000000/ffffff?text=lorum + * faker.image.placeholder.randomUrl(150) // https://via.placeholder.com/150x150/000000/ffffff?text=lorum + * faker.image.placeholder.randomUrl(150, 200) // https://via.placeholder.com/150x200/000000/ffffff?text=lorum + * faker.image.placeholder.randomUrl(150, 200, 'png') // https://via.placeholder.com/150x200/000000/ffffff.png?text=lorum + */ + randomUrl( + width?: number, + height?: number, + format?: 'png' | 'jpeg' | 'jpg' | 'gif' | 'webp' + ): string { + return this.imageUrl( + width, + height, + this.faker.lorem.word(), + format, + this.faker.color.rgb({ + casing: 'upper', + prefix: '', + }), + this.faker.color.rgb({ casing: 'upper', prefix: '' }) + ); + } +} diff --git a/test/image.spec.ts b/test/image.spec.ts index bbb99ffaaab..36503efa3eb 100644 --- a/test/image.spec.ts +++ b/test/image.spec.ts @@ -237,6 +237,122 @@ describe('image', () => { } }); + describe('placeholder', () => { + describe('imageUrl()', () => { + it('should return a random image url from placeholder', () => { + const imageUrl = faker.image.placeholder.imageUrl(); + + expect(imageUrl).toBe('https://via.placeholder.com/640x640'); + }); + + it('should return a square random image url from placeholder with width and height', () => { + const imageUrl = faker.image.placeholder.imageUrl(100); + + expect(imageUrl).toBe('https://via.placeholder.com/100x100'); + }); + + it('should return a random image url with a gif format', () => { + const imageUrl = faker.image.placeholder.imageUrl( + 100, + 100, + undefined, + 'gif' + ); + + expect(imageUrl).toBe('https://via.placeholder.com/100x100.gif'); + }); + + it('should return a random image url with correct text for a specified format', () => { + const imageUrl = faker.image.placeholder.imageUrl( + 100, + 100, + 'I love food', + 'png' + ); + + expect(imageUrl).toBe( + 'https://via.placeholder.com/100x100.png?text=I+love+food' + ); + }); + + it('should return a random image url with specified background color and text color', () => { + const imageUrl = faker.image.placeholder.imageUrl( + 100, + 100, + undefined, + undefined, + '000000', + 'ffffff' + ); + + expect(imageUrl).toBe( + 'https://via.placeholder.com/100x100/000000/FFFFFF' + ); + }); + + it('should return a random image url with specified background color and color without the #', () => { + const imageUrl = faker.image.placeholder.imageUrl( + 100, + 100, + undefined, + undefined, + '#000000', + '#ffffff' + ); + + expect(imageUrl).toBe( + 'https://via.placeholder.com/100x100/000000/FFFFFF' + ); + }); + + it('should return a random image url given all parameter', () => { + const imageUrl = faker.image.placeholder.imageUrl( + 100, + 200, + 'I love food', + 'jpg', + '000000', + 'ffffff' + ); + + expect(imageUrl).toBe( + 'https://via.placeholder.com/100x200/000000/FFFFFF.jpg?text=I+love+food' + ); + }); + }); + + describe('randomUrl()', () => { + it('should return a random url with specified width and height', () => { + const imageUrl = faker.image.placeholder.randomUrl(200, 150); + + // https://via.placeholder.com/150/000000/FFFFFF/ + const urlSpilt = imageUrl.split('/'); + + console.log(imageUrl); + + expect(urlSpilt[0]).toBe('https:'); + expect(urlSpilt[2]).toBe('via.placeholder.com'); + expect(urlSpilt[3]).toBe('200x150'); + expect(urlSpilt[4]).toHaveLength(6); + expect(urlSpilt[5].split('?')[0]).toHaveLength(6); + expect(urlSpilt[5].split('?')[1]).toContain('text='); + }); + it('should return a random url with specified width and height and format', () => { + const imageUrl = faker.image.placeholder.randomUrl(200, 150, 'png'); + + const urlSpilt = imageUrl.split('/'); + + expect(urlSpilt[0]).toBe('https:'); + expect(urlSpilt[2]).toBe('via.placeholder.com'); + expect(urlSpilt[3]).toBe('200x150'); + expect(urlSpilt[4]).toHaveLength(6); + expect(urlSpilt[5].split('?')[0]).toHaveLength(10); + expect(urlSpilt[5].split('?')[0]).toContain('.png'); + expect(urlSpilt[5].split('?')[1]).toContain('text='); + }); + }); + }); + describe('dataUri', () => { it('should return a blank data', () => { const dataUri = faker.image.dataUri(200, 300);