-
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.
chore: add util to make (lazy) injection tokens
- Loading branch information
Showing
4 changed files
with
139 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export { _isDefined } from './is-defined' | ||
export { _makeInjectionToken } from './make-injection-token' |
94 changes: 94 additions & 0 deletions
94
projects/ngx-meta/src/core/src/utils/make-injection-token.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,94 @@ | ||
import { | ||
_makeInjectionToken, | ||
INJECTION_TOKEN_FACTORIES, | ||
INJECTION_TOKENS, | ||
} from './make-injection-token' | ||
import { TestBed } from '@angular/core/testing' | ||
import { InjectionToken } from '@angular/core' | ||
|
||
describe('make injection token', () => { | ||
const sut = _makeInjectionToken | ||
const description = 'dummy' | ||
const factory = () => description | ||
|
||
afterEach(() => { | ||
INJECTION_TOKENS.clear() | ||
INJECTION_TOKEN_FACTORIES.clear() | ||
}) | ||
|
||
it('should return an injection token using the provided factory', () => { | ||
const factoryOutput = factory() | ||
const injectionToken = sut(description, factory) | ||
|
||
expect(TestBed.inject(injectionToken)).toEqual(factoryOutput) | ||
}) | ||
|
||
it('should return an injection token with given description prefixed by library name', () => { | ||
const injectionToken = sut(description, factory) | ||
|
||
expect(injectionToken.toString()).toContain(`ngx-meta ${description}`) | ||
}) | ||
|
||
describe('when making an already existing token', () => { | ||
let injectionToken: InjectionToken<ReturnType<typeof factory>> | ||
|
||
beforeEach(() => { | ||
spyOn(console, 'warn') | ||
injectionToken = sut(description, factory) | ||
}) | ||
|
||
const shouldNotLogAnyMessage = () => | ||
it('should not log any message', () => { | ||
expect(console.warn).not.toHaveBeenCalled() | ||
}) | ||
|
||
describe('when providing another description', () => { | ||
let secondInjectionToken: InjectionToken<ReturnType<typeof factory>> | ||
|
||
beforeEach(() => { | ||
secondInjectionToken = sut('another-description', factory) | ||
}) | ||
|
||
it('should return another injection token', () => { | ||
expect(injectionToken).not.toBe(secondInjectionToken) | ||
}) | ||
|
||
shouldNotLogAnyMessage() | ||
}) | ||
|
||
describe('when providing same description and factory', () => { | ||
let secondInjectionToken: InjectionToken<ReturnType<typeof factory>> | ||
|
||
beforeEach(() => { | ||
secondInjectionToken = sut(description, factory) | ||
}) | ||
|
||
it('should return the same injection token', () => { | ||
expect(injectionToken).toBe(secondInjectionToken) | ||
}) | ||
|
||
shouldNotLogAnyMessage() | ||
}) | ||
|
||
describe('when providing same description but different factory', () => { | ||
const anotherFactory = () => 'another' | ||
let secondInjectionToken: InjectionToken< | ||
ReturnType<typeof anotherFactory> | ||
> | ||
|
||
beforeEach(() => { | ||
secondInjectionToken = sut(description, anotherFactory) | ||
}) | ||
|
||
it('should return the same injection token if providing same description but different factory', () => { | ||
expect(secondInjectionToken).toBe(injectionToken) | ||
}) | ||
|
||
it('should warn about it', () => { | ||
expect(console.warn).toHaveBeenCalledWith( | ||
jasmine.stringContaining('same description but different factory'), | ||
) | ||
}) | ||
}) | ||
}) | ||
}) |
41 changes: 41 additions & 0 deletions
41
projects/ngx-meta/src/core/src/utils/make-injection-token.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,41 @@ | ||
import { InjectionToken } from '@angular/core' | ||
import { _formatDevMessage } from '../messaging' | ||
import { MODULE_NAME } from '../module-name' | ||
|
||
export const INJECTION_TOKENS = new Map<string, InjectionToken<unknown>>() | ||
export const INJECTION_TOKEN_FACTORIES = new Map<string, () => unknown>() | ||
|
||
/** | ||
* See https://github.com/davidlj95/ngx/pull/892 | ||
* | ||
* @internal | ||
*/ | ||
export const _makeInjectionToken: <T>( | ||
description: string, | ||
factory: () => T, | ||
) => InjectionToken<T> = (description, factory) => { | ||
const injectionToken = | ||
INJECTION_TOKENS.get(description) ?? | ||
new InjectionToken(`ngx-meta ${description}`, { factory }) | ||
/* istanbul ignore next https://github.com/istanbuljs/istanbuljs/issues/719 */ | ||
if (ngDevMode) { | ||
if ((INJECTION_TOKEN_FACTORIES.get(description) ?? factory) !== factory) { | ||
console.warn( | ||
_formatDevMessage( | ||
[ | ||
'trying to create an injection token with same description but different factory. ', | ||
'The existing injection token will be used and this new factory will be ignored. ', | ||
'This use case is a bit weird anyway. Ensure no duplicate injection tokens are created. ', | ||
].join('\n'), | ||
{ | ||
module: MODULE_NAME, | ||
value: description, | ||
}, | ||
), | ||
) | ||
} | ||
INJECTION_TOKEN_FACTORIES.set(description, factory) | ||
} | ||
INJECTION_TOKENS.set(description, injectionToken) | ||
return injectionToken | ||
} |