diff --git a/packages/common/test/directives/ng_optimized_image_spec.ts b/packages/common/test/directives/ng_optimized_image_spec.ts index 521c2c4461d..dbe1396c453 100644 --- a/packages/common/test/directives/ng_optimized_image_spec.ts +++ b/packages/common/test/directives/ng_optimized_image_spec.ts @@ -696,19 +696,18 @@ describe('Image directive', () => { it('should set `src` to match `rawSrc` if image loader is not provided', () => { setupTestingModule(); - const template = ''; + const template = ``; const fixture = createTestComponent(template); fixture.detectChanges(); const nativeElement = fixture.nativeElement as HTMLElement; const img = nativeElement.querySelector('img')!; - expect(img.src).toBe('https://somesite.imgix.net/img.png'); + expect(img.src).toBe(`${IMG_BASE_URL}/img.png`); }); it('should set `src` using the image loader provided via the `IMAGE_LOADER` token to compose src URL', () => { - const imageLoader = (config: ImageLoaderConfig) => - `https://somesite.imgix.net/${config.src}`; + const imageLoader = (config: ImageLoaderConfig) => `${IMG_BASE_URL}/${config.src}`; setupTestingModule({imageLoader}); const template = ` @@ -720,14 +719,14 @@ describe('Image directive', () => { const nativeElement = fixture.nativeElement as HTMLElement; const imgs = nativeElement.querySelectorAll('img')!; - expect(imgs[0].src.trim()).toBe('https://somesite.imgix.net/img.png'); - expect(imgs[1].src.trim()).toBe('https://somesite.imgix.net/img-2.png'); + expect(imgs[0].src.trim()).toBe(`${IMG_BASE_URL}/img.png`); + expect(imgs[1].src.trim()).toBe(`${IMG_BASE_URL}/img-2.png`); }); it('should set `src` to an image URL that does not include a default width parameter', () => { const imageLoader = (config: ImageLoaderConfig) => { const widthStr = config.width ? `?w=${config.width}` : ``; - return `https://somesite.imgix.net/${config.src}${widthStr}`; + return `${IMG_BASE_URL}/${config.src}${widthStr}`; }; setupTestingModule({imageLoader}); @@ -737,7 +736,7 @@ describe('Image directive', () => { const nativeElement = fixture.nativeElement as HTMLElement; const img = nativeElement.querySelector('img')!; - expect(img.src).toBe('https://somesite.imgix.net/img.png'); + expect(img.src).toBe(`${IMG_BASE_URL}/img.png`); }); describe('`rawSrcset` values', () => { @@ -746,7 +745,7 @@ describe('Image directive', () => { beforeEach(() => { imageLoader = (config: ImageLoaderConfig) => { const width = config.width ? `?w=${config.width}` : ``; - return `https://somesite.imgix.net/${config.src}${width}`; + return `${IMG_BASE_URL}/${config.src}${width}`; }; }); @@ -761,7 +760,7 @@ describe('Image directive', () => { const nativeElement = fixture.nativeElement as HTMLElement; const img = nativeElement.querySelector('img')!; - expect(img.src).toBe('https://somesite.imgix.net/img-100.png'); + expect(img.src).toBe(`${IMG_BASE_URL}/img-100.png`); expect(img.srcset).toBe(''); }); @@ -776,10 +775,9 @@ describe('Image directive', () => { const nativeElement = fixture.nativeElement as HTMLElement; const img = nativeElement.querySelector('img')!; - expect(img.src).toBe('https://somesite.imgix.net/img.png'); + expect(img.src).toBe(`${IMG_BASE_URL}/img.png`); expect(img.srcset) - .toBe( - 'https://somesite.imgix.net/img.png?w=100 100w, https://somesite.imgix.net/img.png?w=200 200w'); + .toBe(`${IMG_BASE_URL}/img.png?w=100 100w, ${IMG_BASE_URL}/img.png?w=200 200w`); }); it('should set the `srcset` using the `rawSrcset` value with density descriptors', () => { @@ -793,10 +791,9 @@ describe('Image directive', () => { const nativeElement = fixture.nativeElement as HTMLElement; const img = nativeElement.querySelector('img')!; - expect(img.src).toBe('https://somesite.imgix.net/img.png'); + expect(img.src).toBe(`${IMG_BASE_URL}/img.png`); expect(img.srcset) - .toBe( - 'https://somesite.imgix.net/img.png?w=100 1x, https://somesite.imgix.net/img.png?w=200 2x'); + .toBe(`${IMG_BASE_URL}/img.png?w=100 1x, ${IMG_BASE_URL}/img.png?w=200 2x`); }); it('should set the `srcset` if `rawSrcset` has only one src defined', () => { @@ -810,8 +807,8 @@ describe('Image directive', () => { const nativeElement = fixture.nativeElement as HTMLElement; const img = nativeElement.querySelector('img')!; - expect(img.src.trim()).toBe('https://somesite.imgix.net/img.png'); - expect(img.srcset.trim()).toBe('https://somesite.imgix.net/img.png?w=100 100w'); + expect(img.src.trim()).toBe(`${IMG_BASE_URL}/img.png`); + expect(img.srcset.trim()).toBe(`${IMG_BASE_URL}/img.png?w=100 100w`); }); it('should set the `srcset` if `rawSrcSet` has extra spaces', () => { @@ -825,10 +822,9 @@ describe('Image directive', () => { const nativeElement = fixture.nativeElement as HTMLElement; const img = nativeElement.querySelector('img')!; - expect(img.src).toBe('https://somesite.imgix.net/img.png'); + expect(img.src).toBe(`${IMG_BASE_URL}/img.png`); expect(img.srcset) - .toBe( - 'https://somesite.imgix.net/img.png?w=100 100w, https://somesite.imgix.net/img.png?w=200 200w'); + .toBe(`${IMG_BASE_URL}/img.png?w=100 100w, ${IMG_BASE_URL}/img.png?w=200 200w`); }); it('should set the `srcset` if `rawSrcSet` has a trailing comma', () => { @@ -842,10 +838,9 @@ describe('Image directive', () => { const nativeElement = fixture.nativeElement as HTMLElement; const img = nativeElement.querySelector('img')!; - expect(img.src).toBe('https://somesite.imgix.net/img.png'); + expect(img.src).toBe(`${IMG_BASE_URL}/img.png`); expect(img.srcset) - .toBe( - 'https://somesite.imgix.net/img.png?w=100 1x, https://somesite.imgix.net/img.png?w=200 2x'); + .toBe(`${IMG_BASE_URL}/img.png?w=100 1x, ${IMG_BASE_URL}/img.png?w=200 2x`); }); it('should set the `srcset` if `rawSrcSet` has 3+ srcs', () => { @@ -859,10 +854,12 @@ describe('Image directive', () => { const nativeElement = fixture.nativeElement as HTMLElement; const img = nativeElement.querySelector('img')!; - expect(img.src).toBe('https://somesite.imgix.net/img.png'); + expect(img.src).toBe(`${IMG_BASE_URL}/img.png`); expect(img.srcset) .toBe( - 'https://somesite.imgix.net/img.png?w=100 100w, https://somesite.imgix.net/img.png?w=200 200w, https://somesite.imgix.net/img.png?w=300 300w'); + `${IMG_BASE_URL}/img.png?w=100 100w, ` + + `${IMG_BASE_URL}/img.png?w=200 200w, ` + + `${IMG_BASE_URL}/img.png?w=300 300w`); }); it('should set the `srcset` if `rawSrcSet` has decimal density descriptors', () => { @@ -876,10 +873,12 @@ describe('Image directive', () => { const nativeElement = fixture.nativeElement as HTMLElement; const img = nativeElement.querySelector('img')!; - expect(img.src).toBe('https://somesite.imgix.net/img.png'); + expect(img.src).toBe(`${IMG_BASE_URL}/img.png`); expect(img.srcset) .toBe( - 'https://somesite.imgix.net/img.png?w=100 1x, https://somesite.imgix.net/img.png?w=250 2.5x, https://somesite.imgix.net/img.png?w=300 3x'); + `${IMG_BASE_URL}/img.png?w=100 1x, ` + + `${IMG_BASE_URL}/img.png?w=250 2.5x, ` + + `${IMG_BASE_URL}/img.png?w=300 3x`); }); }); }); @@ -887,6 +886,13 @@ describe('Image directive', () => { // Helpers +// Base URL that can be used in tests to construct absolute URLs. +const IMG_BASE_URL = { + // Use `toString` here to delay referencing the `window` until the tests + // execution starts, otherwise the `window` might not be defined in Node env. + toString: () => window.location.origin +}; + const ANGULAR_LOGO_BASE64 = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg=='; diff --git a/packages/common/test/image_loaders/image_loader_spec.ts b/packages/common/test/image_loaders/image_loader_spec.ts index 369ff1bbf4f..4d6f5c14679 100644 --- a/packages/common/test/image_loaders/image_loader_spec.ts +++ b/packages/common/test/image_loaders/image_loader_spec.ts @@ -6,59 +6,70 @@ * found in the LICENSE file at https://angular.io/license */ -import {CommonModule} from '@angular/common'; +import {IMAGE_LOADER, ImageLoader, PRECONNECT_CHECK_BLOCKLIST} from '@angular/common/src/directives/ng_optimized_image'; import {provideImgixLoader} from '@angular/common/src/directives/ng_optimized_image/image_loaders/imgix_loader'; -import {NgOptimizedImageModule} from '@angular/common/src/directives/ng_optimized_image/ng_optimized_image'; -import {PRECONNECT_CHECK_BLOCKLIST} from '@angular/common/src/directives/ng_optimized_image/preconnect_link_checker'; import {RuntimeErrorCode} from '@angular/common/src/errors'; -import {Component, ValueProvider} from '@angular/core'; -import {ComponentFixture, TestBed} from '@angular/core/testing'; -import {expect} from '@angular/platform-browser/testing/src/matchers'; +import {createEnvironmentInjector, ValueProvider} from '@angular/core'; describe('Built-in image directive loaders', () => { describe('Imgix loader', () => { + function createImgixLoader(path: string): ImageLoader { + const injector = createEnvironmentInjector([provideImgixLoader(path)]); + return injector.get(IMAGE_LOADER); + } + + function invalidPathError(path: string): string { + return `NG0${RuntimeErrorCode.INVALID_INPUT}: ImgixLoader has detected ` + + `an invalid path: expecting a path like https://somepath.imgix.net/` + + `but got: \`${path}\``; + } + describe('invalid paths', () => { - it('should throw if path is empty', () => { - expect(() => { - setupTestingModule([provideImgixLoader('')]); - }) - .toThrowError( - `NG0${RuntimeErrorCode.INVALID_INPUT}: ImgixLoader has detected an invalid path: ` + - `expecting a path like https://somepath.imgix.net/` + - `but got: \`\``); + it('should throw when a path is empty', () => { + const path = ''; + expect(() => provideImgixLoader(path)).toThrowError(invalidPathError(path)); }); - it('should throw if not a path', () => { - expect(() => { - setupTestingModule([provideImgixLoader('wellhellothere')]); - }) - .toThrowError( - `NG0${RuntimeErrorCode.INVALID_INPUT}: ImgixLoader has detected an invalid path: ` + - `expecting a path like https://somepath.imgix.net/` + - `but got: \`wellhellothere\``); + it('should throw when a path is not a URL', () => { + const path = 'wellhellothere'; + expect(() => provideImgixLoader(path)).toThrowError(invalidPathError(path)); }); - it('should throw if path is missing a scheme', () => { - expect(() => { - setupTestingModule([provideImgixLoader('somepath.imgix.net')]); - }) - .toThrowError( - `NG0${RuntimeErrorCode.INVALID_INPUT}: ImgixLoader has detected an invalid path: ` + - `expecting a path like https://somepath.imgix.net/` + - `but got: \`somepath.imgix.net\``); + it('should throw when a path is missing a scheme', () => { + const path = 'somepath.imgix.net'; + expect(() => provideImgixLoader(path)).toThrowError(invalidPathError(path)); }); - it('should throw if path is malformed', () => { - expect(() => { - setupTestingModule([provideImgixLoader('somepa\th.imgix.net? few')]); - }) - .toThrowError( - `NG0${RuntimeErrorCode.INVALID_INPUT}: ImgixLoader has detected an invalid path: ` + - `expecting a path like https://somepath.imgix.net/` + - `but got: \`somepa\th.imgix.net? few\``); + it('should throw when a path is malformed', () => { + const path = 'somepa\th.imgix.net? few'; + expect(() => provideImgixLoader(path)).toThrowError(invalidPathError(path)); }); }); + it('should construct an image loader with the given path', () => { + const loader = createImgixLoader('https://somesite.imgix.net'); + const config = {src: 'img.png'}; + expect(loader(config)).toBe('https://somesite.imgix.net/img.png?auto=format'); + }); + + it('should handle a trailing forward slash on the path', () => { + const loader = createImgixLoader('https://somesite.imgix.net/'); + const config = {src: 'img.png'}; + expect(loader(config)).toBe('https://somesite.imgix.net/img.png?auto=format'); + }); + + it('should handle a leading forward slash on the src', () => { + const loader = createImgixLoader('https://somesite.imgix.net'); + const config = {src: '/img.png'}; + expect(loader(config)).toBe('https://somesite.imgix.net/img.png?auto=format'); + }); + + it('should construct an image loader with the given path', () => { + const loader = createImgixLoader('https://somesite.imgix.net'); + const config = {src: 'img.png', width: 100}; + expect(loader(config)).toBe('https://somesite.imgix.net/img.png?auto=format&w=100'); + }); + describe('options', () => { it('should configure PRECONNECT_CHECK_BLOCKLIST token by default', () => { const providers = provideImgixLoader('https://somesite.imgix.net'); @@ -89,91 +100,5 @@ describe('Built-in image directive loaders', () => { expect(providers.length).toBe(1); }); }); - - it('should construct an image loader with the given path', () => { - setupTestingModule([provideImgixLoader('https://somesite.imgix.net')]); - - const template = ` - - - `; - const fixture = createTestComponent(template); - fixture.detectChanges(); - - const nativeElement = fixture.nativeElement as HTMLElement; - const imgs = nativeElement.querySelectorAll('img')!; - expect(imgs[0].src).toBe('https://somesite.imgix.net/img.png?auto=format'); - expect(imgs[1].src).toBe('https://somesite.imgix.net/img-2.png?auto=format'); - }); - - it('should handle a trailing forward slash on the path', () => { - setupTestingModule([provideImgixLoader('https://somesite.imgix.net/')]); - - const template = ` - - `; - const fixture = createTestComponent(template); - fixture.detectChanges(); - - const nativeElement = fixture.nativeElement as HTMLElement; - const img = nativeElement.querySelector('img')!; - expect(img.src).toBe('https://somesite.imgix.net/img.png?auto=format'); - }); - - it('should handle a leading forward slash on the src', () => { - setupTestingModule([provideImgixLoader('https://somesite.imgix.net/')]); - - const template = ` - - `; - const fixture = createTestComponent(template); - fixture.detectChanges(); - - const nativeElement = fixture.nativeElement as HTMLElement; - const img = nativeElement.querySelector('img')!; - expect(img.src).toBe('https://somesite.imgix.net/img.png?auto=format'); - }); - - it('should be compatible with rawSrcset', () => { - setupTestingModule([provideImgixLoader('https://somesite.imgix.net')]); - - const template = ` - - `; - const fixture = createTestComponent(template); - fixture.detectChanges(); - - const nativeElement = fixture.nativeElement as HTMLElement; - const img = nativeElement.querySelector('img')!; - expect(img.src).toBe('https://somesite.imgix.net/img.png?auto=format'); - expect(img.srcset) - .toBe( - 'https://somesite.imgix.net/img.png?auto=format&w=100 100w, https://somesite.imgix.net/img.png?auto=format&w=200 200w'); - }); }); }); - - -// Helpers - -@Component({ - selector: 'test-cmp', - template: '', -}) -class TestComponent { -} - -function setupTestingModule(providers: any[]) { - TestBed.configureTestingModule({ - declarations: [TestComponent], - // Note: the `NgOptimizedImage` directive is experimental and is not a part of the - // `CommonModule` yet, so it's imported separately. - imports: [CommonModule, NgOptimizedImageModule], - providers, - }); -} - -function createTestComponent(template: string): ComponentFixture { - return TestBed.overrideComponent(TestComponent, {set: {template: template}}) - .createComponent(TestComponent); -}