diff --git a/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.test.ts b/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.test.ts index 986a878cee..80b1df93b1 100644 --- a/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.test.ts +++ b/src/Umbraco.Web.UI.Client/src/libs/context-api/consume/context-consumer.test.ts @@ -5,20 +5,22 @@ import { UmbContextConsumer } from './context-consumer.js'; import { UmbContextRequestEventImplementation, UMB_CONTENT_REQUEST_EVENT_TYPE } from './context-request.event.js'; const testContextAlias = 'my-test-context'; +const testContextAliasAndApiAlias = 'my-test-context#testApi'; +const testContextAliasAndNotExstingApiAlias = 'my-test-context#notExistingTestApi'; class UmbTestContextConsumerClass { public prop: string = 'value from provider'; } describe('UmbContextConsumer', () => { - let consumer: UmbContextConsumer; - - beforeEach(() => { - // eslint-disable-next-line @typescript-eslint/no-empty-function - consumer = new UmbContextConsumer(document.body, testContextAlias, () => {}); - }); - describe('Public API', () => { + let consumer: UmbContextConsumer; + + beforeEach(() => { + // eslint-disable-next-line @typescript-eslint/no-empty-function + consumer = new UmbContextConsumer(document.body, testContextAlias, () => {}); + }); + describe('properties', () => { it('has a instance property', () => { expect(consumer).to.have.property('instance').that.is.undefined; @@ -45,128 +47,178 @@ describe('UmbContextConsumer', () => { }); }); - it('works with UmbContextProvider', (done) => { - const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass()); - provider.hostConnected(); + describe('Simple implementation', () => { + it('works with UmbContextProvider', (done) => { + const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass()); + provider.hostConnected(); - const element = document.createElement('div'); - document.body.appendChild(element); + const element = document.createElement('div'); + document.body.appendChild(element); - const localConsumer = new UmbContextConsumer( - element, - testContextAlias, - (_instance: UmbTestContextConsumerClass | undefined) => { + const localConsumer = new UmbContextConsumer( + element, + testContextAlias, + (_instance: UmbTestContextConsumerClass | undefined) => { + if (_instance) { + expect(_instance.prop).to.eq('value from provider'); + done(); + localConsumer.hostDisconnected(); + provider.hostDisconnected(); + } + }, + ); + localConsumer.hostConnected(); + }); + + /* + Unprovided feature is out commented currently. I'm not sure there is a use case. So lets leave the code around until we know for sure. + it('acts to Context API disconnected', (done) => { + const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass()); + provider.hostConnected(); + + const element = document.createElement('div'); + document.body.appendChild(element); + + let callbackNum = 0; + + const localConsumer = new UmbContextConsumer( + element, + testContextAlias, + (_instance: UmbTestContextConsumerClass | undefined) => { + callbackNum++; + if (callbackNum === 1) { + expect(_instance?.prop).to.eq('value from provider'); + // unregister. + provider.hostDisconnected(); + } else if (callbackNum === 2) { + expect(_instance?.prop).to.be.undefined; + done(); + } + } + ); + localConsumer.hostConnected(); + }); + */ + }); + + describe('Implementation with Api Alias', () => { + it('responds when api alias matches', (done) => { + const provider = new UmbContextProvider( + document.body, + testContextAliasAndApiAlias, + new UmbTestContextConsumerClass(), + ); + provider.hostConnected(); + + const element = document.createElement('div'); + document.body.appendChild(element); + + const localConsumer = new UmbContextConsumer(element, testContextAliasAndApiAlias, (_instance) => { if (_instance) { + expect((_instance as UmbTestContextConsumerClass).prop).to.eq('value from provider'); + localConsumer.hostDisconnected(); + provider.hostDisconnected(); + done(); + } + }); + localConsumer.hostConnected(); + }); + + it('does not respond to a non existing api alias', (done) => { + const provider = new UmbContextProvider( + document.body, + testContextAliasAndApiAlias, + new UmbTestContextConsumerClass(), + ); + provider.hostConnected(); + + const element = document.createElement('div'); + document.body.appendChild(element); + + const localConsumer = new UmbContextConsumer(element, testContextAliasAndNotExstingApiAlias, (_instance) => { + expect(false).to.be.true; + }); + localConsumer.hostConnected(); + + // Delayed check to make sure the callback is not called. + Promise.resolve().then(() => { + localConsumer.hostDisconnected(); + provider.hostDisconnected(); + done(); + }); + }); + }); + + describe('Implementation with discriminator method', () => { + type A = { prop: string }; + + function discriminator(instance: unknown): instance is A { + return typeof (instance as any).prop === 'string'; + } + + function badDiscriminator(instance: unknown): instance is A { + return typeof (instance as any).notExistingProp === 'string'; + } + + it('discriminator determines the instance type', async () => { + const localConsumer = new UmbContextConsumer( + document.body, + new UmbContextToken(testContextAlias, undefined, discriminator), + (instance: A) => { + console.log(instance); + }, + ); + localConsumer.hostConnected(); + + // This bit of code is not really a test but it serves as a TypeScript type test, making sure the given type is matches the one given from the Discriminator method. + type TestType = Exclude extends A ? true : never; + const test: TestType = true; + expect(test).to.be.true; + + localConsumer.destroy(); + }); + + it('approving discriminator still fires callback', (done) => { + const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass()); + provider.hostConnected(); + + const element = document.createElement('div'); + document.body.appendChild(element); + + const localConsumer = new UmbContextConsumer( + element, + new UmbContextToken(testContextAlias, undefined, discriminator), + (_instance) => { expect(_instance.prop).to.eq('value from provider'); done(); localConsumer.hostDisconnected(); provider.hostDisconnected(); - } - }, - ); - localConsumer.hostConnected(); - }); + }, + ); + localConsumer.hostConnected(); + }); - /* - Unprovided feature is out commented currently. I'm not sure there is a use case. So lets leave the code around until we know for sure. - it('acts to Context API disconnected', (done) => { - const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass()); - provider.hostConnected(); + it('disapproving discriminator does not fire callback', (done) => { + const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass()); + provider.hostConnected(); - const element = document.createElement('div'); - document.body.appendChild(element); + const element = document.createElement('div'); + document.body.appendChild(element); - let callbackNum = 0; + const localConsumer = new UmbContextConsumer( + element, + new UmbContextToken(testContextAlias, undefined, badDiscriminator), + (_instance) => { + expect(_instance.prop).to.eq('this must not happen!'); + }, + ); + localConsumer.hostConnected(); - const localConsumer = new UmbContextConsumer( - element, - testContextAlias, - (_instance: UmbTestContextConsumerClass | undefined) => { - callbackNum++; - if (callbackNum === 1) { - expect(_instance?.prop).to.eq('value from provider'); - // unregister. - provider.hostDisconnected(); - } else if (callbackNum === 2) { - expect(_instance?.prop).to.be.undefined; - done(); - } - } - ); - localConsumer.hostConnected(); - }); - */ -}); - -describe('UmbContextConsumer with discriminator test', () => { - type A = { prop: string }; - - function discriminator(instance: unknown): instance is A { - return typeof (instance as any).prop === 'string'; - } - - function badDiscriminator(instance: unknown): instance is A { - return typeof (instance as any).notExistingProp === 'string'; - } - - it('discriminator determines the instance type', async () => { - const localConsumer = new UmbContextConsumer( - document.body, - new UmbContextToken(testContextAlias, undefined, discriminator), - (instance: A) => { - console.log(instance); - }, - ); - localConsumer.hostConnected(); - - // This bit of code is not really a test but it serves as a TypeScript type test, making sure the given type is matches the one given from the Discriminator method. - type TestType = Exclude extends A ? true : never; - const test: TestType = true; - expect(test).to.be.true; - - localConsumer.destroy(); - }); - - it('approving discriminator still fires callback', (done) => { - const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass()); - provider.hostConnected(); - - const element = document.createElement('div'); - document.body.appendChild(element); - - const localConsumer = new UmbContextConsumer( - element, - new UmbContextToken(testContextAlias, undefined, discriminator), - (_instance) => { - expect(_instance.prop).to.eq('value from provider'); + Promise.resolve().then(() => { done(); localConsumer.hostDisconnected(); provider.hostDisconnected(); - }, - ); - localConsumer.hostConnected(); - }); - - it('disapproving discriminator does not fire callback', (done) => { - const provider = new UmbContextProvider(document.body, testContextAlias, new UmbTestContextConsumerClass()); - provider.hostConnected(); - - const element = document.createElement('div'); - document.body.appendChild(element); - - const localConsumer = new UmbContextConsumer( - element, - new UmbContextToken(testContextAlias, undefined, badDiscriminator), - (_instance) => { - expect(_instance.prop).to.eq('this must not happen!'); - }, - ); - localConsumer.hostConnected(); - - Promise.resolve().then(() => { - done(); - localConsumer.hostDisconnected(); - provider.hostDisconnected(); + }); }); }); });