@limetech/lime-web-components 4.48.2 → 4.49.1-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +145 -1
- package/README.md +1 -1
- package/dist/application/decorators/application.d.ts +8 -0
- package/dist/application/decorators/application.js +18 -0
- package/dist/application/decorators/index.d.ts +3 -0
- package/dist/application/decorators/index.js +3 -0
- package/dist/application/decorators/session.d.ts +8 -0
- package/dist/application/decorators/session.js +18 -0
- package/dist/application/decorators/user.d.ts +8 -0
- package/dist/application/decorators/user.js +18 -0
- package/dist/application/index.d.ts +4 -0
- package/dist/application/index.js +4 -0
- package/dist/application/session.d.ts +67 -0
- package/dist/application/session.js +1 -0
- package/dist/application/types.d.ts +14 -0
- package/dist/application/types.js +3 -0
- package/dist/application/user.d.ts +59 -0
- package/dist/application/user.js +1 -0
- package/dist/commandbus/commandbus.d.ts +112 -0
- package/dist/commandbus/commandbus.js +63 -0
- package/dist/commandbus/index.d.ts +2 -0
- package/dist/commandbus/index.js +2 -0
- package/dist/commandbus/types.d.ts +14 -0
- package/dist/commandbus/types.js +3 -0
- package/dist/config/decorator.d.ts +14 -0
- package/dist/config/decorator.js +14 -0
- package/dist/config/index.d.ts +3 -0
- package/dist/config/index.js +3 -0
- package/dist/config/repository.d.ts +17 -0
- package/dist/config/repository.js +1 -0
- package/dist/config/types.d.ts +14 -0
- package/dist/config/types.js +3 -0
- package/dist/core/context.d.ts +17 -0
- package/dist/core/context.js +1 -0
- package/dist/core/decorators/factory.d.ts +29 -0
- package/dist/core/decorators/factory.js +243 -0
- package/dist/core/decorators/factory.spec.d.ts +1 -0
- package/dist/core/decorators/factory.spec.js +337 -0
- package/dist/core/decorators/index.d.ts +1 -0
- package/dist/core/decorators/index.js +1 -0
- package/dist/core/index.d.ts +6 -0
- package/dist/core/index.js +6 -0
- package/dist/core/lime-web-component.d.ts +15 -0
- package/dist/core/lime-web-component.js +1 -0
- package/dist/core/platform.d.ts +38 -0
- package/dist/core/platform.js +6 -0
- package/dist/core/plugin-loader.d.ts +28 -0
- package/dist/core/plugin-loader.js +1 -0
- package/dist/core/state.d.ts +39 -0
- package/dist/core/state.js +1 -0
- package/dist/device/decorator.d.ts +16 -0
- package/dist/device/decorator.js +16 -0
- package/dist/device/device.d.ts +21 -0
- package/dist/device/device.js +1 -0
- package/dist/device/index.d.ts +3 -0
- package/dist/device/index.js +3 -0
- package/dist/device/types.d.ts +14 -0
- package/dist/device/types.js +3 -0
- package/dist/dialog/dialog.d.ts +41 -0
- package/dist/dialog/dialog.js +1 -0
- package/dist/dialog/index.d.ts +2 -0
- package/dist/dialog/index.js +2 -0
- package/dist/dialog/types.d.ts +14 -0
- package/dist/dialog/types.js +3 -0
- package/dist/es5/application/decorators/application.js +18 -0
- package/dist/es5/application/decorators/index.js +6 -0
- package/dist/es5/application/decorators/session.js +18 -0
- package/dist/es5/application/decorators/user.js +18 -0
- package/dist/es5/application/index.js +7 -0
- package/dist/es5/application/session.js +2 -0
- package/dist/es5/application/types.js +5 -0
- package/dist/es5/application/user.js +2 -0
- package/dist/es5/commandbus/commandbus.js +31 -0
- package/dist/es5/commandbus/index.js +5 -0
- package/dist/es5/commandbus/types.js +5 -0
- package/dist/es5/config/decorator.js +12 -0
- package/dist/es5/config/index.js +6 -0
- package/dist/es5/config/repository.js +2 -0
- package/dist/es5/config/types.js +5 -0
- package/dist/es5/core/context.js +2 -0
- package/dist/es5/core/decorators/factory.js +213 -0
- package/dist/es5/core/decorators/factory.spec.js +495 -0
- package/dist/es5/core/decorators/index.js +2 -0
- package/dist/es5/core/index.js +9 -0
- package/dist/es5/core/lime-web-component.js +2 -0
- package/dist/es5/core/platform.js +6 -0
- package/dist/es5/core/plugin-loader.js +2 -0
- package/dist/es5/core/state.js +2 -0
- package/dist/es5/device/decorator.js +13 -0
- package/dist/es5/device/device.js +2 -0
- package/dist/es5/device/index.js +6 -0
- package/dist/es5/device/types.js +5 -0
- package/dist/es5/dialog/dialog.js +2 -0
- package/dist/es5/dialog/index.js +5 -0
- package/dist/es5/dialog/types.js +5 -0
- package/dist/es5/eventdispatcher/eventdispatcher.js +2 -0
- package/dist/es5/eventdispatcher/index.js +5 -0
- package/dist/es5/eventdispatcher/types.js +5 -0
- package/dist/es5/filter/decorator.js +13 -0
- package/dist/es5/filter/index.js +6 -0
- package/dist/es5/filter/repository.js +2 -0
- package/dist/es5/filter/types.js +5 -0
- package/dist/es5/http/http.js +2 -0
- package/dist/es5/http/index.js +5 -0
- package/dist/es5/http/types.js +5 -0
- package/dist/es5/index.js +22 -0
- package/dist/es5/keybindings/index.js +5 -0
- package/dist/es5/keybindings/registry.js +2 -0
- package/dist/es5/keybindings/types.js +5 -0
- package/dist/es5/limeobject/commands/bulk-create-dialog.js +17 -0
- package/dist/es5/limeobject/commands/create-dialog.js +17 -0
- package/dist/es5/limeobject/commands/delete-object.js +16 -0
- package/dist/es5/limeobject/commands/index.js +8 -0
- package/dist/es5/limeobject/commands/object-access.js +16 -0
- package/dist/es5/limeobject/commands/save-object.js +17 -0
- package/dist/es5/limeobject/decorator.js +38 -0
- package/dist/es5/limeobject/error.js +2 -0
- package/dist/es5/limeobject/index.js +9 -0
- package/dist/es5/limeobject/limeobject.js +2 -0
- package/dist/es5/limeobject/repository.js +2 -0
- package/dist/es5/limeobject/types.js +5 -0
- package/dist/es5/limetype/acl.js +2 -0
- package/dist/es5/limetype/decorator.js +28 -0
- package/dist/es5/limetype/index.js +8 -0
- package/dist/es5/limetype/limetype.js +2 -0
- package/dist/es5/limetype/property.js +40 -0
- package/dist/es5/limetype/types.js +5 -0
- package/dist/es5/navigator/decorator.js +13 -0
- package/dist/es5/navigator/index.js +6 -0
- package/dist/es5/navigator/navigator.js +2 -0
- package/dist/es5/navigator/types.js +5 -0
- package/dist/es5/notifications/index.js +5 -0
- package/dist/es5/notifications/notifications.js +2 -0
- package/dist/es5/notifications/types.js +5 -0
- package/dist/es5/query/index.js +6 -0
- package/dist/es5/query/query.js +17 -0
- package/dist/es5/query/service.js +2 -0
- package/dist/es5/query/types.js +5 -0
- package/dist/es5/routeregistry/index.js +5 -0
- package/dist/es5/routeregistry/registry.js +2 -0
- package/dist/es5/routeregistry/types.js +5 -0
- package/dist/es5/task/index.js +5 -0
- package/dist/es5/task/repository.js +17 -0
- package/dist/es5/task/types.js +5 -0
- package/dist/es5/testing/component-testing.js +102 -0
- package/dist/es5/testing/index.js +10 -0
- package/dist/es5/testing/limeobjects/company.js +660 -0
- package/dist/es5/testing/limeobjects/coworker.js +110 -0
- package/dist/es5/testing/limeobjects/deal.js +447 -0
- package/dist/es5/testing/limeobjects/document.js +82 -0
- package/dist/es5/testing/limeobjects/index.js +55 -0
- package/dist/es5/testing/limeobjects/person.js +1162 -0
- package/dist/es5/testing/limetypes/campaign.js +486 -0
- package/dist/es5/testing/limetypes/company.js +621 -0
- package/dist/es5/testing/limetypes/consent.js +237 -0
- package/dist/es5/testing/limetypes/consenttype.js +194 -0
- package/dist/es5/testing/limetypes/coworker.js +579 -0
- package/dist/es5/testing/limetypes/deal.js +422 -0
- package/dist/es5/testing/limetypes/document.js +343 -0
- package/dist/es5/testing/limetypes/helpdesk.js +426 -0
- package/dist/es5/testing/limetypes/helpdesktype.js +142 -0
- package/dist/es5/testing/limetypes/history.js +349 -0
- package/dist/es5/testing/limetypes/index.js +69 -0
- package/dist/es5/testing/limetypes/infotiles.js +514 -0
- package/dist/es5/testing/limetypes/localize.js +287 -0
- package/dist/es5/testing/limetypes/mailing.js +218 -0
- package/dist/es5/testing/limetypes/office.js +388 -0
- package/dist/es5/testing/limetypes/participant.js +195 -0
- package/dist/es5/testing/limetypes/person.js +535 -0
- package/dist/es5/testing/limetypes/recipient.js +175 -0
- package/dist/es5/testing/limetypes/solutionimprovement.js +353 -0
- package/dist/es5/testing/limetypes/successplan.js +215 -0
- package/dist/es5/testing/limetypes/target.js +181 -0
- package/dist/es5/testing/limetypes/todo.js +429 -0
- package/dist/es5/testing/platform/index.js +53 -0
- package/dist/es5/testing/platform/platform.spec.js +44 -0
- package/dist/es5/translator/index.js +5 -0
- package/dist/es5/translator/translator.js +2 -0
- package/dist/es5/translator/types.js +5 -0
- package/dist/es5/userdata/decorator.js +13 -0
- package/dist/es5/userdata/index.js +6 -0
- package/dist/es5/userdata/repository.js +2 -0
- package/dist/es5/userdata/types.js +5 -0
- package/dist/eventdispatcher/eventdispatcher.d.ts +26 -0
- package/dist/eventdispatcher/eventdispatcher.js +1 -0
- package/dist/eventdispatcher/index.d.ts +2 -0
- package/dist/eventdispatcher/index.js +2 -0
- package/dist/eventdispatcher/types.d.ts +14 -0
- package/dist/eventdispatcher/types.js +3 -0
- package/dist/filter/decorator.d.ts +15 -0
- package/dist/filter/decorator.js +14 -0
- package/dist/filter/index.d.ts +3 -0
- package/dist/filter/index.js +3 -0
- package/dist/filter/repository.d.ts +18 -0
- package/dist/filter/repository.js +1 -0
- package/dist/filter/types.d.ts +14 -0
- package/dist/filter/types.js +3 -0
- package/dist/http/http.d.ts +72 -0
- package/dist/http/http.js +1 -0
- package/dist/http/index.d.ts +2 -0
- package/dist/http/index.js +2 -0
- package/dist/http/types.d.ts +14 -0
- package/dist/http/types.js +3 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +19 -0
- package/dist/keybindings/index.d.ts +2 -0
- package/dist/keybindings/index.js +2 -0
- package/dist/keybindings/registry.d.ts +79 -0
- package/dist/keybindings/registry.js +1 -0
- package/dist/keybindings/types.d.ts +17 -0
- package/dist/keybindings/types.js +3 -0
- package/dist/limeobject/commands/bulk-create-dialog.d.ts +49 -0
- package/dist/limeobject/commands/bulk-create-dialog.js +48 -0
- package/dist/limeobject/commands/create-dialog.d.ts +28 -0
- package/dist/limeobject/commands/create-dialog.js +26 -0
- package/dist/limeobject/commands/delete-object.d.ts +10 -0
- package/dist/limeobject/commands/delete-object.js +15 -0
- package/dist/limeobject/commands/index.d.ts +5 -0
- package/dist/limeobject/commands/index.js +5 -0
- package/dist/limeobject/commands/object-access.d.ts +10 -0
- package/dist/limeobject/commands/object-access.js +15 -0
- package/dist/limeobject/commands/save-object.d.ts +16 -0
- package/dist/limeobject/commands/save-object.js +21 -0
- package/dist/limeobject/decorator.d.ts +32 -0
- package/dist/limeobject/decorator.js +42 -0
- package/dist/limeobject/error.d.ts +4 -0
- package/dist/limeobject/error.js +1 -0
- package/dist/limeobject/index.d.ts +6 -0
- package/dist/limeobject/index.js +6 -0
- package/dist/limeobject/limeobject.d.ts +43 -0
- package/dist/limeobject/limeobject.js +1 -0
- package/dist/limeobject/repository.d.ts +113 -0
- package/dist/limeobject/repository.js +1 -0
- package/dist/limeobject/types.d.ts +14 -0
- package/dist/limeobject/types.js +3 -0
- package/dist/limetype/acl.d.ts +6 -0
- package/dist/limetype/acl.js +1 -0
- package/dist/limetype/decorator.d.ts +21 -0
- package/dist/limetype/decorator.js +32 -0
- package/dist/limetype/index.d.ts +5 -0
- package/dist/limetype/index.js +5 -0
- package/dist/limetype/limetype.d.ts +25 -0
- package/dist/limetype/limetype.js +1 -0
- package/dist/limetype/property.d.ts +32 -0
- package/dist/limetype/property.js +32 -0
- package/dist/limetype/types.d.ts +14 -0
- package/dist/limetype/types.js +3 -0
- package/dist/navigator/decorator.d.ts +18 -0
- package/dist/navigator/decorator.js +15 -0
- package/dist/navigator/index.d.ts +3 -0
- package/dist/navigator/index.js +3 -0
- package/dist/navigator/navigator.d.ts +158 -0
- package/dist/navigator/navigator.js +1 -0
- package/dist/navigator/types.d.ts +17 -0
- package/dist/navigator/types.js +3 -0
- package/dist/notifications/index.d.ts +2 -0
- package/dist/notifications/index.js +2 -0
- package/dist/notifications/notifications.d.ts +101 -0
- package/dist/notifications/notifications.js +1 -0
- package/dist/notifications/types.d.ts +14 -0
- package/dist/notifications/types.js +3 -0
- package/dist/query/index.d.ts +3 -0
- package/dist/query/index.js +3 -0
- package/dist/query/query.d.ts +46 -0
- package/dist/query/query.js +14 -0
- package/dist/query/service.d.ts +12 -0
- package/dist/query/service.js +1 -0
- package/dist/query/types.d.ts +14 -0
- package/dist/query/types.js +3 -0
- package/dist/routeregistry/index.d.ts +2 -0
- package/dist/routeregistry/index.js +2 -0
- package/dist/routeregistry/registry.d.ts +92 -0
- package/dist/routeregistry/registry.js +1 -0
- package/dist/routeregistry/types.d.ts +17 -0
- package/dist/routeregistry/types.js +3 -0
- package/dist/task/index.d.ts +2 -0
- package/dist/task/index.js +2 -0
- package/dist/task/repository.d.ts +82 -0
- package/dist/task/repository.js +49 -0
- package/dist/task/types.d.ts +14 -0
- package/dist/task/types.js +3 -0
- package/dist/testing/component-testing.d.ts +53 -0
- package/dist/testing/component-testing.js +162 -0
- package/dist/testing/index.d.ts +4 -0
- package/dist/testing/index.js +4 -0
- package/dist/testing/limeobjects/company.d.ts +55 -0
- package/dist/testing/limeobjects/company.js +656 -0
- package/dist/testing/limeobjects/coworker.d.ts +22 -0
- package/dist/testing/limeobjects/coworker.js +106 -0
- package/dist/testing/limeobjects/deal.d.ts +41 -0
- package/dist/testing/limeobjects/deal.js +443 -0
- package/dist/testing/limeobjects/document.d.ts +20 -0
- package/dist/testing/limeobjects/document.js +78 -0
- package/dist/testing/limeobjects/index.d.ts +177 -0
- package/dist/testing/limeobjects/index.js +50 -0
- package/dist/testing/limeobjects/person.d.ts +20 -0
- package/dist/testing/limeobjects/person.js +1158 -0
- package/dist/testing/limetypes/campaign.d.ts +417 -0
- package/dist/testing/limetypes/campaign.js +477 -0
- package/dist/testing/limetypes/company.d.ts +591 -0
- package/dist/testing/limetypes/company.js +614 -0
- package/dist/testing/limetypes/consent.d.ts +199 -0
- package/dist/testing/limetypes/consent.js +232 -0
- package/dist/testing/limetypes/consenttype.d.ts +188 -0
- package/dist/testing/limetypes/consenttype.js +189 -0
- package/dist/testing/limetypes/coworker.d.ts +563 -0
- package/dist/testing/limetypes/coworker.js +564 -0
- package/dist/testing/limetypes/deal.d.ts +391 -0
- package/dist/testing/limetypes/deal.js +419 -0
- package/dist/testing/limetypes/document.d.ts +309 -0
- package/dist/testing/limetypes/document.js +332 -0
- package/dist/testing/limetypes/helpdesk.d.ts +394 -0
- package/dist/testing/limetypes/helpdesk.js +417 -0
- package/dist/testing/limetypes/helpdesktype.d.ts +136 -0
- package/dist/testing/limetypes/helpdesktype.js +137 -0
- package/dist/testing/limetypes/history.d.ts +308 -0
- package/dist/testing/limetypes/history.js +346 -0
- package/dist/testing/limetypes/index.d.ts +5 -0
- package/dist/testing/limetypes/index.js +63 -0
- package/dist/testing/limetypes/infotiles.d.ts +387 -0
- package/dist/testing/limetypes/infotiles.js +509 -0
- package/dist/testing/limetypes/localize.d.ts +283 -0
- package/dist/testing/limetypes/localize.js +284 -0
- package/dist/testing/limetypes/mailing.d.ts +212 -0
- package/dist/testing/limetypes/mailing.js +213 -0
- package/dist/testing/limetypes/office.d.ts +384 -0
- package/dist/testing/limetypes/office.js +385 -0
- package/dist/testing/limetypes/participant.d.ts +165 -0
- package/dist/testing/limetypes/participant.js +188 -0
- package/dist/testing/limetypes/person.d.ts +472 -0
- package/dist/testing/limetypes/person.js +530 -0
- package/dist/testing/limetypes/recipient.d.ts +147 -0
- package/dist/testing/limetypes/recipient.js +170 -0
- package/dist/testing/limetypes/solutionimprovement.d.ts +302 -0
- package/dist/testing/limetypes/solutionimprovement.js +344 -0
- package/dist/testing/limetypes/successplan.d.ts +209 -0
- package/dist/testing/limetypes/successplan.js +210 -0
- package/dist/testing/limetypes/target.d.ts +160 -0
- package/dist/testing/limetypes/target.js +178 -0
- package/dist/testing/limetypes/todo.d.ts +386 -0
- package/dist/testing/limetypes/todo.js +426 -0
- package/dist/testing/platform/index.d.ts +8 -0
- package/dist/testing/platform/index.js +61 -0
- package/dist/testing/platform/platform.spec.d.ts +1 -0
- package/dist/testing/platform/platform.spec.js +41 -0
- package/dist/translator/index.d.ts +2 -0
- package/dist/translator/index.js +2 -0
- package/dist/translator/translator.d.ts +13 -0
- package/dist/translator/translator.js +1 -0
- package/dist/translator/types.d.ts +14 -0
- package/dist/translator/types.js +3 -0
- package/dist/userdata/decorator.d.ts +17 -0
- package/dist/userdata/decorator.js +14 -0
- package/dist/userdata/index.d.ts +3 -0
- package/dist/userdata/index.js +3 -0
- package/dist/userdata/repository.d.ts +29 -0
- package/dist/userdata/repository.js +1 -0
- package/dist/userdata/types.d.ts +14 -0
- package/dist/userdata/types.js +3 -0
- package/package.json +11 -6
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { StateRepository } from '../core/state';
|
|
2
|
+
export interface ConfigRepository extends StateRepository {
|
|
3
|
+
/**
|
|
4
|
+
* Check if a config exists
|
|
5
|
+
*
|
|
6
|
+
* @param key name of the key containing the config
|
|
7
|
+
* @returns true if config exists
|
|
8
|
+
*/
|
|
9
|
+
has(key: string): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Get config from the state
|
|
12
|
+
*
|
|
13
|
+
* @param key name of the key containing the config
|
|
14
|
+
* @returns the config
|
|
15
|
+
*/
|
|
16
|
+
get<T = any>(key: string): T;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ConfigRepository as Service } from './repository';
|
|
2
|
+
declare const SERVICE_NAME = "state.configs";
|
|
3
|
+
declare module '../core/platform' {
|
|
4
|
+
interface PlatformServiceName {
|
|
5
|
+
/**
|
|
6
|
+
* @see {@link Service ConfigRepository}
|
|
7
|
+
*/
|
|
8
|
+
ConfigRepository: typeof SERVICE_NAME;
|
|
9
|
+
}
|
|
10
|
+
interface LimeWebComponentPlatform {
|
|
11
|
+
get(name: PlatformServiceName['ConfigRepository']): Service;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface for the context in which the Lime Web Component appears
|
|
3
|
+
*/
|
|
4
|
+
export interface LimeWebComponentContext {
|
|
5
|
+
/**
|
|
6
|
+
* The name of the limetype of the context
|
|
7
|
+
*/
|
|
8
|
+
limetype: string | null;
|
|
9
|
+
/**
|
|
10
|
+
* The id of the limeobject of the context
|
|
11
|
+
*/
|
|
12
|
+
id: number | null;
|
|
13
|
+
/**
|
|
14
|
+
* Optional parent context, if the current context is nested
|
|
15
|
+
*/
|
|
16
|
+
parent?: LimeWebComponentContext;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { LimeWebComponent, StateOptions } from '..';
|
|
2
|
+
declare type OptionFactory = (options: StateOptions, component: LimeWebComponent) => StateOptions;
|
|
3
|
+
export interface StateDecoratorConfig {
|
|
4
|
+
/**
|
|
5
|
+
* Name of the state service to use in the platform
|
|
6
|
+
*/
|
|
7
|
+
name: string;
|
|
8
|
+
/**
|
|
9
|
+
* Name of the method on the service to use
|
|
10
|
+
*/
|
|
11
|
+
method?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Factory for creating options dynamically
|
|
14
|
+
*
|
|
15
|
+
* @param {StateOptions} options decorator options
|
|
16
|
+
* @param {LimeWebComponent} component the web component
|
|
17
|
+
* @returns {StateOptions} state options
|
|
18
|
+
*/
|
|
19
|
+
optionFactory?: OptionFactory;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Create a new state decorator
|
|
23
|
+
*
|
|
24
|
+
* @param {StateOptions} options decorator options
|
|
25
|
+
* @param {StateDecoratorConfig} config decorator configuration
|
|
26
|
+
* @returns {Function} state decorator
|
|
27
|
+
*/
|
|
28
|
+
export declare function createStateDecorator(options: StateOptions, config: StateDecoratorConfig): PropertyDecorator;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { getElement } from '@stencil/core';
|
|
2
|
+
import { BehaviorSubject } from 'rxjs';
|
|
3
|
+
function defaultOptionFactory(options) {
|
|
4
|
+
return options;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Create a new state decorator
|
|
8
|
+
*
|
|
9
|
+
* @param {StateOptions} options decorator options
|
|
10
|
+
* @param {StateDecoratorConfig} config decorator configuration
|
|
11
|
+
* @returns {Function} state decorator
|
|
12
|
+
*/
|
|
13
|
+
export function createStateDecorator(options, config) {
|
|
14
|
+
return (target, property) => {
|
|
15
|
+
const properties = getComponentProperties(target, property, options, config);
|
|
16
|
+
if (properties.length === 1) {
|
|
17
|
+
extendLifecycleMethods(target, properties);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const componentProperties = new WeakMap();
|
|
22
|
+
const contexts = new WeakMap();
|
|
23
|
+
const contextObservables = new WeakMap();
|
|
24
|
+
const componentSubscriptions = new WeakMap();
|
|
25
|
+
const connectedComponents = new WeakMap();
|
|
26
|
+
/**
|
|
27
|
+
* Get properties data for a component
|
|
28
|
+
*
|
|
29
|
+
* @param {Component} component the component class containing the decorator
|
|
30
|
+
* @param {string} property name of the property
|
|
31
|
+
* @param {StateOptions} options decorator options
|
|
32
|
+
* @param {StateDecoratorConfig} config decorator configuration
|
|
33
|
+
* @returns {Property[]} properties data for the component
|
|
34
|
+
*/
|
|
35
|
+
function getComponentProperties(component, property, options, config) {
|
|
36
|
+
let properties = componentProperties.get(component);
|
|
37
|
+
if (!properties) {
|
|
38
|
+
properties = [];
|
|
39
|
+
componentProperties.set(component, properties);
|
|
40
|
+
}
|
|
41
|
+
properties.push({
|
|
42
|
+
options: options,
|
|
43
|
+
name: property,
|
|
44
|
+
optionFactory: config.optionFactory || defaultOptionFactory,
|
|
45
|
+
service: {
|
|
46
|
+
name: config.name,
|
|
47
|
+
method: config.method || 'subscribe',
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
return properties;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Extend the lifecycle methods on the component
|
|
54
|
+
*
|
|
55
|
+
* @param {Component} component the component to extend
|
|
56
|
+
* @param {Property[]} properties the properties with which to extend the component
|
|
57
|
+
* @returns {void}
|
|
58
|
+
*/
|
|
59
|
+
function extendLifecycleMethods(component, properties) {
|
|
60
|
+
// `componentWillLoad` and `componentDidUnload` is included for backwards
|
|
61
|
+
// compatibility reasons. The correct way to setup the subscriptions is in
|
|
62
|
+
// `connectedCallback` and `disconnectedCallback`, but since not all
|
|
63
|
+
// plugins might implement those methods yet we still have include them
|
|
64
|
+
// until we make `connectedCallback` and `disconnectedCallback` required
|
|
65
|
+
// on the interface.
|
|
66
|
+
component.connectedCallback = createConnectedCallback(component.connectedCallback, properties);
|
|
67
|
+
component.componentWillLoad = createComponentWillLoad(component.componentWillLoad, properties);
|
|
68
|
+
component.componentWillUpdate = createComponentWillUpdate(component.componentWillUpdate);
|
|
69
|
+
component.componentDidUnload = createDisconnectedCallback(component.componentDidUnload);
|
|
70
|
+
component.disconnectedCallback = createDisconnectedCallback(component.disconnectedCallback);
|
|
71
|
+
}
|
|
72
|
+
function createConnectedCallback(original, properties) {
|
|
73
|
+
return async function (...args) {
|
|
74
|
+
connectedComponents.set(this, true);
|
|
75
|
+
componentSubscriptions.set(this, []);
|
|
76
|
+
await ensureLimeProps(this);
|
|
77
|
+
const observable = new BehaviorSubject(this.context);
|
|
78
|
+
contexts.set(this, this.context);
|
|
79
|
+
contextObservables.set(this, observable);
|
|
80
|
+
properties.forEach((property) => {
|
|
81
|
+
property.options = property.optionFactory(property.options, this);
|
|
82
|
+
if (isContextAware(property.options)) {
|
|
83
|
+
property.options.context = observable;
|
|
84
|
+
}
|
|
85
|
+
subscribe(this, property);
|
|
86
|
+
});
|
|
87
|
+
if (original) {
|
|
88
|
+
return original.apply(this, args);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function createComponentWillLoad(original, properties) {
|
|
93
|
+
return async function (...args) {
|
|
94
|
+
if (connectedComponents.get(this) === true) {
|
|
95
|
+
await ensureLimeProps(this);
|
|
96
|
+
if (original) {
|
|
97
|
+
return original.apply(this, args);
|
|
98
|
+
}
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const connectedCallback = createConnectedCallback(original, properties);
|
|
102
|
+
return connectedCallback.apply(this, args);
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function createComponentWillUpdate(original) {
|
|
106
|
+
return async function (...args) {
|
|
107
|
+
const context = contexts.get(this);
|
|
108
|
+
if (context !== this.context) {
|
|
109
|
+
contexts.set(this, this.context);
|
|
110
|
+
const observable = contextObservables.get(this);
|
|
111
|
+
observable.next(this.context);
|
|
112
|
+
}
|
|
113
|
+
if (original) {
|
|
114
|
+
return original.apply(this, args);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function createDisconnectedCallback(original) {
|
|
119
|
+
return async function (...args) {
|
|
120
|
+
let result;
|
|
121
|
+
if (original) {
|
|
122
|
+
result = original.apply(this, args);
|
|
123
|
+
}
|
|
124
|
+
unsubscribeAll(this);
|
|
125
|
+
return result;
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Check if the options are context aware
|
|
130
|
+
*
|
|
131
|
+
* @param {object} options state decorator options
|
|
132
|
+
* @returns {boolean} true if the options are context aware
|
|
133
|
+
*/
|
|
134
|
+
function isContextAware(options) {
|
|
135
|
+
return 'context' in options;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Make sure that all required lime properties are set on the web component
|
|
139
|
+
*
|
|
140
|
+
* @param {LimeWebComponent} target the web component
|
|
141
|
+
* @returns {Promise<any>} a promise that resolves when all properties are defined
|
|
142
|
+
*/
|
|
143
|
+
function ensureLimeProps(target) {
|
|
144
|
+
const promises = [];
|
|
145
|
+
if (!target.platform) {
|
|
146
|
+
promises.push(waitForProp(target, 'platform'));
|
|
147
|
+
}
|
|
148
|
+
if (!target.context) {
|
|
149
|
+
promises.push(waitForProp(target, 'context'));
|
|
150
|
+
}
|
|
151
|
+
if (!promises.length) {
|
|
152
|
+
return Promise.resolve();
|
|
153
|
+
}
|
|
154
|
+
return Promise.all(promises);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Wait for a property to be defined on an object
|
|
158
|
+
*
|
|
159
|
+
* @param {LimeWebComponent} target the web component
|
|
160
|
+
* @param {string} property the name of the property to watch
|
|
161
|
+
* @returns {Promise<void>} a promise that will resolve when the property is set on the object
|
|
162
|
+
*/
|
|
163
|
+
function waitForProp(target, property) {
|
|
164
|
+
const element = getElement(target);
|
|
165
|
+
return new Promise((resolve) => {
|
|
166
|
+
Object.defineProperty(element, property, {
|
|
167
|
+
set: (value) => {
|
|
168
|
+
delete element[property];
|
|
169
|
+
element[property] = value;
|
|
170
|
+
resolve();
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Subscribe to changes from the state
|
|
177
|
+
*
|
|
178
|
+
* @param {any} component the component instance
|
|
179
|
+
* @param {Property} property property to update when subscription triggers
|
|
180
|
+
* @returns {void}
|
|
181
|
+
*/
|
|
182
|
+
function subscribe(component, property) {
|
|
183
|
+
const subscription = createSubscription(component, property);
|
|
184
|
+
const subscriptions = componentSubscriptions.get(component);
|
|
185
|
+
subscriptions.push(subscription);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Unsubscribe to changes from the state
|
|
189
|
+
*
|
|
190
|
+
* @param {any} component the instance of the component
|
|
191
|
+
* @returns {void}
|
|
192
|
+
*/
|
|
193
|
+
function unsubscribeAll(component) {
|
|
194
|
+
const subscriptions = componentSubscriptions.get(component);
|
|
195
|
+
subscriptions.forEach((unsubscribe) => unsubscribe());
|
|
196
|
+
componentSubscriptions.set(component, []);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Get a function that accepts a state, and updates the given property
|
|
200
|
+
* on the given component with that state
|
|
201
|
+
*
|
|
202
|
+
* @param {any} instance the component to augment
|
|
203
|
+
* @param {string} property name of the property on the component
|
|
204
|
+
* @returns {Function} updates the state
|
|
205
|
+
*/
|
|
206
|
+
function mapState(instance, property) {
|
|
207
|
+
return (state) => {
|
|
208
|
+
instance[property] = state;
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Create a state subscription
|
|
213
|
+
*
|
|
214
|
+
* @param {any} component the component instance
|
|
215
|
+
* @param {Property} property the property on the component
|
|
216
|
+
* @returns {Function} unsubscribe function
|
|
217
|
+
*/
|
|
218
|
+
function createSubscription(component, property) {
|
|
219
|
+
const myOptions = Object.assign({}, property.options);
|
|
220
|
+
bindFunctions(myOptions, component);
|
|
221
|
+
const name = property.service.name;
|
|
222
|
+
const platform = component.platform;
|
|
223
|
+
if (!platform.has(name)) {
|
|
224
|
+
throw new Error(`Service ${name} does not exist`);
|
|
225
|
+
}
|
|
226
|
+
const service = platform.get(name);
|
|
227
|
+
return service[property.service.method](mapState(component, property.name), myOptions);
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Bind connect functions to the current scope
|
|
231
|
+
*
|
|
232
|
+
* @param {StateOptions} options options for the selector
|
|
233
|
+
* @param {*} scope the current scope to bind to
|
|
234
|
+
* @returns {void}
|
|
235
|
+
*/
|
|
236
|
+
function bindFunctions(options, scope) {
|
|
237
|
+
if (options.filter) {
|
|
238
|
+
options.filter = options.filter.map((func) => func.bind(scope));
|
|
239
|
+
}
|
|
240
|
+
if (options.map) {
|
|
241
|
+
options.map = options.map.map((func) => func.bind(scope));
|
|
242
|
+
}
|
|
243
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
/* eslint-disable max-classes-per-file */
|
|
3
|
+
let getElement;
|
|
4
|
+
jest.mock('@stencil/core', () => {
|
|
5
|
+
const original = jest.requireActual('@stencil/core');
|
|
6
|
+
return Object.assign(Object.assign({}, original), { getElement: () => getElement() });
|
|
7
|
+
});
|
|
8
|
+
import { createStateDecorator } from './factory';
|
|
9
|
+
import { Subject } from 'rxjs';
|
|
10
|
+
import { take } from 'rxjs/operators';
|
|
11
|
+
describe('createStateDecorator', () => {
|
|
12
|
+
let platform;
|
|
13
|
+
let context;
|
|
14
|
+
let service;
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
service = new TestService();
|
|
17
|
+
const services = {
|
|
18
|
+
test: service,
|
|
19
|
+
};
|
|
20
|
+
platform = {
|
|
21
|
+
has: jest.fn((name) => name in services),
|
|
22
|
+
get: jest.fn((name) => services[name]),
|
|
23
|
+
};
|
|
24
|
+
context = {};
|
|
25
|
+
});
|
|
26
|
+
describe('when using a state decorator on a property', () => {
|
|
27
|
+
it('adds required lifecycle hooks on the component', () => {
|
|
28
|
+
const Decorator = () => createStateDecorator({}, { name: 'test' });
|
|
29
|
+
class MyComponent {
|
|
30
|
+
}
|
|
31
|
+
__decorate([
|
|
32
|
+
Decorator()
|
|
33
|
+
], MyComponent.prototype, "foo", void 0);
|
|
34
|
+
const component = new MyComponent();
|
|
35
|
+
expect(typeof component.connectedCallback).toEqual('function');
|
|
36
|
+
expect(typeof component.componentWillLoad).toEqual('function');
|
|
37
|
+
expect(typeof component.componentWillUpdate).toEqual('function');
|
|
38
|
+
expect(typeof component.componentDidUnload).toEqual('function');
|
|
39
|
+
expect(typeof component.disconnectedCallback).toEqual('function');
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
describe('when more than one property is decorated', () => {
|
|
43
|
+
it('only extends the lifecycle methods once', () => {
|
|
44
|
+
const Decorator = () => createStateDecorator({}, { name: 'test' });
|
|
45
|
+
class MyComponent {
|
|
46
|
+
}
|
|
47
|
+
__decorate([
|
|
48
|
+
Decorator()
|
|
49
|
+
], MyComponent.prototype, "foo", void 0);
|
|
50
|
+
const component = new MyComponent();
|
|
51
|
+
const connectedCallback = component.connectedCallback;
|
|
52
|
+
const componentWillLoad = component.componentWillLoad;
|
|
53
|
+
const componentWillUpdate = component.componentWillUpdate;
|
|
54
|
+
const componentDidUnload = component.componentDidUnload;
|
|
55
|
+
const disconnectedCallback = component.disconnectedCallback;
|
|
56
|
+
Decorator()(MyComponent.prototype, 'bar');
|
|
57
|
+
expect(component.connectedCallback).toEqual(connectedCallback);
|
|
58
|
+
expect(component.componentWillLoad).toEqual(componentWillLoad);
|
|
59
|
+
expect(component.componentWillUpdate).toEqual(componentWillUpdate);
|
|
60
|
+
expect(component.componentDidUnload).toEqual(componentDidUnload);
|
|
61
|
+
expect(component.disconnectedCallback).toEqual(disconnectedCallback);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
describe('when lifecycle hooks already exist', () => {
|
|
65
|
+
it('overwrites the lifecycle hooks', () => {
|
|
66
|
+
const Decorator = () => createStateDecorator({}, { name: 'test' });
|
|
67
|
+
class MyComponent {
|
|
68
|
+
connectedCallback() { }
|
|
69
|
+
componentWillLoad() { }
|
|
70
|
+
componentWillUpdate() { }
|
|
71
|
+
componentDidUnload() { }
|
|
72
|
+
disconnectedCallback() { }
|
|
73
|
+
}
|
|
74
|
+
const component = new MyComponent();
|
|
75
|
+
const connectedCallback = component.connectedCallback;
|
|
76
|
+
const componentWillLoad = component.componentWillLoad;
|
|
77
|
+
const componentWillUpdate = component.componentWillUpdate;
|
|
78
|
+
const componentDidUnload = component.componentDidUnload;
|
|
79
|
+
const disconnectedCallback = component.disconnectedCallback;
|
|
80
|
+
Decorator()(MyComponent.prototype, 'foo');
|
|
81
|
+
expect(component.connectedCallback).not.toEqual(connectedCallback);
|
|
82
|
+
expect(component.componentWillLoad).not.toEqual(componentWillLoad);
|
|
83
|
+
expect(component.componentWillUpdate).not.toEqual(componentWillUpdate);
|
|
84
|
+
expect(component.componentDidUnload).not.toEqual(componentDidUnload);
|
|
85
|
+
expect(component.disconnectedCallback).not.toEqual(disconnectedCallback);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe('when invoking connectedCallback without required properties', () => {
|
|
89
|
+
let component;
|
|
90
|
+
let element;
|
|
91
|
+
beforeEach(() => {
|
|
92
|
+
const Decorator = () => createStateDecorator({}, { name: 'test' });
|
|
93
|
+
class MyComponent {
|
|
94
|
+
}
|
|
95
|
+
__decorate([
|
|
96
|
+
Decorator()
|
|
97
|
+
], MyComponent.prototype, "foo", void 0);
|
|
98
|
+
component = new MyComponent();
|
|
99
|
+
element = { platform: null, context: null };
|
|
100
|
+
getElement = () => element;
|
|
101
|
+
});
|
|
102
|
+
it('returns a promise that does not resolve', () => {
|
|
103
|
+
expect.assertions(0);
|
|
104
|
+
component.connectedCallback().then(() => {
|
|
105
|
+
expect(false).toBeTruthy();
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
it('returns a promise that resolves when platform and context has been set', () => {
|
|
109
|
+
expect.assertions(1);
|
|
110
|
+
component.connectedCallback().then(() => {
|
|
111
|
+
expect(true).toBeTruthy();
|
|
112
|
+
});
|
|
113
|
+
component.platform = platform;
|
|
114
|
+
component.context = context;
|
|
115
|
+
element.platform = platform;
|
|
116
|
+
element.context = context;
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
describe('when invoking componentWillLoad without required properties', () => {
|
|
120
|
+
let component;
|
|
121
|
+
let element;
|
|
122
|
+
let spy;
|
|
123
|
+
beforeEach(() => {
|
|
124
|
+
spy = jest.fn(() => { });
|
|
125
|
+
const Decorator = () => createStateDecorator({}, { name: 'test' });
|
|
126
|
+
class MyComponent {
|
|
127
|
+
componentWillLoad() {
|
|
128
|
+
spy();
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
__decorate([
|
|
132
|
+
Decorator()
|
|
133
|
+
], MyComponent.prototype, "foo", void 0);
|
|
134
|
+
component = new MyComponent();
|
|
135
|
+
element = { platform: null, context: null };
|
|
136
|
+
getElement = () => element;
|
|
137
|
+
});
|
|
138
|
+
it('returns a promise that does not resolve', () => {
|
|
139
|
+
expect.assertions(0);
|
|
140
|
+
component.connectedCallback();
|
|
141
|
+
component.componentWillLoad().then(() => {
|
|
142
|
+
expect(false).toBeTruthy();
|
|
143
|
+
expect(spy).not.toHaveBeenCalled();
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
it('returns a promise that resolves when platform and context has been set', () => {
|
|
147
|
+
expect.assertions(3);
|
|
148
|
+
component.connectedCallback();
|
|
149
|
+
component.componentWillLoad().then(() => {
|
|
150
|
+
expect(true).toBeTruthy();
|
|
151
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
152
|
+
});
|
|
153
|
+
expect(spy).toHaveBeenCalledTimes(0);
|
|
154
|
+
component.platform = platform;
|
|
155
|
+
component.context = context;
|
|
156
|
+
element.platform = platform;
|
|
157
|
+
element.context = context;
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
describe('when invoking connectedCallback or componentWillLoad with required properties', () => {
|
|
161
|
+
let component;
|
|
162
|
+
beforeEach(() => {
|
|
163
|
+
component = createComponent();
|
|
164
|
+
});
|
|
165
|
+
it('creates a subscription on the service', async () => {
|
|
166
|
+
await component.connectedCallback();
|
|
167
|
+
expect(service.getSubscriptions().length).toEqual(1);
|
|
168
|
+
});
|
|
169
|
+
it('creates a subscription on the service', async () => {
|
|
170
|
+
await component.componentWillLoad();
|
|
171
|
+
expect(service.getSubscriptions().length).toEqual(1);
|
|
172
|
+
});
|
|
173
|
+
describe('when invoking both connectedCallback and componentWillLoad', () => {
|
|
174
|
+
it('creates only one subscription on the service', async () => {
|
|
175
|
+
await component.connectedCallback();
|
|
176
|
+
await component.componentWillLoad();
|
|
177
|
+
expect(service.getSubscriptions().length).toEqual(1);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
describe('when multiple properties are decorated', () => {
|
|
182
|
+
let component;
|
|
183
|
+
beforeEach(() => {
|
|
184
|
+
component = createComponent({ foo: true, bar: true });
|
|
185
|
+
});
|
|
186
|
+
it('connectedCallback creates a subscription for each property', async () => {
|
|
187
|
+
await component.connectedCallback();
|
|
188
|
+
expect(service.getSubscriptions().length).toEqual(2);
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
describe('when invoking disconnectedCallback', () => {
|
|
192
|
+
let component;
|
|
193
|
+
beforeEach(async () => {
|
|
194
|
+
component = createComponent({ foo: true, bar: true });
|
|
195
|
+
await component.connectedCallback();
|
|
196
|
+
});
|
|
197
|
+
it('removes the subscriptions', () => {
|
|
198
|
+
expect(service.getSubscriptions().length).toEqual(2);
|
|
199
|
+
component.disconnectedCallback();
|
|
200
|
+
expect(service.getSubscriptions().length).toEqual(0);
|
|
201
|
+
});
|
|
202
|
+
describe('when invoked multiple times', () => {
|
|
203
|
+
it('does not crash', async () => {
|
|
204
|
+
expect(service.getSubscriptions().length).toEqual(2);
|
|
205
|
+
component.disconnectedCallback();
|
|
206
|
+
expect(service.getSubscriptions().length).toEqual(0);
|
|
207
|
+
expect(() => component.disconnectedCallback()).not.toThrow();
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
describe('when a component is inserted in the DOM again after being removed', () => {
|
|
211
|
+
it('creates a subscription on the service again', async () => {
|
|
212
|
+
expect(service.getSubscriptions().length).toEqual(2);
|
|
213
|
+
component.disconnectedCallback();
|
|
214
|
+
expect(service.getSubscriptions().length).toEqual(0);
|
|
215
|
+
await component.connectedCallback();
|
|
216
|
+
expect(service.getSubscriptions().length).toEqual(2);
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
describe('when context is set on options', () => {
|
|
221
|
+
let component;
|
|
222
|
+
let options;
|
|
223
|
+
beforeEach(async () => {
|
|
224
|
+
options = { context: null };
|
|
225
|
+
component = createComponent({ foo: true, bar: true }, options);
|
|
226
|
+
await component.connectedCallback();
|
|
227
|
+
});
|
|
228
|
+
it('sets the context option to an observable', () => {
|
|
229
|
+
expect(options.context).toBeInstanceOf(Subject);
|
|
230
|
+
});
|
|
231
|
+
describe('when componentWillUpdate is invoked without a context change', () => {
|
|
232
|
+
it('does not emit a value on the observable', async () => {
|
|
233
|
+
const spy = jest.spyOn(options.context, 'next');
|
|
234
|
+
await component.componentWillUpdate();
|
|
235
|
+
expect(spy).not.toHaveBeenCalled();
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
describe('when componentWillUpdate is invoked with a context change', () => {
|
|
239
|
+
it('emits a value on the observable', async () => {
|
|
240
|
+
const spy = jest.spyOn(options.context, 'next');
|
|
241
|
+
component.context = 'new context';
|
|
242
|
+
await component.componentWillUpdate();
|
|
243
|
+
expect(spy).toHaveBeenCalled();
|
|
244
|
+
const subject = options.context;
|
|
245
|
+
const value = await subject.pipe(take(1)).toPromise();
|
|
246
|
+
expect(value).toEqual('new context');
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
describe('when component has lifecycle methods', () => {
|
|
251
|
+
let component;
|
|
252
|
+
let options;
|
|
253
|
+
let methods;
|
|
254
|
+
beforeEach(async () => {
|
|
255
|
+
options = { context: null };
|
|
256
|
+
methods = {
|
|
257
|
+
connectedCallback: jest.fn(),
|
|
258
|
+
componentWillLoad: jest.fn(),
|
|
259
|
+
componentWillUpdate: jest.fn(),
|
|
260
|
+
componentDidUnload: jest.fn(),
|
|
261
|
+
disconnectedCallback: jest.fn(),
|
|
262
|
+
};
|
|
263
|
+
component = createComponent({ foo: true, bar: true }, options, methods);
|
|
264
|
+
});
|
|
265
|
+
it('connectedCallback invokes the original connectedCallback', async () => {
|
|
266
|
+
expect(methods.connectedCallback).toHaveBeenCalledTimes(0);
|
|
267
|
+
expect(component.connectedCallback).not.toEqual(methods.connectedCallback);
|
|
268
|
+
await component.connectedCallback();
|
|
269
|
+
expect(methods.connectedCallback).toHaveBeenCalledTimes(1);
|
|
270
|
+
});
|
|
271
|
+
it('componentWillLoad invokes the original componentWillLoad', async () => {
|
|
272
|
+
expect(methods.componentWillLoad).toHaveBeenCalledTimes(0);
|
|
273
|
+
expect(component.componentWillLoad).not.toEqual(methods.componentWillLoad);
|
|
274
|
+
await component.componentWillLoad();
|
|
275
|
+
expect(methods.componentWillLoad).toHaveBeenCalledTimes(1);
|
|
276
|
+
});
|
|
277
|
+
describe('when connectedCallback is invoked first', () => {
|
|
278
|
+
it('componentWillLoad invkoes the original componentWillLoad', async () => {
|
|
279
|
+
expect(methods.componentWillLoad).toHaveBeenCalledTimes(0);
|
|
280
|
+
expect(component.componentWillLoad).not.toEqual(methods.componentWillLoad);
|
|
281
|
+
await component.connectedCallback();
|
|
282
|
+
await component.componentWillLoad();
|
|
283
|
+
expect(methods.componentWillLoad).toHaveBeenCalledTimes(1);
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
it('componentWillUpdate invokes the original componentWillUpdate', async () => {
|
|
287
|
+
expect(methods.componentWillUpdate).toHaveBeenCalledTimes(0);
|
|
288
|
+
expect(component.componentWillUpdate).not.toEqual(methods.componentWillUpdate);
|
|
289
|
+
await component.connectedCallback();
|
|
290
|
+
component.componentWillUpdate();
|
|
291
|
+
expect(methods.componentWillUpdate).toHaveBeenCalledTimes(1);
|
|
292
|
+
});
|
|
293
|
+
it('componentDidUnload invokes the original componentDidUnload', async () => {
|
|
294
|
+
expect(methods.componentDidUnload).toHaveBeenCalledTimes(0);
|
|
295
|
+
expect(component.componentDidUnload).not.toEqual(methods.componentDidUnload);
|
|
296
|
+
await component.connectedCallback();
|
|
297
|
+
component.componentDidUnload();
|
|
298
|
+
expect(methods.componentDidUnload).toHaveBeenCalledTimes(1);
|
|
299
|
+
});
|
|
300
|
+
it('disconnectedCallback invokes the original disconnectedCallback', async () => {
|
|
301
|
+
expect(methods.disconnectedCallback).toHaveBeenCalledTimes(0);
|
|
302
|
+
expect(component.disconnectedCallback).not.toEqual(methods.disconnectedCallback);
|
|
303
|
+
await component.connectedCallback();
|
|
304
|
+
component.disconnectedCallback();
|
|
305
|
+
expect(methods.disconnectedCallback).toHaveBeenCalledTimes(1);
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
function createComponent(props = { foo: 'bar' }, options = {}, methods = {}) {
|
|
309
|
+
const Decorator = (o) => createStateDecorator(o, { name: 'test' });
|
|
310
|
+
class MyComponent {
|
|
311
|
+
}
|
|
312
|
+
Object.keys(methods).forEach((method) => {
|
|
313
|
+
MyComponent.prototype[method] = methods[method];
|
|
314
|
+
});
|
|
315
|
+
const component = new MyComponent();
|
|
316
|
+
component.platform = platform;
|
|
317
|
+
component.context = context;
|
|
318
|
+
Object.keys(props).forEach((key) => {
|
|
319
|
+
Decorator(options)(MyComponent.prototype, key);
|
|
320
|
+
});
|
|
321
|
+
return component;
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
class TestService {
|
|
325
|
+
constructor() {
|
|
326
|
+
this.subscriptions = [];
|
|
327
|
+
}
|
|
328
|
+
subscribe(...args) {
|
|
329
|
+
this.subscriptions.push(args);
|
|
330
|
+
return () => {
|
|
331
|
+
this.subscriptions = this.subscriptions.filter((item) => item !== args);
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
getSubscriptions() {
|
|
335
|
+
return this.subscriptions;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { StateDecoratorConfig } from './factory';
|