-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add dev error 4 non http(s) Twitter Card image URLs (#738)
* feat: add dev error 4 non http(s) Twitter Card image URLs * refactor: create util to warn about non http URLs * feat: improve invalid URL message with relative URL comment
- Loading branch information
Showing
11 changed files
with
263 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
projects/ngx-meta/src/core/src/maybe-non-http-url-dev-message.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { _maybeNonHttpUrlDevMessage } from './maybe-non-http-url-dev-message' | ||
|
||
describe('maybeNonHttpUrlDevMessage', () => { | ||
const sut = _maybeNonHttpUrlDevMessage | ||
|
||
beforeEach(() => { | ||
spyOn(console, 'error') | ||
}) | ||
|
||
describe('when URL is valid', () => { | ||
// noinspection HttpUrlsUsage | ||
const TEST_CASES = [ | ||
{ url: undefined, case: 'is not defined' }, | ||
{ url: 'http://example.com/image.jpg', case: 'uses HTTP protocol' }, | ||
{ url: 'https://example.com/image.jpg', case: 'uses HTTPS protocol' }, | ||
] as const | ||
for (const testCase of TEST_CASES) { | ||
describe(`like when URL ${testCase.case}`, () => { | ||
it('should not emit any message', () => { | ||
sut(testCase.url) | ||
|
||
expect(console.error).not.toHaveBeenCalled() | ||
}) | ||
}) | ||
} | ||
}) | ||
|
||
describe('when URL is invalid', () => { | ||
const TEST_CASES = [ | ||
{ url: 'assets/image.png', case: 'is relative' }, | ||
{ | ||
url: 'ftp://example.com/image.jpg', | ||
case: 'uses a non-HTTP protocol (ie: ftp)', | ||
}, | ||
] as const | ||
for (const testCase of TEST_CASES) { | ||
describe(`like when URL ${testCase.case}`, () => { | ||
it('should emit a message about it', () => { | ||
sut(testCase.url) | ||
|
||
expect(console.error).toHaveBeenCalledWith( | ||
jasmine.stringContaining(testCase.url), | ||
) | ||
}) | ||
}) | ||
} | ||
|
||
it('should emit a message containing the provided extra options', () => { | ||
let receivedMessage: string | ||
;(console.error as jasmine.Spy).and.callFake( | ||
(message) => (receivedMessage = message), | ||
) | ||
const opts = { | ||
module: 'graphTweet', | ||
property: 'profile image', | ||
link: 'https://example.com/url-error', | ||
} satisfies Parameters<typeof sut>[1] | ||
|
||
sut(TEST_CASES[0].url, opts) | ||
|
||
expect(receivedMessage!).toContain(opts.module) | ||
expect(receivedMessage!).toContain(opts.property) | ||
expect(receivedMessage!).toContain(opts.link) | ||
}) | ||
}) | ||
}) |
26 changes: 26 additions & 0 deletions
26
projects/ngx-meta/src/core/src/maybe-non-http-url-dev-message.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/** | ||
* Logs an error message about a URL not being HTTP or HTTPs | ||
* | ||
* Useful to warn developers about some metadata that requires absolute HTTP | ||
* or HTTPs URLs | ||
* | ||
* MUST be used with `ngDevMode` so that this message only runs in development | ||
* | ||
* @internal | ||
*/ | ||
export const _maybeNonHttpUrlDevMessage = ( | ||
url?: string | URL, | ||
opts: { module?: string; property?: string; link?: string } = {}, | ||
) => { | ||
const urlStr = url?.toString() | ||
if (!urlStr || urlStr.startsWith('http') || urlStr.startsWith('https')) { | ||
return | ||
} | ||
const moduleStr = opts.module ? `/${opts.module}` : '' | ||
const propertyStr = opts.property ? `${opts.property} ` : '' | ||
const linkStr = opts.link ? `For more information, see ${opts.link}` : '' | ||
console.error( | ||
`ngx-meta${moduleStr}: ${propertyStr}URL must be absolute and use either http or https.\n` + | ||
` -> Invalid ${propertyStr}URL: ${urlStr}\n${linkStr}`, | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/** | ||
* @internal | ||
*/ | ||
export const _NO_OP = () => {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 73 additions & 0 deletions
73
projects/ngx-meta/src/twitter-card/src/twitter-card-image-metadata-provider.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import { enableAutoSpy } from '@/ngx-meta/test/enable-auto-spy' | ||
import { MetadataSetter, NgxMetaMetaService } from '../../core' | ||
import { TestBed } from '@angular/core/testing' | ||
import { MockProviders } from 'ng-mocks' | ||
import { TwitterCard } from './twitter-card' | ||
import { | ||
__TWITTER_CARD_IMAGE_METADATA_SETTER_FACTORY, | ||
TWITTER_CARD_IMAGE_METADATA_PROVIDER, | ||
} from './twitter-card-image-metadata-provider' | ||
import { TwitterCardImage } from './twitter-card-image' | ||
|
||
describe('Twitter Card image metadata', () => { | ||
enableAutoSpy() | ||
let sut: MetadataSetter<TwitterCard['image']> | ||
let metaService: jasmine.SpyObj<NgxMetaMetaService> | ||
|
||
beforeEach(() => { | ||
sut = makeSut() | ||
metaService = TestBed.inject( | ||
NgxMetaMetaService, | ||
) as jasmine.SpyObj<NgxMetaMetaService> | ||
}) | ||
|
||
const image = { | ||
url: 'https://example.com/foo.png', | ||
alt: 'Alternative text', | ||
} satisfies TwitterCardImage | ||
|
||
describe('when image is provided', () => { | ||
it('should set all meta properties', () => { | ||
// noinspection DuplicatedCode | ||
sut(image) | ||
|
||
const props = Object.keys(image).length | ||
expect(metaService.set).toHaveBeenCalledTimes(props) | ||
expect(metaService.set).toHaveBeenCalledWith( | ||
jasmine.anything(), | ||
image.url, | ||
) | ||
expect(metaService.set).toHaveBeenCalledWith( | ||
jasmine.anything(), | ||
image.alt, | ||
) | ||
}) | ||
}) | ||
|
||
describe('when no image provided', () => { | ||
it('should remove all meta properties', () => { | ||
sut(undefined) | ||
|
||
const props = Object.keys(image).length | ||
expect(metaService.set).toHaveBeenCalledTimes(props) | ||
for (let i = 0; i < props; i++) { | ||
expect(metaService.set).toHaveBeenCalledWith( | ||
jasmine.anything(), | ||
undefined, | ||
) | ||
} | ||
}) | ||
}) | ||
}) | ||
|
||
function makeSut(): MetadataSetter<TwitterCard['image']> { | ||
TestBed.configureTestingModule({ | ||
providers: [ | ||
MockProviders(NgxMetaMetaService), | ||
TWITTER_CARD_IMAGE_METADATA_PROVIDER, | ||
], | ||
}) | ||
return __TWITTER_CARD_IMAGE_METADATA_SETTER_FACTORY( | ||
TestBed.inject(NgxMetaMetaService), | ||
) | ||
} |
Oops, something went wrong.