velocious 1.0.396 → 1.0.397
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/README.md +12 -0
- package/build/src/database/record/instance-relationships/has-many.d.ts +2 -0
- package/build/src/database/record/instance-relationships/has-many.d.ts.map +1 -1
- package/build/src/database/record/instance-relationships/has-many.js +13 -1
- package/build/src/frontend-models/clear-pending-debounced-callback.d.ts +6 -0
- package/build/src/frontend-models/clear-pending-debounced-callback.d.ts.map +1 -0
- package/build/src/frontend-models/clear-pending-debounced-callback.js +12 -0
- package/build/src/frontend-models/event-hook-models.d.ts +12 -0
- package/build/src/frontend-models/event-hook-models.d.ts.map +1 -0
- package/build/src/frontend-models/event-hook-models.js +37 -0
- package/build/src/frontend-models/use-created-event.d.ts +17 -0
- package/build/src/frontend-models/use-created-event.d.ts.map +1 -0
- package/build/src/frontend-models/use-created-event.js +19 -0
- package/build/src/frontend-models/use-destroyed-event.d.ts +19 -0
- package/build/src/frontend-models/use-destroyed-event.d.ts.map +1 -0
- package/build/src/frontend-models/use-destroyed-event.js +99 -0
- package/build/src/frontend-models/use-model-class-event.d.ts +27 -0
- package/build/src/frontend-models/use-model-class-event.d.ts.map +1 -0
- package/build/src/frontend-models/use-model-class-event.js +112 -0
- package/build/src/frontend-models/use-updated-event.d.ts +20 -0
- package/build/src/frontend-models/use-updated-event.d.ts.map +1 -0
- package/build/src/frontend-models/use-updated-event.js +101 -0
- package/build/src/testing/browser-frontend-model-event-hook-scenarios.d.ts +35 -0
- package/build/src/testing/browser-frontend-model-event-hook-scenarios.d.ts.map +1 -0
- package/build/src/testing/browser-frontend-model-event-hook-scenarios.js +259 -0
- package/build/src/testing/browser-test-app.js +3 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hook for frontend-model update events. Pass a model class for class-level
|
|
3
|
+
* update events, or a model / model array for instance-level update events.
|
|
4
|
+
* @param {FrontendModelClass | FrontendModelInstance | FrontendModelInstance[] | null | undefined} modelClassOrModels - Model class, model, or models.
|
|
5
|
+
* @param {FrontendModelUpdateEventCallback} callback - Event callback.
|
|
6
|
+
* @param {UseUpdatedEventOptions} [options] - Hook options.
|
|
7
|
+
* @returns {void}
|
|
8
|
+
*/
|
|
9
|
+
export default function useUpdatedEvent(modelClassOrModels: FrontendModelClass | FrontendModelInstance | FrontendModelInstance[] | null | undefined, callback: FrontendModelUpdateEventCallback, options?: UseUpdatedEventOptions): void;
|
|
10
|
+
export type FrontendModelClass = typeof import("./base.js").default;
|
|
11
|
+
export type FrontendModelInstance = import("./base.js").default;
|
|
12
|
+
export type FrontendModelClassUpdateEventPayload = import("./use-model-class-event.js").FrontendModelCreateUpdateEventPayload;
|
|
13
|
+
export type FrontendModelInstanceUpdateEventPayload = {
|
|
14
|
+
id: string;
|
|
15
|
+
model: FrontendModelInstance;
|
|
16
|
+
};
|
|
17
|
+
export type FrontendModelUpdateEventPayload = FrontendModelClassUpdateEventPayload | FrontendModelInstanceUpdateEventPayload;
|
|
18
|
+
export type UseUpdatedEventOptions = import("./use-model-class-event.js").UseModelClassEventOptions;
|
|
19
|
+
export type FrontendModelUpdateEventCallback = (payload: FrontendModelUpdateEventPayload) => void;
|
|
20
|
+
//# sourceMappingURL=use-updated-event.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-updated-event.d.ts","sourceRoot":"","sources":["../../../src/frontend-models/use-updated-event.js"],"names":[],"mappings":"AA6BA;;;;;;;GAOG;AACH,4DALW,kBAAkB,GAAG,qBAAqB,GAAG,qBAAqB,EAAE,GAAG,IAAI,GAAG,SAAS,YACvF,gCAAgC,YAChC,sBAAsB,GACpB,IAAI,CAahB;iCAvCa,cAAc,WAAW,EAAE,OAAO;oCAClC,OAAO,WAAW,EAAE,OAAO;mDAC3B,OAAO,4BAA4B,EAAE,qCAAqC;sDAC1E;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,qBAAqB,CAAA;CAAC;8CAC1C,oCAAoC,GAAG,uCAAuC;qCAC9E,OAAO,4BAA4B,EAAE,yBAAyB;+CAC9D,CAAC,OAAO,EAAE,+BAA+B,KAAK,IAAI"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import debounceFunction from "debounce";
|
|
3
|
+
import { useEffect, useMemo, useRef } from "react";
|
|
4
|
+
import clearPendingDebouncedCallback from "./clear-pending-debounced-callback.js";
|
|
5
|
+
import { modelsDependencyKey, modelsFromInput } from "./event-hook-models.js";
|
|
6
|
+
import useModelClassEvent from "./use-model-class-event.js";
|
|
7
|
+
/** @typedef {typeof import("./base.js").default} FrontendModelClass */
|
|
8
|
+
/** @typedef {import("./base.js").default} FrontendModelInstance */
|
|
9
|
+
/** @typedef {import("./use-model-class-event.js").FrontendModelCreateUpdateEventPayload} FrontendModelClassUpdateEventPayload */
|
|
10
|
+
/** @typedef {{id: string, model: FrontendModelInstance}} FrontendModelInstanceUpdateEventPayload */
|
|
11
|
+
/** @typedef {FrontendModelClassUpdateEventPayload | FrontendModelInstanceUpdateEventPayload} FrontendModelUpdateEventPayload */
|
|
12
|
+
/** @typedef {import("./use-model-class-event.js").UseModelClassEventOptions} UseUpdatedEventOptions */
|
|
13
|
+
/** @typedef {(payload: FrontendModelUpdateEventPayload) => void} FrontendModelUpdateEventCallback */
|
|
14
|
+
/**
|
|
15
|
+
* @param {Record<string, unknown>} restOptions - Unknown options object.
|
|
16
|
+
* @returns {void}
|
|
17
|
+
*/
|
|
18
|
+
function assertNoUnknownOptions(restOptions) {
|
|
19
|
+
const unknownOptionNames = Object.keys(restOptions);
|
|
20
|
+
if (unknownOptionNames.length > 0) {
|
|
21
|
+
throw new Error(`Unknown options given to useUpdatedEvent: ${unknownOptionNames.join(", ")}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* React hook for frontend-model update events. Pass a model class for class-level
|
|
26
|
+
* update events, or a model / model array for instance-level update events.
|
|
27
|
+
* @param {FrontendModelClass | FrontendModelInstance | FrontendModelInstance[] | null | undefined} modelClassOrModels - Model class, model, or models.
|
|
28
|
+
* @param {FrontendModelUpdateEventCallback} callback - Event callback.
|
|
29
|
+
* @param {UseUpdatedEventOptions} [options] - Hook options.
|
|
30
|
+
* @returns {void}
|
|
31
|
+
*/
|
|
32
|
+
export default function useUpdatedEvent(modelClassOrModels, callback, options = {}) {
|
|
33
|
+
const { active = true, debounce = false, onConnected, ...restOptions } = options;
|
|
34
|
+
assertNoUnknownOptions(restOptions);
|
|
35
|
+
const classModel = typeof modelClassOrModels === "function" ? modelClassOrModels : null;
|
|
36
|
+
const instanceModels = typeof modelClassOrModels === "function" ? null : modelClassOrModels;
|
|
37
|
+
useModelClassEvent(classModel, "update", (payload) => {
|
|
38
|
+
callback(/** @type {FrontendModelClassUpdateEventPayload} */ (payload));
|
|
39
|
+
}, { active: active && Boolean(classModel), debounce, onConnected });
|
|
40
|
+
useInstanceUpdatedEvent(instanceModels, callback, { active: active && !classModel, debounce, onConnected });
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* @param {FrontendModelInstance | FrontendModelInstance[] | null | undefined} modelOrModels - Model or models.
|
|
44
|
+
* @param {FrontendModelUpdateEventCallback} callback - Event callback.
|
|
45
|
+
* @param {UseUpdatedEventOptions} options - Hook options.
|
|
46
|
+
* @returns {void}
|
|
47
|
+
*/
|
|
48
|
+
function useInstanceUpdatedEvent(modelOrModels, callback, options) {
|
|
49
|
+
const { active = true, debounce = false, onConnected } = options;
|
|
50
|
+
const callbackRef = useRef(callback);
|
|
51
|
+
const activeRef = useRef(active);
|
|
52
|
+
callbackRef.current = callback;
|
|
53
|
+
activeRef.current = active;
|
|
54
|
+
const modelsKey = modelsDependencyKey(modelOrModels);
|
|
55
|
+
const eventCallback = useMemo(() => {
|
|
56
|
+
const wrappedCallback = (/** @type {FrontendModelInstanceUpdateEventPayload} */ payload) => {
|
|
57
|
+
if (activeRef.current)
|
|
58
|
+
callbackRef.current(payload);
|
|
59
|
+
};
|
|
60
|
+
if (typeof debounce === "number")
|
|
61
|
+
return debounceFunction(wrappedCallback, debounce);
|
|
62
|
+
if (debounce)
|
|
63
|
+
return debounceFunction(wrappedCallback);
|
|
64
|
+
return wrappedCallback;
|
|
65
|
+
}, [debounce]);
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (!active)
|
|
68
|
+
return undefined;
|
|
69
|
+
const models = modelsFromInput(modelOrModels);
|
|
70
|
+
if (models.length < 1)
|
|
71
|
+
return undefined;
|
|
72
|
+
let closed = false;
|
|
73
|
+
/** @type {Array<() => void>} */
|
|
74
|
+
const unsubscribeCallbacks = [];
|
|
75
|
+
const subscriptionCallback = (/** @type {FrontendModelInstanceUpdateEventPayload} */ payload) => {
|
|
76
|
+
if (!closed)
|
|
77
|
+
eventCallback(payload);
|
|
78
|
+
};
|
|
79
|
+
void (async () => {
|
|
80
|
+
for (const model of models) {
|
|
81
|
+
const unsubscribe = await model.onUpdate(subscriptionCallback);
|
|
82
|
+
if (closed) {
|
|
83
|
+
unsubscribe();
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
unsubscribeCallbacks.push(unsubscribe);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (!closed && onConnected)
|
|
90
|
+
onConnected();
|
|
91
|
+
})();
|
|
92
|
+
return () => {
|
|
93
|
+
closed = true;
|
|
94
|
+
for (const unsubscribe of unsubscribeCallbacks) {
|
|
95
|
+
unsubscribe();
|
|
96
|
+
}
|
|
97
|
+
clearPendingDebouncedCallback(eventCallback);
|
|
98
|
+
};
|
|
99
|
+
}, [active, eventCallback, modelsKey, onConnected]);
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlLXVwZGF0ZWQtZXZlbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZnJvbnRlbmQtbW9kZWxzL3VzZS11cGRhdGVkLWV2ZW50LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLGdCQUFnQixNQUFNLFVBQVUsQ0FBQTtBQUN2QyxPQUFPLEVBQUMsU0FBUyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUMsTUFBTSxPQUFPLENBQUE7QUFFaEQsT0FBTyw2QkFBNkIsTUFBTSx1Q0FBdUMsQ0FBQTtBQUNqRixPQUFPLEVBQUMsbUJBQW1CLEVBQUUsZUFBZSxFQUFDLE1BQU0sd0JBQXdCLENBQUE7QUFDM0UsT0FBTyxrQkFBa0IsTUFBTSw0QkFBNEIsQ0FBQTtBQUUzRCx1RUFBdUU7QUFDdkUsbUVBQW1FO0FBQ25FLGlJQUFpSTtBQUNqSSxvR0FBb0c7QUFDcEcsZ0lBQWdJO0FBQ2hJLHVHQUF1RztBQUN2RyxxR0FBcUc7QUFFckc7OztHQUdHO0FBQ0gsU0FBUyxzQkFBc0IsQ0FBQyxXQUFXO0lBQ3pDLE1BQU0sa0JBQWtCLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQTtJQUVuRCxJQUFJLGtCQUFrQixDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNsQyxNQUFNLElBQUksS0FBSyxDQUFDLDZDQUE2QyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFBO0lBQy9GLENBQUM7QUFDSCxDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILE1BQU0sQ0FBQyxPQUFPLFVBQVUsZUFBZSxDQUFDLGtCQUFrQixFQUFFLFFBQVEsRUFBRSxPQUFPLEdBQUcsRUFBRTtJQUNoRixNQUFNLEVBQUMsTUFBTSxHQUFHLElBQUksRUFBRSxRQUFRLEdBQUcsS0FBSyxFQUFFLFdBQVcsRUFBRSxHQUFHLFdBQVcsRUFBQyxHQUFHLE9BQU8sQ0FBQTtJQUM5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RSxDQUFBO2dCQUNmLENBQUM7cUJBQU0sQ0FBQztvQkFDTixvQkFBb0IsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUE7Z0JBQ3hDLENBQUM7WUFDSCxDQUFDO1lBRUQsSUFBSSxDQUFDLE1BQU0sSUFBSSxXQUFXO2dCQUFFLFdBQVcsRUFBRSxDQUFBO1FBQzNDLENBQUMsQ0FBQyxFQUFFLENBQUE7UUFFSixPQUFPLEdBQUcsRUFBRTtZQUNWLE1BQU0sR0FBRyxJQUFJLENBQUE7WUFFYixLQUFLLE1BQU0sV0FBVyxJQUFJLG9CQUFvQixFQUFFLENBQUM7Z0JBQy9DLFdBQVcsRUFBRSxDQUFBO1lBQ2YsQ0FBQztZQUVELDZCQUE2QixDQUFDLGFBQWEsQ0FBQyxDQUFBO1FBQzlDLENBQUMsQ0FBQTtJQUNILENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxhQUFhLEVBQUUsU0FBUyxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUE7QUFDckQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgZGVib3VuY2VGdW5jdGlvbiBmcm9tIFwiZGVib3VuY2VcIlxuaW1wb3J0IHt1c2VFZmZlY3QsIHVzZU1lbW8sIHVzZVJlZn0gZnJvbSBcInJlYWN0XCJcblxuaW1wb3J0IGNsZWFyUGVuZGluZ0RlYm91bmNlZENhbGxiYWNrIGZyb20gXCIuL2NsZWFyLXBlbmRpbmctZGVib3VuY2VkLWNhbGxiYWNrLmpzXCJcbmltcG9ydCB7bW9kZWxzRGVwZW5kZW5jeUtleSwgbW9kZWxzRnJvbUlucHV0fSBmcm9tIFwiLi9ldmVudC1ob29rLW1vZGVscy5qc1wiXG5pbXBvcnQgdXNlTW9kZWxDbGFzc0V2ZW50IGZyb20gXCIuL3VzZS1tb2RlbC1jbGFzcy1ldmVudC5qc1wiXG5cbi8qKiBAdHlwZWRlZiB7dHlwZW9mIGltcG9ydChcIi4vYmFzZS5qc1wiKS5kZWZhdWx0fSBGcm9udGVuZE1vZGVsQ2xhc3MgKi9cbi8qKiBAdHlwZWRlZiB7aW1wb3J0KFwiLi9iYXNlLmpzXCIpLmRlZmF1bHR9IEZyb250ZW5kTW9kZWxJbnN0YW5jZSAqL1xuLyoqIEB0eXBlZGVmIHtpbXBvcnQoXCIuL3VzZS1tb2RlbC1jbGFzcy1ldmVudC5qc1wiKS5Gcm9udGVuZE1vZGVsQ3JlYXRlVXBkYXRlRXZlbnRQYXlsb2FkfSBGcm9udGVuZE1vZGVsQ2xhc3NVcGRhdGVFdmVudFBheWxvYWQgKi9cbi8qKiBAdHlwZWRlZiB7e2lkOiBzdHJpbmcsIG1vZGVsOiBGcm9udGVuZE1vZGVsSW5zdGFuY2V9fSBGcm9udGVuZE1vZGVsSW5zdGFuY2VVcGRhdGVFdmVudFBheWxvYWQgKi9cbi8qKiBAdHlwZWRlZiB7RnJvbnRlbmRNb2RlbENsYXNzVXBkYXRlRXZlbnRQYXlsb2FkIHwgRnJvbnRlbmRNb2RlbEluc3RhbmNlVXBkYXRlRXZlbnRQYXlsb2FkfSBGcm9udGVuZE1vZGVsVXBkYXRlRXZlbnRQYXlsb2FkICovXG4vKiogQHR5cGVkZWYge2ltcG9ydChcIi4vdXNlLW1vZGVsLWNsYXNzLWV2ZW50LmpzXCIpLlVzZU1vZGVsQ2xhc3NFdmVudE9wdGlvbnN9IFVzZVVwZGF0ZWRFdmVudE9wdGlvbnMgKi9cbi8qKiBAdHlwZWRlZiB7KHBheWxvYWQ6IEZyb250ZW5kTW9kZWxVcGRhdGVFdmVudFBheWxvYWQpID0+IHZvaWR9IEZyb250ZW5kTW9kZWxVcGRhdGVFdmVudENhbGxiYWNrICovXG5cbi8qKlxuICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCB1bmtub3duPn0gcmVzdE9wdGlvbnMgLSBVbmtub3duIG9wdGlvbnMgb2JqZWN0LlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIGFzc2VydE5vVW5rbm93bk9wdGlvbnMocmVzdE9wdGlvbnMpIHtcbiAgY29uc3QgdW5rbm93bk9wdGlvbk5hbWVzID0gT2JqZWN0LmtleXMocmVzdE9wdGlvbnMpXG5cbiAgaWYgKHVua25vd25PcHRpb25OYW1lcy5sZW5ndGggPiAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIG9wdGlvbnMgZ2l2ZW4gdG8gdXNlVXBkYXRlZEV2ZW50OiAke3Vua25vd25PcHRpb25OYW1lcy5qb2luKFwiLCBcIil9YClcbiAgfVxufVxuXG4vKipcbiAqIFJlYWN0IGhvb2sgZm9yIGZyb250ZW5kLW1vZGVsIHVwZGF0ZSBldmVudHMuIFBhc3MgYSBtb2RlbCBjbGFzcyBmb3IgY2xhc3MtbGV2ZWxcbiAqIHVwZGF0ZSBldmVudHMsIG9yIGEgbW9kZWwgLyBtb2RlbCBhcnJheSBmb3IgaW5zdGFuY2UtbGV2ZWwgdXBkYXRlIGV2ZW50cy5cbiAqIEBwYXJhbSB7RnJvbnRlbmRNb2RlbENsYXNzIHwgRnJvbnRlbmRNb2RlbEluc3RhbmNlIHwgRnJvbnRlbmRNb2RlbEluc3RhbmNlW10gfCBudWxsIHwgdW5kZWZpbmVkfSBtb2RlbENsYXNzT3JNb2RlbHMgLSBNb2RlbCBjbGFzcywgbW9kZWwsIG9yIG1vZGVscy5cbiAqIEBwYXJhbSB7RnJvbnRlbmRNb2RlbFVwZGF0ZUV2ZW50Q2FsbGJhY2t9IGNhbGxiYWNrIC0gRXZlbnQgY2FsbGJhY2suXG4gKiBAcGFyYW0ge1VzZVVwZGF0ZWRFdmVudE9wdGlvbnN9IFtvcHRpb25zXSAtIEhvb2sgb3B0aW9ucy5cbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiB1c2VVcGRhdGVkRXZlbnQobW9kZWxDbGFzc09yTW9kZWxzLCBjYWxsYmFjaywgb3B0aW9ucyA9IHt9KSB7XG4gIGNvbnN0IHthY3RpdmUgPSB0cnVlLCBkZWJvdW5jZSA9IGZhbHNlLCBvbkNvbm5lY3RlZCwgLi4ucmVzdE9wdGlvbnN9ID0gb3B0aW9uc1xuICBhc3NlcnROb1Vua25vd25PcHRpb25zKHJlc3RPcHRpb25zKVxuXG4gIGNvbnN0IGNsYXNzTW9kZWwgPSB0eXBlb2YgbW9kZWxDbGFzc09yTW9kZWxzID09PSBcImZ1bmN0aW9uXCIgPyBtb2RlbENsYXNzT3JNb2RlbHMgOiBudWxsXG4gIGNvbnN0IGluc3RhbmNlTW9kZWxzID0gdHlwZW9mIG1vZGVsQ2xhc3NPck1vZGVscyA9PT0gXCJmdW5jdGlvblwiID8gbnVsbCA6IG1vZGVsQ2xhc3NPck1vZGVsc1xuXG4gIHVzZU1vZGVsQ2xhc3NFdmVudChjbGFzc01vZGVsLCBcInVwZGF0ZVwiLCAocGF5bG9hZCkgPT4ge1xuICAgIGNhbGxiYWNrKC8qKiBAdHlwZSB7RnJvbnRlbmRNb2RlbENsYXNzVXBkYXRlRXZlbnRQYXlsb2FkfSAqLyAocGF5bG9hZCkpXG4gIH0sIHthY3RpdmU6IGFjdGl2ZSAmJiBCb29sZWFuKGNsYXNzTW9kZWwpLCBkZWJvdW5jZSwgb25Db25uZWN0ZWR9KVxuICB1c2VJbnN0YW5jZVVwZGF0ZWRFdmVudChpbnN0YW5jZU1vZGVscywgY2FsbGJhY2ssIHthY3RpdmU6IGFjdGl2ZSAmJiAhY2xhc3NNb2RlbCwgZGVib3VuY2UsIG9uQ29ubmVjdGVkfSlcbn1cblxuLyoqXG4gKiBAcGFyYW0ge0Zyb250ZW5kTW9kZWxJbnN0YW5jZSB8IEZyb250ZW5kTW9kZWxJbnN0YW5jZVtdIHwgbnVsbCB8IHVuZGVmaW5lZH0gbW9kZWxPck1vZGVscyAtIE1vZGVsIG9yIG1vZGVscy5cbiAqIEBwYXJhbSB7RnJvbnRlbmRNb2RlbFVwZGF0ZUV2ZW50Q2FsbGJhY2t9IGNhbGxiYWNrIC0gRXZlbnQgY2FsbGJhY2suXG4gKiBAcGFyYW0ge1VzZVVwZGF0ZWRFdmVudE9wdGlvbnN9IG9wdGlvbnMgLSBIb29rIG9wdGlvbnMuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gdXNlSW5zdGFuY2VVcGRhdGVkRXZlbnQobW9kZWxPck1vZGVscywgY2FsbGJhY2ssIG9wdGlvbnMpIHtcbiAgY29uc3Qge2FjdGl2ZSA9IHRydWUsIGRlYm91bmNlID0gZmFsc2UsIG9uQ29ubmVjdGVkfSA9IG9wdGlvbnNcbiAgY29uc3QgY2FsbGJhY2tSZWYgPSB1c2VSZWYoY2FsbGJhY2spXG4gIGNvbnN0IGFjdGl2ZVJlZiA9IHVzZVJlZihhY3RpdmUpXG4gIGNhbGxiYWNrUmVmLmN1cnJlbnQgPSBjYWxsYmFja1xuICBhY3RpdmVSZWYuY3VycmVudCA9IGFjdGl2ZVxuXG4gIGNvbnN0IG1vZGVsc0tleSA9IG1vZGVsc0RlcGVuZGVuY3lLZXkobW9kZWxPck1vZGVscylcbiAgY29uc3QgZXZlbnRDYWxsYmFjayA9IHVzZU1lbW8oKCkgPT4ge1xuICAgIGNvbnN0IHdyYXBwZWRDYWxsYmFjayA9ICgvKiogQHR5cGUge0Zyb250ZW5kTW9kZWxJbnN0YW5jZVVwZGF0ZUV2ZW50UGF5bG9hZH0gKi8gcGF5bG9hZCkgPT4ge1xuICAgICAgaWYgKGFjdGl2ZVJlZi5jdXJyZW50KSBjYWxsYmFja1JlZi5jdXJyZW50KHBheWxvYWQpXG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBkZWJvdW5jZSA9PT0gXCJudW1iZXJcIikgcmV0dXJuIGRlYm91bmNlRnVuY3Rpb24od3JhcHBlZENhbGxiYWNrLCBkZWJvdW5jZSlcbiAgICBpZiAoZGVib3VuY2UpIHJldHVybiBkZWJvdW5jZUZ1bmN0aW9uKHdyYXBwZWRDYWxsYmFjaylcblxuICAgIHJldHVybiB3cmFwcGVkQ2FsbGJhY2tcbiAgfSwgW2RlYm91bmNlXSlcblxuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlmICghYWN0aXZlKSByZXR1cm4gdW5kZWZpbmVkXG5cbiAgICBjb25zdCBtb2RlbHMgPSBtb2RlbHNGcm9tSW5wdXQobW9kZWxPck1vZGVscylcbiAgICBpZiAobW9kZWxzLmxlbmd0aCA8IDEpIHJldHVybiB1bmRlZmluZWRcblxuICAgIGxldCBjbG9zZWQgPSBmYWxzZVxuICAgIC8qKiBAdHlwZSB7QXJyYXk8KCkgPT4gdm9pZD59ICovXG4gICAgY29uc3QgdW5zdWJzY3JpYmVDYWxsYmFja3MgPSBbXVxuICAgIGNvbnN0IHN1YnNjcmlwdGlvbkNhbGxiYWNrID0gKC8qKiBAdHlwZSB7RnJvbnRlbmRNb2RlbEluc3RhbmNlVXBkYXRlRXZlbnRQYXlsb2FkfSAqLyBwYXlsb2FkKSA9PiB7XG4gICAgICBpZiAoIWNsb3NlZCkgZXZlbnRDYWxsYmFjayhwYXlsb2FkKVxuICAgIH1cblxuICAgIHZvaWQgKGFzeW5jICgpID0+IHtcbiAgICAgIGZvciAoY29uc3QgbW9kZWwgb2YgbW9kZWxzKSB7XG4gICAgICAgIGNvbnN0IHVuc3Vic2NyaWJlID0gYXdhaXQgbW9kZWwub25VcGRhdGUoc3Vic2NyaXB0aW9uQ2FsbGJhY2spXG5cbiAgICAgICAgaWYgKGNsb3NlZCkge1xuICAgICAgICAgIHVuc3Vic2NyaWJlKClcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB1bnN1YnNjcmliZUNhbGxiYWNrcy5wdXNoKHVuc3Vic2NyaWJlKVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmICghY2xvc2VkICYmIG9uQ29ubmVjdGVkKSBvbkNvbm5lY3RlZCgpXG4gICAgfSkoKVxuXG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIGNsb3NlZCA9IHRydWVcblxuICAgICAgZm9yIChjb25zdCB1bnN1YnNjcmliZSBvZiB1bnN1YnNjcmliZUNhbGxiYWNrcykge1xuICAgICAgICB1bnN1YnNjcmliZSgpXG4gICAgICB9XG5cbiAgICAgIGNsZWFyUGVuZGluZ0RlYm91bmNlZENhbGxiYWNrKGV2ZW50Q2FsbGJhY2spXG4gICAgfVxuICB9LCBbYWN0aXZlLCBldmVudENhbGxiYWNrLCBtb2RlbHNLZXksIG9uQ29ubmVjdGVkXSlcbn1cbiJdfQ==
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {keyof typeof scenarios} scenarioName - Scenario name.
|
|
3
|
+
* @returns {Promise<Record<string, number>>} - Scenario result.
|
|
4
|
+
*/
|
|
5
|
+
export default function runFrontendModelEventHookScenario(scenarioName: keyof typeof scenarios): Promise<Record<string, number>>;
|
|
6
|
+
export type FakeSubscriptions = {
|
|
7
|
+
/**
|
|
8
|
+
* - Create callbacks.
|
|
9
|
+
*/
|
|
10
|
+
create: Set<(payload: unknown) => void>;
|
|
11
|
+
/**
|
|
12
|
+
* - Destroy callbacks.
|
|
13
|
+
*/
|
|
14
|
+
destroy: Set<(payload: unknown) => void>;
|
|
15
|
+
/**
|
|
16
|
+
* - Update callbacks.
|
|
17
|
+
*/
|
|
18
|
+
update: Set<(payload: unknown) => void>;
|
|
19
|
+
};
|
|
20
|
+
declare namespace scenarios {
|
|
21
|
+
export { classLifecycleScenario as classLifecycle };
|
|
22
|
+
export { debounceUnmountScenario as debounceUnmount };
|
|
23
|
+
export { instanceLifecycleScenario as instanceLifecycle };
|
|
24
|
+
export { resubscribeInstanceScenario as resubscribeInstance };
|
|
25
|
+
}
|
|
26
|
+
/** @returns {Promise<Record<string, number>>} - Scenario result. */
|
|
27
|
+
declare function classLifecycleScenario(): Promise<Record<string, number>>;
|
|
28
|
+
/** @returns {Promise<Record<string, number>>} - Scenario result. */
|
|
29
|
+
declare function debounceUnmountScenario(): Promise<Record<string, number>>;
|
|
30
|
+
/** @returns {Promise<Record<string, number>>} - Scenario result. */
|
|
31
|
+
declare function instanceLifecycleScenario(): Promise<Record<string, number>>;
|
|
32
|
+
/** @returns {Promise<Record<string, number>>} - Scenario result. */
|
|
33
|
+
declare function resubscribeInstanceScenario(): Promise<Record<string, number>>;
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=browser-frontend-model-event-hook-scenarios.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser-frontend-model-event-hook-scenarios.d.ts","sourceRoot":"","sources":["../../../src/testing/browser-frontend-model-event-hook-scenarios.js"],"names":[],"mappings":"AAiTA;;;GAGG;AACH,wEAHW,MAAM,OAAO,SAAS,GACpB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAQ3C;;;;;YA/Sa,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;;;;aAC/B,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;;;;YAC/B,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;;;;;;;;AAqH7C,oEAAoE;AACpE,2CADc,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAyC5C;AA6CD,oEAAoE;AACpE,4CADc,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA2B5C;AAtED,oEAAoE;AACpE,8CADc,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAyC5C;AA+BD,oEAAoE;AACpE,gDADc,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAkD5C"}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { createRoot } from "react-dom/client";
|
|
4
|
+
import useDestroyedEvent from "../frontend-models/use-destroyed-event.js";
|
|
5
|
+
import useCreatedEvent from "../frontend-models/use-created-event.js";
|
|
6
|
+
import useModelClassEvent from "../frontend-models/use-model-class-event.js";
|
|
7
|
+
import useUpdatedEvent from "../frontend-models/use-updated-event.js";
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {object} FakeSubscriptions
|
|
10
|
+
* @property {Set<(payload: unknown) => void>} create - Create callbacks.
|
|
11
|
+
* @property {Set<(payload: unknown) => void>} destroy - Destroy callbacks.
|
|
12
|
+
* @property {Set<(payload: unknown) => void>} update - Update callbacks.
|
|
13
|
+
*/
|
|
14
|
+
/** @returns {Promise<void>} - Resolves after React effects have run. */
|
|
15
|
+
async function flushEffects() {
|
|
16
|
+
await Promise.resolve();
|
|
17
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* @param {number} milliseconds - Milliseconds to wait.
|
|
21
|
+
* @returns {Promise<void>} - Resolves after the delay.
|
|
22
|
+
*/
|
|
23
|
+
async function sleep(milliseconds) {
|
|
24
|
+
await new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* @param {() => boolean} callback - Predicate to wait for.
|
|
28
|
+
* @returns {Promise<void>} - Resolves when the predicate returns true.
|
|
29
|
+
*/
|
|
30
|
+
async function waitFor(callback) {
|
|
31
|
+
const startedAt = Date.now();
|
|
32
|
+
while (!callback()) {
|
|
33
|
+
if (Date.now() - startedAt > 1000)
|
|
34
|
+
return;
|
|
35
|
+
await sleep(10);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* @param {React.ReactElement} element - Element to render.
|
|
40
|
+
* @returns {Promise<{rerender: (nextElement: React.ReactElement) => Promise<void>, unmount: () => Promise<void>}>} - Render controls.
|
|
41
|
+
*/
|
|
42
|
+
async function renderElement(element) {
|
|
43
|
+
const container = document.createElement("div");
|
|
44
|
+
document.body.appendChild(container);
|
|
45
|
+
const root = createRoot(container);
|
|
46
|
+
root.render(element);
|
|
47
|
+
await flushEffects();
|
|
48
|
+
return {
|
|
49
|
+
rerender: async (nextElement) => {
|
|
50
|
+
root.render(nextElement);
|
|
51
|
+
await flushEffects();
|
|
52
|
+
},
|
|
53
|
+
unmount: async () => {
|
|
54
|
+
root.unmount();
|
|
55
|
+
container.remove();
|
|
56
|
+
await flushEffects();
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/** @returns {{ModelClass: typeof import("../frontend-models/base.js").default, subscriptions: FakeSubscriptions}} - Fake model class setup. */
|
|
61
|
+
function buildFakeModelClass() {
|
|
62
|
+
const subscriptions = {
|
|
63
|
+
create: new Set(),
|
|
64
|
+
destroy: new Set(),
|
|
65
|
+
update: new Set()
|
|
66
|
+
};
|
|
67
|
+
const ModelClass = /** @type {typeof import("../frontend-models/base.js").default} */ ( /** @type {unknown} */({
|
|
68
|
+
onCreate: async (/** @type {(payload: unknown) => void} */ callback) => {
|
|
69
|
+
subscriptions.create.add(callback);
|
|
70
|
+
return () => subscriptions.create.delete(callback);
|
|
71
|
+
},
|
|
72
|
+
onDestroy: async (/** @type {(payload: unknown) => void} */ callback) => {
|
|
73
|
+
subscriptions.destroy.add(callback);
|
|
74
|
+
return () => subscriptions.destroy.delete(callback);
|
|
75
|
+
},
|
|
76
|
+
onUpdate: async (/** @type {(payload: unknown) => void} */ callback) => {
|
|
77
|
+
subscriptions.update.add(callback);
|
|
78
|
+
return () => subscriptions.update.delete(callback);
|
|
79
|
+
}
|
|
80
|
+
}));
|
|
81
|
+
return { ModelClass, subscriptions };
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* @param {FakeSubscriptions} subscriptions - Callback sets.
|
|
85
|
+
* @param {"create" | "destroy" | "update"} eventName - Event name.
|
|
86
|
+
* @param {unknown} payload - Event payload.
|
|
87
|
+
* @returns {void}
|
|
88
|
+
*/
|
|
89
|
+
function emitEvent(subscriptions, eventName, payload) {
|
|
90
|
+
for (const callback of subscriptions[eventName]) {
|
|
91
|
+
callback(payload);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* @param {string} id - Model id.
|
|
96
|
+
* @param {FakeSubscriptions} subscriptions - Callback sets.
|
|
97
|
+
* @returns {import("../frontend-models/base.js").default} - Fake model instance.
|
|
98
|
+
*/
|
|
99
|
+
function buildFakeModel(id, subscriptions) {
|
|
100
|
+
return /** @type {import("../frontend-models/base.js").default} */ ( /** @type {unknown} */({
|
|
101
|
+
onDestroy: async (/** @type {(payload: unknown) => void} */ callback) => {
|
|
102
|
+
subscriptions.destroy.add(callback);
|
|
103
|
+
return () => subscriptions.destroy.delete(callback);
|
|
104
|
+
},
|
|
105
|
+
onUpdate: async (/** @type {(payload: unknown) => void} */ callback) => {
|
|
106
|
+
subscriptions.update.add(callback);
|
|
107
|
+
return () => subscriptions.update.delete(callback);
|
|
108
|
+
},
|
|
109
|
+
primaryKeyValue: () => id
|
|
110
|
+
}));
|
|
111
|
+
}
|
|
112
|
+
/** @returns {Promise<Record<string, number>>} - Scenario result. */
|
|
113
|
+
async function classLifecycleScenario() {
|
|
114
|
+
const { ModelClass, subscriptions } = buildFakeModelClass();
|
|
115
|
+
const receivedEvents = /** @type {unknown[]} */ ([]);
|
|
116
|
+
let connectedCount = 0;
|
|
117
|
+
/** @returns {React.ReactElement} - Test element. */
|
|
118
|
+
function TestComponent() {
|
|
119
|
+
useModelClassEvent(ModelClass, ["create", "update"], (payload) => receivedEvents.push(payload), {
|
|
120
|
+
onConnected: () => { connectedCount += 1; }
|
|
121
|
+
});
|
|
122
|
+
useCreatedEvent(ModelClass, (payload) => receivedEvents.push(payload));
|
|
123
|
+
return React.createElement("div");
|
|
124
|
+
}
|
|
125
|
+
const controls = await renderElement(React.createElement(TestComponent));
|
|
126
|
+
await waitFor(() => subscriptions.create.size === 2 && subscriptions.update.size === 1);
|
|
127
|
+
const mountedCreateSubscriptions = subscriptions.create.size;
|
|
128
|
+
const mountedUpdateSubscriptions = subscriptions.update.size;
|
|
129
|
+
const mountedDestroySubscriptions = subscriptions.destroy.size;
|
|
130
|
+
const mountedConnectedCount = connectedCount;
|
|
131
|
+
emitEvent(subscriptions, "create", { id: "1", model: { id: "1" } });
|
|
132
|
+
emitEvent(subscriptions, "update", { id: "1", model: { id: "1" } });
|
|
133
|
+
emitEvent(subscriptions, "destroy", { id: "1" });
|
|
134
|
+
const receivedEventsAfterEmit = receivedEvents.length;
|
|
135
|
+
await controls.unmount();
|
|
136
|
+
return {
|
|
137
|
+
mountedConnectedCount,
|
|
138
|
+
mountedCreateSubscriptions,
|
|
139
|
+
mountedDestroySubscriptions,
|
|
140
|
+
mountedUpdateSubscriptions,
|
|
141
|
+
receivedEventsAfterEmit,
|
|
142
|
+
unmountedCreateSubscriptions: subscriptions.create.size,
|
|
143
|
+
unmountedUpdateSubscriptions: subscriptions.update.size
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/** @returns {Promise<Record<string, number>>} - Scenario result. */
|
|
147
|
+
async function instanceLifecycleScenario() {
|
|
148
|
+
const subscriptions = { create: new Set(), destroy: new Set(), update: new Set() };
|
|
149
|
+
const model = buildFakeModel("task-1", subscriptions);
|
|
150
|
+
const receivedEvents = /** @type {unknown[]} */ ([]);
|
|
151
|
+
let connectedCount = 0;
|
|
152
|
+
/** @returns {React.ReactElement} - Test element. */
|
|
153
|
+
function TestComponent() {
|
|
154
|
+
useUpdatedEvent(model, (payload) => receivedEvents.push(payload), {
|
|
155
|
+
onConnected: () => { connectedCount += 1; }
|
|
156
|
+
});
|
|
157
|
+
useDestroyedEvent([model], (payload) => receivedEvents.push(payload), {
|
|
158
|
+
onConnected: () => { connectedCount += 1; }
|
|
159
|
+
});
|
|
160
|
+
return React.createElement("div");
|
|
161
|
+
}
|
|
162
|
+
const controls = await renderElement(React.createElement(TestComponent));
|
|
163
|
+
await waitFor(() => subscriptions.update.size === 1 && subscriptions.destroy.size === 1);
|
|
164
|
+
const mountedConnectedCount = connectedCount;
|
|
165
|
+
const mountedDestroySubscriptions = subscriptions.destroy.size;
|
|
166
|
+
const mountedUpdateSubscriptions = subscriptions.update.size;
|
|
167
|
+
emitEvent(subscriptions, "update", { id: "task-1", model });
|
|
168
|
+
emitEvent(subscriptions, "destroy", { id: "task-1" });
|
|
169
|
+
const receivedEventsAfterEmit = receivedEvents.length;
|
|
170
|
+
await controls.unmount();
|
|
171
|
+
return {
|
|
172
|
+
mountedConnectedCount,
|
|
173
|
+
mountedDestroySubscriptions,
|
|
174
|
+
mountedUpdateSubscriptions,
|
|
175
|
+
receivedEventsAfterEmit,
|
|
176
|
+
unmountedDestroySubscriptions: subscriptions.destroy.size,
|
|
177
|
+
unmountedUpdateSubscriptions: subscriptions.update.size
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/** @returns {Promise<Record<string, number>>} - Scenario result. */
|
|
181
|
+
async function debounceUnmountScenario() {
|
|
182
|
+
const { ModelClass, subscriptions: classSubscriptions } = buildFakeModelClass();
|
|
183
|
+
const instanceSubscriptions = { create: new Set(), destroy: new Set(), update: new Set() };
|
|
184
|
+
const model = buildFakeModel("task-1", instanceSubscriptions);
|
|
185
|
+
const receivedEvents = /** @type {unknown[]} */ ([]);
|
|
186
|
+
/** @returns {React.ReactElement} - Test element. */
|
|
187
|
+
function TestComponent() {
|
|
188
|
+
useModelClassEvent(ModelClass, "update", (payload) => receivedEvents.push(payload), { debounce: 20 });
|
|
189
|
+
useUpdatedEvent(model, (payload) => receivedEvents.push(payload), { debounce: 20 });
|
|
190
|
+
useDestroyedEvent(model, (payload) => receivedEvents.push(payload), { debounce: 20 });
|
|
191
|
+
return React.createElement("div");
|
|
192
|
+
}
|
|
193
|
+
const controls = await renderElement(React.createElement(TestComponent));
|
|
194
|
+
await waitFor(() => classSubscriptions.update.size === 1 && instanceSubscriptions.update.size === 1 && instanceSubscriptions.destroy.size === 1);
|
|
195
|
+
emitEvent(classSubscriptions, "update", { id: "task-1", model });
|
|
196
|
+
emitEvent(instanceSubscriptions, "update", { id: "task-1", model });
|
|
197
|
+
emitEvent(instanceSubscriptions, "destroy", { id: "task-1" });
|
|
198
|
+
await controls.unmount();
|
|
199
|
+
await sleep(30);
|
|
200
|
+
return { receivedEventsAfterDebounceWindow: receivedEvents.length };
|
|
201
|
+
}
|
|
202
|
+
/** @returns {Promise<Record<string, number>>} - Scenario result. */
|
|
203
|
+
async function resubscribeInstanceScenario() {
|
|
204
|
+
const firstSubscriptions = { create: new Set(), destroy: new Set(), update: new Set() };
|
|
205
|
+
const secondSubscriptions = { create: new Set(), destroy: new Set(), update: new Set() };
|
|
206
|
+
const firstModel = buildFakeModel("task-1", firstSubscriptions);
|
|
207
|
+
const secondModel = buildFakeModel("task-1", secondSubscriptions);
|
|
208
|
+
const receivedEvents = /** @type {unknown[]} */ ([]);
|
|
209
|
+
/**
|
|
210
|
+
* @param {{model: import("../frontend-models/base.js").default}} props - Component props.
|
|
211
|
+
* @returns {React.ReactElement} - Test element.
|
|
212
|
+
*/
|
|
213
|
+
function TestComponent({ model }) {
|
|
214
|
+
useUpdatedEvent(model, (payload) => receivedEvents.push(payload));
|
|
215
|
+
useDestroyedEvent(model, (payload) => receivedEvents.push(payload));
|
|
216
|
+
return React.createElement("div");
|
|
217
|
+
}
|
|
218
|
+
const controls = await renderElement(React.createElement(TestComponent, { model: firstModel }));
|
|
219
|
+
await waitFor(() => firstSubscriptions.update.size === 1 && firstSubscriptions.destroy.size === 1);
|
|
220
|
+
const firstMountedDestroySubscriptions = firstSubscriptions.destroy.size;
|
|
221
|
+
const firstMountedUpdateSubscriptions = firstSubscriptions.update.size;
|
|
222
|
+
await controls.rerender(React.createElement(TestComponent, { model: secondModel }));
|
|
223
|
+
await waitFor(() => firstSubscriptions.update.size === 0 && firstSubscriptions.destroy.size === 0 && secondSubscriptions.update.size === 1 && secondSubscriptions.destroy.size === 1);
|
|
224
|
+
const firstAfterRerenderDestroySubscriptions = firstSubscriptions.destroy.size;
|
|
225
|
+
const firstAfterRerenderUpdateSubscriptions = firstSubscriptions.update.size;
|
|
226
|
+
const secondAfterRerenderDestroySubscriptions = secondSubscriptions.destroy.size;
|
|
227
|
+
const secondAfterRerenderUpdateSubscriptions = secondSubscriptions.update.size;
|
|
228
|
+
emitEvent(firstSubscriptions, "update", { id: "task-1", model: firstModel });
|
|
229
|
+
emitEvent(secondSubscriptions, "update", { id: "task-1", model: secondModel });
|
|
230
|
+
emitEvent(secondSubscriptions, "destroy", { id: "task-1" });
|
|
231
|
+
const receivedEventsAfterEmit = receivedEvents.length;
|
|
232
|
+
await controls.unmount();
|
|
233
|
+
return {
|
|
234
|
+
firstAfterRerenderDestroySubscriptions,
|
|
235
|
+
firstAfterRerenderUpdateSubscriptions,
|
|
236
|
+
firstMountedDestroySubscriptions,
|
|
237
|
+
firstMountedUpdateSubscriptions,
|
|
238
|
+
receivedEventsAfterEmit,
|
|
239
|
+
secondAfterRerenderDestroySubscriptions,
|
|
240
|
+
secondAfterRerenderUpdateSubscriptions
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
const scenarios = {
|
|
244
|
+
classLifecycle: classLifecycleScenario,
|
|
245
|
+
debounceUnmount: debounceUnmountScenario,
|
|
246
|
+
instanceLifecycle: instanceLifecycleScenario,
|
|
247
|
+
resubscribeInstance: resubscribeInstanceScenario
|
|
248
|
+
};
|
|
249
|
+
/**
|
|
250
|
+
* @param {keyof typeof scenarios} scenarioName - Scenario name.
|
|
251
|
+
* @returns {Promise<Record<string, number>>} - Scenario result.
|
|
252
|
+
*/
|
|
253
|
+
export default async function runFrontendModelEventHookScenario(scenarioName) {
|
|
254
|
+
const scenario = scenarios[scenarioName];
|
|
255
|
+
if (!scenario)
|
|
256
|
+
throw new Error(`Unknown frontend model event hook scenario: ${scenarioName}`);
|
|
257
|
+
return await scenario();
|
|
258
|
+
}
|
|
259
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJvd3Nlci1mcm9udGVuZC1tb2RlbC1ldmVudC1ob29rLXNjZW5hcmlvcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90ZXN0aW5nL2Jyb3dzZXItZnJvbnRlbmQtbW9kZWwtZXZlbnQtaG9vay1zY2VuYXJpb3MuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sS0FBSyxNQUFNLE9BQU8sQ0FBQTtBQUN6QixPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sa0JBQWtCLENBQUE7QUFFM0MsT0FBTyxpQkFBaUIsTUFBTSwyQ0FBMkMsQ0FBQTtBQUN6RSxPQUFPLGVBQWUsTUFBTSx5Q0FBeUMsQ0FBQTtBQUNyRSxPQUFPLGtCQUFrQixNQUFNLDZDQUE2QyxDQUFBO0FBQzVFLE9BQU8sZUFBZSxNQUFNLHlDQUF5QyxDQUFBO0FBRXJFOzs7OztHQUtHO0FBRUgsd0VBQXdFO0FBQ3hFLEtBQUssVUFBVSxZQUFZO0lBQ3pCLE1BQU0sT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFBO0lBQ3ZCLE1BQU0sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQTtBQUN4RCxDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsS0FBSyxVQUFVLEtBQUssQ0FBQyxZQUFZO0lBQy9CLE1BQU0sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQTtBQUNuRSxDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsS0FBSyxVQUFVLE9BQU8sQ0FBQyxRQUFRO0lBQzdCLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQTtJQUU1QixPQUFPLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQztRQUNuQixJQUFJLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxT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QUMsSUFBSSxDQUFBO0lBRTlFLFNBQVMsQ0FBQyxrQkFBa0IsRUFBRSxRQUFRLEVBQUUsRUFBQyxFQUFFLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUMsQ0FBQyxDQUFBO0lBQzFFLFNBQVMsQ0FBQyxtQkFBbUIsRUFBRSxRQUFRLEVBQUUsRUFBQyxFQUFFLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUMsQ0FBQyxDQUFBO0lBQzVFLFNBQVMsQ0FBQyxtQkFBbUIsRUFBRSxTQUFTLEVBQUUsRUFBQyxFQUFFLEVBQUUsUUFBUSxFQUFDLENBQUMsQ0FBQTtJQUV6RCxNQUFNLHVCQUF1QixHQUFHLGNBQWMsQ0FBQyxNQUFNLENBQUE7SUFFckQsTUFBTSxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUE7SUFFeEIsT0FBTztRQUNMLHNDQUFzQztRQUN0QyxxQ0FBcUM7UUFDckMsZ0NBQWdDO1FBQ2hDLCtCQUErQjtRQUMvQix1QkFBdUI7UUFDdkIsdUNBQXVDO1FBQ3ZDLHNDQUFzQztLQUN2QyxDQUFBO0FBQ0gsQ0FBQztBQUVELE1BQU0sU0FBUyxHQUFHO0lBQ2hCLGNBQWMsRUFBRSxzQkFBc0I7SUFDdEMsZUFBZSxFQUFFLHVCQUF1QjtJQUN4QyxpQkFBaUIsRUFBRSx5QkFBeUI7SUFDNUMsbUJBQW1CLEVBQUUsMkJBQTJCO0NBQ2pELENBQUE7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLENBQUMsT0FBTyxDQUFDLEtBQUssVUFBVSxpQ0FBaUMsQ0FBQyxZQUFZO0lBQzFFLE1BQU0sUUFBUSxHQUFHLFNBQVMsQ0FBQyxZQUFZLENBQUMsQ0FBQTtJQUV4QyxJQUFJLENBQUMsUUFBUTtRQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsK0NBQStDLFlBQVksRUFBRSxDQUFDLENBQUE7SUFFN0YsT0FBTyxNQUFNLFFBQVEsRUFBRSxDQUFBO0FBQ3pCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IFJlYWN0IGZyb20gXCJyZWFjdFwiXG5pbXBvcnQge2NyZWF0ZVJvb3R9IGZyb20gXCJyZWFjdC1kb20vY2xpZW50XCJcblxuaW1wb3J0IHVzZURlc3Ryb3llZEV2ZW50IGZyb20gXCIuLi9mcm9udGVuZC1tb2RlbHMvdXNlLWRlc3Ryb3llZC1ldmVudC5qc1wiXG5pbXBvcnQgdXNlQ3JlYXRlZEV2ZW50IGZyb20gXCIuLi9mcm9udGVuZC1tb2RlbHMvdXNlLWNyZWF0ZWQtZXZlbnQuanNcIlxuaW1wb3J0IHVzZU1vZGVsQ2xhc3NFdmVudCBmcm9tIFwiLi4vZnJvbnRlbmQtbW9kZWxzL3VzZS1tb2RlbC1jbGFzcy1ldmVudC5qc1wiXG5pbXBvcnQgdXNlVXBkYXRlZEV2ZW50IGZyb20gXCIuLi9mcm9udGVuZC1tb2RlbHMvdXNlLXVwZGF0ZWQtZXZlbnQuanNcIlxuXG4vKipcbiAqIEB0eXBlZGVmIHtvYmplY3R9IEZha2VTdWJzY3JpcHRpb25zXG4gKiBAcHJvcGVydHkge1NldDwocGF5bG9hZDogdW5rbm93bikgPT4gdm9pZD59IGNyZWF0ZSAtIENyZWF0ZSBjYWxsYmFja3MuXG4gKiBAcHJvcGVydHkge1NldDwocGF5bG9hZDogdW5rbm93bikgPT4gdm9pZD59IGRlc3Ryb3kgLSBEZXN0cm95IGNhbGxiYWNrcy5cbiAqIEBwcm9wZXJ0eSB7U2V0PChwYXlsb2FkOiB1bmtub3duKSA9PiB2b2lkPn0gdXBkYXRlIC0gVXBkYXRlIGNhbGxiYWNrcy5cbiAqL1xuXG4vKiogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgYWZ0ZXIgUmVhY3QgZWZmZWN0cyBoYXZlIHJ1bi4gKi9cbmFzeW5jIGZ1bmN0aW9uIGZsdXNoRWZmZWN0cygpIHtcbiAgYXdhaXQgUHJvbWlzZS5yZXNvbHZlKClcbiAgYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgMCkpXG59XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IG1pbGxpc2Vjb25kcyAtIE1pbGxpc2Vjb25kcyB0byB3YWl0LlxuICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgYWZ0ZXIgdGhlIGRlbGF5LlxuICovXG5hc3luYyBmdW5jdGlvbiBzbGVlcChtaWxsaXNlY29uZHMpIHtcbiAgYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgbWlsbGlzZWNvbmRzKSlcbn1cblxuLyoqXG4gKiBAcGFyYW0geygpID0+IGJvb2xlYW59IGNhbGxiYWNrIC0gUHJlZGljYXRlIHRvIHdhaXQgZm9yLlxuICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgd2hlbiB0aGUgcHJlZGljYXRlIHJldHVybnMgdHJ1ZS5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gd2FpdEZvcihjYWxsYmFjaykge1xuICBjb25zdCBzdGFydGVkQXQgPSBEYXRlLm5vdygpXG5cbiAgd2hpbGUgKCFjYWxsYmFjaygpKSB7XG4gICAgaWYgKERhdGUubm93KCkgLSBzdGFydGVkQXQgPiAxMDAwKSByZXR1cm5cblxuICAgIGF3YWl0IHNsZWVwKDEwKVxuICB9XG59XG5cbi8qKlxuICogQHBhcmFtIHtSZWFjdC5SZWFjdEVsZW1lbnR9IGVsZW1lbnQgLSBFbGVtZW50IHRvIHJlbmRlci5cbiAqIEByZXR1cm5zIHtQcm9taXNlPHtyZXJlbmRlcjogKG5leHRFbGVtZW50OiBSZWFjdC5SZWFjdEVsZW1lbnQpID0+IFByb21pc2U8dm9pZD4sIHVubW91bnQ6ICgpID0+IFByb21pc2U8dm9pZD59Pn0gLSBSZW5kZXIgY29udHJvbHMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlbmRlckVsZW1lbnQoZWxlbWVudCkge1xuICBjb25zdCBjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpXG4gIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoY29udGFpbmVyKVxuICBjb25zdCByb290ID0gY3JlYXRlUm9vdChjb250YWluZXIpXG5cbiAgcm9vdC5yZW5kZXIoZWxlbWVudClcbiAgYXdhaXQgZmx1c2hFZmZlY3RzKClcblxuICByZXR1cm4ge1xuICAgIHJlcmVuZGVyOiBhc3luYyAobmV4dEVsZW1lbnQpID0+IHtcbiAgICAgIHJvb3QucmVuZGVyKG5leHRFbGVtZW50KVxuICAgICAgYXdhaXQgZmx1c2hFZmZlY3RzKClcbiAgICB9LFxuICAgIHVubW91bnQ6IGFzeW5jICgpID0+IHtcbiAgICAgIHJvb3QudW5tb3VudCgpXG4gICAgICBjb250YWluZXIucmVtb3ZlKClcbiAgICAgIGF3YWl0IGZsdXNoRWZmZWN0cygpXG4gICAgfVxuICB9XG59XG5cbi8qKiBAcmV0dXJucyB7e01vZGVsQ2xhc3M6IHR5cGVvZiBpbXBvcnQoXCIuLi9mcm9udGVuZC1tb2RlbHMvYmFzZS5qc1wiKS5kZWZhdWx0LCBzdWJzY3JpcHRpb25zOiBGYWtlU3Vic2NyaXB0aW9uc319IC0gRmFrZSBtb2RlbCBjbGFzcyBzZXR1cC4gKi9cbmZ1bmN0aW9uIGJ1aWxkRmFrZU1vZGVsQ2xhc3MoKSB7XG4gIGNvbnN0IHN1YnNjcmlwdGlvbnMgPSB7XG4gICAgY3JlYXRlOiBuZXcgU2V0KCksXG4gICAgZGVzdHJveTogbmV3IFNldCgpLFxuICAgIHVwZGF0ZTogbmV3IFNldCgpXG4gIH1cbiAgY29uc3QgTW9kZWxDbGFzcyA9IC8qKiBAdHlwZSB7dHlwZW9mIGltcG9ydChcIi4uL2Zyb250ZW5kLW1vZGVscy9iYXNlLmpzXCIpLmRlZmF1bHR9ICovICgvKiogQHR5cGUge3Vua25vd259ICovICh7XG4gICAgb25DcmVhdGU6IGFzeW5jICgvKiogQHR5cGUgeyhwYXlsb2FkOiB1bmtub3duKSA9PiB2b2lkfSAqLyBjYWxsYmFjaykgPT4ge1xuICAgICAgc3Vic2NyaXB0aW9ucy5jcmVhdGUuYWRkKGNhbGxiYWNrKVxuXG4gICAgICByZXR1cm4gKCkgPT4gc3Vic2NyaXB0aW9ucy5jcmVhdGUuZGVsZXRlKGNhbGxiYWNrKVxuICAgIH0sXG4gICAgb25EZXN0cm95OiBhc3luYyAoLyoqIEB0eXBlIHsocGF5bG9hZDogdW5rbm93bikgPT4gdm9pZH0gKi8gY2FsbGJhY2spID0+IHtcbiAgICAgIHN1YnNjcmlwdGlvbnMuZGVzdHJveS5hZGQoY2FsbGJhY2spXG5cbiAgICAgIHJldHVybiAoKSA9PiBzdWJzY3JpcHRpb25zLmRlc3Ryb3kuZGVsZXRlKGNhbGxiYWNrKVxuICAgIH0sXG4gICAgb25VcGRhdGU6IGFzeW5jICgvKiogQHR5cGUgeyhwYXlsb2FkOiB1bmtub3duKSA9PiB2b2lkfSAqLyBjYWxsYmFjaykgPT4ge1xuICAgICAgc3Vic2NyaXB0aW9ucy51cGRhdGUuYWRkKGNhbGxiYWNrKVxuXG4gICAgICByZXR1cm4gKCkgPT4gc3Vic2NyaXB0aW9ucy51cGRhdGUuZGVsZXRlKGNhbGxiYWNrKVxuICAgIH1cbiAgfSkpXG5cbiAgcmV0dXJuIHtNb2RlbENsYXNzLCBzdWJzY3JpcHRpb25zfVxufVxuXG4vKipcbiAqIEBwYXJhbSB7RmFrZVN1YnNjcmlwdGlvbnN9IHN1YnNjcmlwdGlvbnMgLSBDYWxsYmFjayBzZXRzLlxuICogQHBhcmFtIHtcImNyZWF0ZVwiIHwgXCJkZXN0cm95XCIgfCBcInVwZGF0ZVwifSBldmVudE5hbWUgLSBFdmVudCBuYW1lLlxuICogQHBhcmFtIHt1bmtub3dufSBwYXlsb2FkIC0gRXZlbnQgcGF5bG9hZC5cbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5mdW5jdGlvbiBlbWl0RXZlbnQoc3Vic2NyaXB0aW9ucywgZXZlbnROYW1lLCBwYXlsb2FkKSB7XG4gIGZvciAoY29uc3QgY2FsbGJhY2sgb2Ygc3Vic2NyaXB0aW9uc1tldmVudE5hbWVdKSB7XG4gICAgY2FsbGJhY2socGF5bG9hZClcbiAgfVxufVxuXG4vKipcbiAqIEBwYXJhbSB7c3RyaW5nfSBpZCAtIE1vZGVsIGlkLlxuICogQHBhcmFtIHtGYWtlU3Vic2NyaXB0aW9uc30gc3Vic2NyaXB0aW9ucyAtIENhbGxiYWNrIHNldHMuXG4gKiBAcmV0dXJucyB7aW1wb3J0KFwiLi4vZnJvbnRlbmQtbW9kZWxzL2Jhc2UuanNcIikuZGVmYXVsdH0gLSBGYWtlIG1vZGVsIGluc3RhbmNlLlxuICovXG5mdW5jdGlvbiBidWlsZEZha2VNb2RlbChpZCwgc3Vic2NyaXB0aW9ucykge1xuICByZXR1cm4gLyoqIEB0eXBlIHtpbXBvcnQoXCIuLi9mcm9udGVuZC1tb2RlbHMvYmFzZS5qc1wiKS5kZWZhdWx0fSAqLyAoLyoqIEB0eXBlIHt1bmtub3dufSAqLyAoe1xuICAgIG9uRGVzdHJveTogYXN5bmMgKC8qKiBAdHlwZSB7KHBheWxvYWQ6IHVua25vd24pID0+IHZvaWR9ICovIGNhbGxiYWNrKSA9PiB7XG4gICAgICBzdWJzY3JpcHRpb25zLmRlc3Ryb3kuYWRkKGNhbGxiYWNrKVxuXG4gICAgICByZXR1cm4gKCkgPT4gc3Vic2NyaXB0aW9ucy5kZXN0cm95LmRlbGV0ZShjYWxsYmFjaylcbiAgICB9LFxuICAgIG9uVXBkYXRlOiBhc3luYyAoLyoqIEB0eXBlIHsocGF5bG9hZDogdW5rbm93bikgPT4gdm9pZH0gKi8gY2FsbGJhY2spID0+IHtcbiAgICAgIHN1YnNjcmlwdGlvbnMudXBkYXRlLmFkZChjYWxsYmFjaylcblxuICAgICAgcmV0dXJuICgpID0+IHN1YnNjcmlwdGlvbnMudXBkYXRlLmRlbGV0ZShjYWxsYmFjaylcbiAgICB9LFxuICAgIHByaW1hcnlLZXlWYWx1ZTogKCkgPT4gaWRcbiAgfSkpXG59XG5cbi8qKiBAcmV0dXJucyB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBudW1iZXI+Pn0gLSBTY2VuYXJpbyByZXN1bHQuICovXG5hc3luYyBmdW5jdGlvbiBjbGFzc0xpZmVjeWNsZVNjZW5hcmlvKCkge1xuICBjb25zdCB7TW9kZWxDbGFzcywgc3Vic2NyaXB0aW9uc30gPSBidWlsZEZha2VNb2RlbENsYXNzKClcbiAgY29uc3QgcmVjZWl2ZWRFdmVudHMgPSAvKiogQHR5cGUge3Vua25vd25bXX0gKi8gKFtdKVxuICBsZXQgY29ubmVjdGVkQ291bnQgPSAwXG5cbiAgLyoqIEByZXR1cm5zIHtSZWFjdC5SZWFjdEVsZW1lbnR9IC0gVGVzdCBlbGVtZW50LiAqL1xuICBmdW5jdGlvbiBUZXN0Q29tcG9uZW50KCkge1xuICAgIHVzZU1vZGVsQ2xhc3NFdmVudChNb2RlbENsYXNzLCBbXCJjcmVhdGVcIiwgXCJ1cGRhdGVcIl0sIChwYXlsb2FkKSA9PiByZWNlaXZlZEV2ZW50cy5wdXNoKHBheWxvYWQpLCB7XG4gICAgICBvbkNvbm5lY3RlZDogKCkgPT4geyBjb25uZWN0ZWRDb3VudCArPSAxIH1cbiAgICB9KVxuICAgIHVzZUNyZWF0ZWRFdmVudChNb2RlbENsYXNzLCAocGF5bG9hZCkgPT4gcmVjZWl2ZWRFdmVudHMucHVzaChwYXlsb2FkKSlcblxuICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpXG4gIH1cblxuICBjb25zdCBjb250cm9scyA9IGF3YWl0IHJlbmRlckVsZW1lbnQoUmVhY3QuY3JlYXRlRWxlbWVudChUZXN0Q29tcG9uZW50KSlcbiAgYXdhaXQgd2FpdEZvcigoKSA9PiBzdWJzY3JpcHRpb25zLmNyZWF0ZS5zaXplID09PSAyICYmIHN1YnNjcmlwdGlvbnMudXBkYXRlLnNpemUgPT09IDEpXG5cbiAgY29uc3QgbW91bnRlZENyZWF0ZVN1YnNjcmlwdGlvbnMgPSBzdWJzY3JpcHRpb25zLmNyZWF0ZS5zaXplXG4gIGNvbnN0IG1vdW50ZWRVcGRhdGVTdWJzY3JpcHRpb25zID0gc3Vic2NyaXB0aW9ucy51cGRhdGUuc2l6ZVxuICBjb25zdCBtb3VudGVkRGVzdHJveVN1YnNjcmlwdGlvbnMgPSBzdWJzY3JpcHRpb25zLmRlc3Ryb3kuc2l6ZVxuICBjb25zdCBtb3VudGVkQ29ubmVjdGVkQ291bnQgPSBjb25uZWN0ZWRDb3VudFxuXG4gIGVtaXRFdmVudChzdWJzY3JpcHRpb25zLCBcImNyZWF0ZVwiLCB7aWQ6IFwiMVwiLCBtb2RlbDoge2lkOiBcIjFcIn19KVxuICBlbWl0RXZlbnQoc3Vic2NyaXB0aW9ucywgXCJ1cGRhdGVcIiwge2lkOiBcIjFcIiwgbW9kZWw6IHtpZDogXCIxXCJ9fSlcbiAgZW1pdEV2ZW50KHN1YnNjcmlwdGlvbnMsIFwiZGVzdHJveVwiLCB7aWQ6IFwiMVwifSlcblxuICBjb25zdCByZWNlaXZlZEV2ZW50c0FmdGVyRW1pdCA9IHJlY2VpdmVkRXZlbnRzLmxlbmd0aFxuXG4gIGF3YWl0IGNvbnRyb2xzLnVubW91bnQoKVxuXG4gIHJldHVybiB7XG4gICAgbW91bnRlZENvbm5lY3RlZENvdW50LFxuICAgIG1vdW50ZWRDcmVhdGVTdWJzY3JpcHRpb25zLFxuICAgIG1vdW50ZWREZXN0cm95U3Vic2NyaXB0aW9ucyxcbiAgICBtb3VudGVkVXBkYXRlU3Vic2NyaXB0aW9ucyxcbiAgICByZWNlaXZlZEV2ZW50c0FmdGVyRW1pdCxcbiAgICB1bm1vdW50ZWRDcmVhdGVTdWJzY3JpcHRpb25zOiBzdWJzY3JpcHRpb25zLmNyZWF0ZS5zaXplLFxuICAgIHVubW91bnRlZFVwZGF0ZVN1YnNjcmlwdGlvbnM6IHN1YnNjcmlwdGlvbnMudXBkYXRlLnNpemVcbiAgfVxufVxuXG4vKiogQHJldHVybnMge1Byb21pc2U8UmVjb3JkPHN0cmluZywgbnVtYmVyPj59IC0gU2NlbmFyaW8gcmVzdWx0LiAqL1xuYXN5bmMgZnVuY3Rpb24gaW5zdGFuY2VMaWZlY3ljbGVTY2VuYXJpbygpIHtcbiAgY29uc3Qgc3Vic2NyaXB0aW9ucyA9IHtjcmVhdGU6IG5ldyBTZXQoKSwgZGVzdHJveTogbmV3IFNldCgpLCB1cGRhdGU6IG5ldyBTZXQoKX1cbiAgY29uc3QgbW9kZWwgPSBidWlsZEZha2VNb2RlbChcInRhc2stMVwiLCBzdWJzY3JpcHRpb25zKVxuICBjb25zdCByZWNlaXZlZEV2ZW50cyA9IC8qKiBAdHlwZSB7dW5rbm93bltdfSAqLyAoW10pXG4gIGxldCBjb25uZWN0ZWRDb3VudCA9IDBcblxuICAvKiogQHJldHVybnMge1JlYWN0LlJlYWN0RWxlbWVudH0gLSBUZXN0IGVsZW1lbnQuICovXG4gIGZ1bmN0aW9uIFRlc3RDb21wb25lbnQoKSB7XG4gICAgdXNlVXBkYXRlZEV2ZW50KG1vZGVsLCAocGF5bG9hZCkgPT4gcmVjZWl2ZWRFdmVudHMucHVzaChwYXlsb2FkKSwge1xuICAgICAgb25Db25uZWN0ZWQ6ICgpID0+IHsgY29ubmVjdGVkQ291bnQgKz0gMSB9XG4gICAgfSlcbiAgICB1c2VEZXN0cm95ZWRFdmVudChbbW9kZWxdLCAocGF5bG9hZCkgPT4gcmVjZWl2ZWRFdmVudHMucHVzaChwYXlsb2FkKSwge1xuICAgICAgb25Db25uZWN0ZWQ6ICgpID0+IHsgY29ubmVjdGVkQ291bnQgKz0gMSB9XG4gICAgfSlcblxuICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpXG4gIH1cblxuICBjb25zdCBjb250cm9scyA9IGF3YWl0IHJlbmRlckVsZW1lbnQoUmVhY3QuY3JlYXRlRWxlbWVudChUZXN0Q29tcG9uZW50KSlcbiAgYXdhaXQgd2FpdEZvcigoKSA9PiBzdWJzY3JpcHRpb25zLnVwZGF0ZS5zaXplID09PSAxICYmIHN1YnNjcmlwdGlvbnMuZGVzdHJveS5zaXplID09PSAxKVxuXG4gIGNvbnN0IG1vdW50ZWRDb25uZWN0ZWRDb3VudCA9IGNvbm5lY3RlZENvdW50XG4gIGNvbnN0IG1vdW50ZWREZXN0cm95U3Vic2NyaXB0aW9ucyA9IHN1YnNjcmlwdGlvbnMuZGVzdHJveS5zaXplXG4gIGNvbnN0IG1vdW50ZWRVcGRhdGVTdWJzY3JpcHRpb25zID0gc3Vic2NyaXB0aW9ucy51cGRhdGUuc2l6ZVxuXG4gIGVtaXRFdmVudChzdWJzY3JpcHRpb25zLCBcInVwZGF0ZVwiLCB7aWQ6IFwidGFzay0xXCIsIG1vZGVsfSlcbiAgZW1pdEV2ZW50KHN1YnNjcmlwdGlvbnMsIFwiZGVzdHJveVwiLCB7aWQ6IFwidGFzay0xXCJ9KVxuXG4gIGNvbnN0IHJlY2VpdmVkRXZlbnRzQWZ0ZXJFbWl0ID0gcmVjZWl2ZWRFdmVudHMubGVuZ3RoXG5cbiAgYXdhaXQgY29udHJvbHMudW5tb3VudCgpXG5cbiAgcmV0dXJuIHtcbiAgICBtb3VudGVkQ29ubmVjdGVkQ291bnQsXG4gICAgbW91bnRlZERlc3Ryb3lTdWJzY3JpcHRpb25zLFxuICAgIG1vdW50ZWRVcGRhdGVTdWJzY3JpcHRpb25zLFxuICAgIHJlY2VpdmVkRXZlbnRzQWZ0ZXJFbWl0LFxuICAgIHVubW91bnRlZERlc3Ryb3lTdWJzY3JpcHRpb25zOiBzdWJzY3JpcHRpb25zLmRlc3Ryb3kuc2l6ZSxcbiAgICB1bm1vdW50ZWRVcGRhdGVTdWJzY3JpcHRpb25zOiBzdWJzY3JpcHRpb25zLnVwZGF0ZS5zaXplXG4gIH1cbn1cblxuLyoqIEByZXR1cm5zIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIG51bWJlcj4+fSAtIFNjZW5hcmlvIHJlc3VsdC4gKi9cbmFzeW5jIGZ1bmN0aW9uIGRlYm91bmNlVW5tb3VudFNjZW5hcmlvKCkge1xuICBjb25zdCB7TW9kZWxDbGFzcywgc3Vic2NyaXB0aW9uczogY2xhc3NTdWJzY3JpcHRpb25zfSA9IGJ1aWxkRmFrZU1vZGVsQ2xhc3MoKVxuICBjb25zdCBpbnN0YW5jZVN1YnNjcmlwdGlvbnMgPSB7Y3JlYXRlOiBuZXcgU2V0KCksIGRlc3Ryb3k6IG5ldyBTZXQoKSwgdXBkYXRlOiBuZXcgU2V0KCl9XG4gIGNvbnN0IG1vZGVsID0gYnVpbGRGYWtlTW9kZWwoXCJ0YXNrLTFcIiwgaW5zdGFuY2VTdWJzY3JpcHRpb25zKVxuICBjb25zdCByZWNlaXZlZEV2ZW50cyA9IC8qKiBAdHlwZSB7dW5rbm93bltdfSAqLyAoW10pXG5cbiAgLyoqIEByZXR1cm5zIHtSZWFjdC5SZWFjdEVsZW1lbnR9IC0gVGVzdCBlbGVtZW50LiAqL1xuICBmdW5jdGlvbiBUZXN0Q29tcG9uZW50KCkge1xuICAgIHVzZU1vZGVsQ2xhc3NFdmVudChNb2RlbENsYXNzLCBcInVwZGF0ZVwiLCAocGF5bG9hZCkgPT4gcmVjZWl2ZWRFdmVudHMucHVzaChwYXlsb2FkKSwge2RlYm91bmNlOiAyMH0pXG4gICAgdXNlVXBkYXRlZEV2ZW50KG1vZGVsLCAocGF5bG9hZCkgPT4gcmVjZWl2ZWRFdmVudHMucHVzaChwYXlsb2FkKSwge2RlYm91bmNlOiAyMH0pXG4gICAgdXNlRGVzdHJveWVkRXZlbnQobW9kZWwsIChwYXlsb2FkKSA9PiByZWNlaXZlZEV2ZW50cy5wdXNoKHBheWxvYWQpLCB7ZGVib3VuY2U6IDIwfSlcblxuICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpXG4gIH1cblxuICBjb25zdCBjb250cm9scyA9IGF3YWl0IHJlbmRlckVsZW1lbnQoUmVhY3QuY3JlYXRlRWxlbWVudChUZXN0Q29tcG9uZW50KSlcbiAgYXdhaXQgd2FpdEZvcigoKSA9PiBjbGFzc1N1YnNjcmlwdGlvbnMudXBkYXRlLnNpemUgPT09IDEgJiYgaW5zdGFuY2VTdWJzY3JpcHRpb25zLnVwZGF0ZS5zaXplID09PSAxICYmIGluc3RhbmNlU3Vic2NyaXB0aW9ucy5kZXN0cm95LnNpemUgPT09IDEpXG5cbiAgZW1pdEV2ZW50KGNsYXNzU3Vic2NyaXB0aW9ucywgXCJ1cGRhdGVcIiwge2lkOiBcInRhc2stMVwiLCBtb2RlbH0pXG4gIGVtaXRFdmVudChpbnN0YW5jZVN1YnNjcmlwdGlvbnMsIFwidXBkYXRlXCIsIHtpZDogXCJ0YXNrLTFcIiwgbW9kZWx9KVxuICBlbWl0RXZlbnQoaW5zdGFuY2VTdWJzY3JpcHRpb25zLCBcImRlc3Ryb3lcIiwge2lkOiBcInRhc2stMVwifSlcblxuICBhd2FpdCBjb250cm9scy51bm1vdW50KClcbiAgYXdhaXQgc2xlZXAoMzApXG5cbiAgcmV0dXJuIHtyZWNlaXZlZEV2ZW50c0FmdGVyRGVib3VuY2VXaW5kb3c6IHJlY2VpdmVkRXZlbnRzLmxlbmd0aH1cbn1cblxuLyoqIEByZXR1cm5zIHtQcm9taXNlPFJlY29yZDxzdHJpbmcsIG51bWJlcj4+fSAtIFNjZW5hcmlvIHJlc3VsdC4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlc3Vic2NyaWJlSW5zdGFuY2VTY2VuYXJpbygpIHtcbiAgY29uc3QgZmlyc3RTdWJzY3JpcHRpb25zID0ge2NyZWF0ZTogbmV3IFNldCgpLCBkZXN0cm95OiBuZXcgU2V0KCksIHVwZGF0ZTogbmV3IFNldCgpfVxuICBjb25zdCBzZWNvbmRTdWJzY3JpcHRpb25zID0ge2NyZWF0ZTogbmV3IFNldCgpLCBkZXN0cm95OiBuZXcgU2V0KCksIHVwZGF0ZTogbmV3IFNldCgpfVxuICBjb25zdCBmaXJzdE1vZGVsID0gYnVpbGRGYWtlTW9kZWwoXCJ0YXNrLTFcIiwgZmlyc3RTdWJzY3JpcHRpb25zKVxuICBjb25zdCBzZWNvbmRNb2RlbCA9IGJ1aWxkRmFrZU1vZGVsKFwidGFzay0xXCIsIHNlY29uZFN1YnNjcmlwdGlvbnMpXG4gIGNvbnN0IHJlY2VpdmVkRXZlbnRzID0gLyoqIEB0eXBlIHt1bmtub3duW119ICovIChbXSlcblxuICAvKipcbiAgICogQHBhcmFtIHt7bW9kZWw6IGltcG9ydChcIi4uL2Zyb250ZW5kLW1vZGVscy9iYXNlLmpzXCIpLmRlZmF1bHR9fSBwcm9wcyAtIENvbXBvbmVudCBwcm9wcy5cbiAgICogQHJldHVybnMge1JlYWN0LlJlYWN0RWxlbWVudH0gLSBUZXN0IGVsZW1lbnQuXG4gICAqL1xuICBmdW5jdGlvbiBUZXN0Q29tcG9uZW50KHttb2RlbH0pIHtcbiAgICB1c2VVcGRhdGVkRXZlbnQobW9kZWwsIChwYXlsb2FkKSA9PiByZWNlaXZlZEV2ZW50cy5wdXNoKHBheWxvYWQpKVxuICAgIHVzZURlc3Ryb3llZEV2ZW50KG1vZGVsLCAocGF5bG9hZCkgPT4gcmVjZWl2ZWRFdmVudHMucHVzaChwYXlsb2FkKSlcblxuICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpXG4gIH1cblxuICBjb25zdCBjb250cm9scyA9IGF3YWl0IHJlbmRlckVsZW1lbnQoUmVhY3QuY3JlYXRlRWxlbWVudChUZXN0Q29tcG9uZW50LCB7bW9kZWw6IGZpcnN0TW9kZWx9KSlcbiAgYXdhaXQgd2FpdEZvcigoKSA9PiBmaXJzdFN1YnNjcmlwdGlvbnMudXBkYXRlLnNpemUgPT09IDEgJiYgZmlyc3RTdWJzY3JpcHRpb25zLmRlc3Ryb3kuc2l6ZSA9PT0gMSlcblxuICBjb25zdCBmaXJzdE1vdW50ZWREZXN0cm95U3Vic2NyaXB0aW9ucyA9IGZpcnN0U3Vic2NyaXB0aW9ucy5kZXN0cm95LnNpemVcbiAgY29uc3QgZmlyc3RNb3VudGVkVXBkYXRlU3Vic2NyaXB0aW9ucyA9IGZpcnN0U3Vic2NyaXB0aW9ucy51cGRhdGUuc2l6ZVxuXG4gIGF3YWl0IGNvbnRyb2xzLnJlcmVuZGVyKFJlYWN0LmNyZWF0ZUVsZW1lbnQoVGVzdENvbXBvbmVudCwge21vZGVsOiBzZWNvbmRNb2RlbH0pKVxuICBhd2FpdCB3YWl0Rm9yKCgpID0+IGZpcnN0U3Vic2NyaXB0aW9ucy51cGRhdGUuc2l6ZSA9PT0gMCAmJiBmaXJzdFN1YnNjcmlwdGlvbnMuZGVzdHJveS5zaXplID09PSAwICYmIHNlY29uZFN1YnNjcmlwdGlvbnMudXBkYXRlLnNpemUgPT09IDEgJiYgc2Vjb25kU3Vic2NyaXB0aW9ucy5kZXN0cm95LnNpemUgPT09IDEpXG5cbiAgY29uc3QgZmlyc3RBZnRlclJlcmVuZGVyRGVzdHJveVN1YnNjcmlwdGlvbnMgPSBmaXJzdFN1YnNjcmlwdGlvbnMuZGVzdHJveS5zaXplXG4gIGNvbnN0IGZpcnN0QWZ0ZXJSZXJlbmRlclVwZGF0ZVN1YnNjcmlwdGlvbnMgPSBmaXJzdFN1YnNjcmlwdGlvbnMudXBkYXRlLnNpemVcbiAgY29uc3Qgc2Vjb25kQWZ0ZXJSZXJlbmRlckRlc3Ryb3lTdWJzY3JpcHRpb25zID0gc2Vjb25kU3Vic2NyaXB0aW9ucy5kZXN0cm95LnNpemVcbiAgY29uc3Qgc2Vjb25kQWZ0ZXJSZXJlbmRlclVwZGF0ZVN1YnNjcmlwdGlvbnMgPSBzZWNvbmRTdWJzY3JpcHRpb25zLnVwZGF0ZS5zaXplXG5cbiAgZW1pdEV2ZW50KGZpcnN0U3Vic2NyaXB0aW9ucywgXCJ1cGRhdGVcIiwge2lkOiBcInRhc2stMVwiLCBtb2RlbDogZmlyc3RNb2RlbH0pXG4gIGVtaXRFdmVudChzZWNvbmRTdWJzY3JpcHRpb25zLCBcInVwZGF0ZVwiLCB7aWQ6IFwidGFzay0xXCIsIG1vZGVsOiBzZWNvbmRNb2RlbH0pXG4gIGVtaXRFdmVudChzZWNvbmRTdWJzY3JpcHRpb25zLCBcImRlc3Ryb3lcIiwge2lkOiBcInRhc2stMVwifSlcblxuICBjb25zdCByZWNlaXZlZEV2ZW50c0FmdGVyRW1pdCA9IHJlY2VpdmVkRXZlbnRzLmxlbmd0aFxuXG4gIGF3YWl0IGNvbnRyb2xzLnVubW91bnQoKVxuXG4gIHJldHVybiB7XG4gICAgZmlyc3RBZnRlclJlcmVuZGVyRGVzdHJveVN1YnNjcmlwdGlvbnMsXG4gICAgZmlyc3RBZnRlclJlcmVuZGVyVXBkYXRlU3Vic2NyaXB0aW9ucyxcbiAgICBmaXJzdE1vdW50ZWREZXN0cm95U3Vic2NyaXB0aW9ucyxcbiAgICBmaXJzdE1vdW50ZWRVcGRhdGVTdWJzY3JpcHRpb25zLFxuICAgIHJlY2VpdmVkRXZlbnRzQWZ0ZXJFbWl0LFxuICAgIHNlY29uZEFmdGVyUmVyZW5kZXJEZXN0cm95U3Vic2NyaXB0aW9ucyxcbiAgICBzZWNvbmRBZnRlclJlcmVuZGVyVXBkYXRlU3Vic2NyaXB0aW9uc1xuICB9XG59XG5cbmNvbnN0IHNjZW5hcmlvcyA9IHtcbiAgY2xhc3NMaWZlY3ljbGU6IGNsYXNzTGlmZWN5Y2xlU2NlbmFyaW8sXG4gIGRlYm91bmNlVW5tb3VudDogZGVib3VuY2VVbm1vdW50U2NlbmFyaW8sXG4gIGluc3RhbmNlTGlmZWN5Y2xlOiBpbnN0YW5jZUxpZmVjeWNsZVNjZW5hcmlvLFxuICByZXN1YnNjcmliZUluc3RhbmNlOiByZXN1YnNjcmliZUluc3RhbmNlU2NlbmFyaW9cbn1cblxuLyoqXG4gKiBAcGFyYW0ge2tleW9mIHR5cGVvZiBzY2VuYXJpb3N9IHNjZW5hcmlvTmFtZSAtIFNjZW5hcmlvIG5hbWUuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBudW1iZXI+Pn0gLSBTY2VuYXJpbyByZXN1bHQuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGFzeW5jIGZ1bmN0aW9uIHJ1bkZyb250ZW5kTW9kZWxFdmVudEhvb2tTY2VuYXJpbyhzY2VuYXJpb05hbWUpIHtcbiAgY29uc3Qgc2NlbmFyaW8gPSBzY2VuYXJpb3Nbc2NlbmFyaW9OYW1lXVxuXG4gIGlmICghc2NlbmFyaW8pIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBmcm9udGVuZCBtb2RlbCBldmVudCBob29rIHNjZW5hcmlvOiAke3NjZW5hcmlvTmFtZX1gKVxuXG4gIHJldHVybiBhd2FpdCBzY2VuYXJpbygpXG59XG4iXX0=
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import SystemTestBrowserHelper from "system-testing/build/system-test-browser-helper.js";
|
|
3
3
|
import BrowserEnvironmentHandler from "../environment-handlers/browser.js";
|
|
4
|
+
import runFrontendModelEventHookScenario from "./browser-frontend-model-event-hook-scenarios.js";
|
|
4
5
|
const root = document.getElementById("root") || (() => {
|
|
5
6
|
const element = document.createElement("div");
|
|
6
7
|
element.id = "root";
|
|
@@ -19,6 +20,7 @@ const systemTestBrowserHelper = new SystemTestBrowserHelper();
|
|
|
19
20
|
systemTestBrowserHelper.enableOnBrowser();
|
|
20
21
|
globalThis.velociousBrowserTest = {
|
|
21
22
|
BrowserEnvironmentHandler,
|
|
23
|
+
runFrontendModelEventHookScenario,
|
|
22
24
|
systemTestBrowserHelper
|
|
23
25
|
};
|
|
24
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
26
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJvd3Nlci10ZXN0LWFwcC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy90ZXN0aW5nL2Jyb3dzZXItdGVzdC1hcHAuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sdUJBQXVCLE1BQU0sb0RBQW9ELENBQUE7QUFDeEYsT0FBTyx5QkFBeUIsTUFBTSxvQ0FBb0MsQ0FBQTtBQUMxRSxPQUFPLGlDQUFpQyxNQUFNLGtEQUFrRCxDQUFBO0FBRWhHLE1BQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUU7SUFDcEQsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUM3QyxPQUFPLENBQUMsRUFBRSxHQUFHLE1BQU0sQ0FBQTtJQUNuQixRQUFRLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQTtJQUNsQyxPQUFPLE9BQU8sQ0FBQTtBQUNoQixDQUFDLENBQUMsRUFBRSxDQUFBO0FBRUosTUFBTSxzQkFBc0IsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFBO0FBQzVELHNCQUFzQixDQUFDLFlBQVksQ0FBQyxhQUFhLEVBQUUsd0JBQXdCLENBQUMsQ0FBQTtBQUM1RSxzQkFBc0IsQ0FBQyxZQUFZLENBQUMsZUFBZSxFQUFFLE1BQU0sQ0FBQyxDQUFBO0FBRTVELE1BQU0sU0FBUyxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUE7QUFDL0MsU0FBUyxDQUFDLFlBQVksQ0FBQyxhQUFhLEVBQUUsV0FBVyxDQUFDLENBQUE7QUFDbEQsU0FBUyxDQUFDLFdBQVcsR0FBRyxPQUFPLENBQUE7QUFFL0Isc0JBQXNCLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxDQUFBO0FBQzdDLElBQUksQ0FBQyxXQUFXLENBQUMsc0JBQXNCLENBQUMsQ0FBQTtBQUV4QyxNQUFNLHVCQUF1QixHQUFHLElBQUksdUJBQXVCLEVBQUUsQ0FBQTtBQUM3RCx1QkFBdUIsQ0FBQyxlQUFlLEVBQUUsQ0FBQTtBQUV6QyxVQUFVLENBQUMsb0JBQW9CLEdBQUc7SUFDaEMseUJBQXlCO0lBQ3pCLGlDQUFpQztJQUNqQyx1QkFBdUI7Q0FDeEIsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgU3lzdGVtVGVzdEJyb3dzZXJIZWxwZXIgZnJvbSBcInN5c3RlbS10ZXN0aW5nL2J1aWxkL3N5c3RlbS10ZXN0LWJyb3dzZXItaGVscGVyLmpzXCJcbmltcG9ydCBCcm93c2VyRW52aXJvbm1lbnRIYW5kbGVyIGZyb20gXCIuLi9lbnZpcm9ubWVudC1oYW5kbGVycy9icm93c2VyLmpzXCJcbmltcG9ydCBydW5Gcm9udGVuZE1vZGVsRXZlbnRIb29rU2NlbmFyaW8gZnJvbSBcIi4vYnJvd3Nlci1mcm9udGVuZC1tb2RlbC1ldmVudC1ob29rLXNjZW5hcmlvcy5qc1wiXG5cbmNvbnN0IHJvb3QgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInJvb3RcIikgfHwgKCgpID0+IHtcbiAgY29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIilcbiAgZWxlbWVudC5pZCA9IFwicm9vdFwiXG4gIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoZWxlbWVudClcbiAgcmV0dXJuIGVsZW1lbnRcbn0pKClcblxuY29uc3Qgc3lzdGVtVGVzdGluZ0NvbXBvbmVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIilcbnN5c3RlbVRlc3RpbmdDb21wb25lbnQuc2V0QXR0cmlidXRlKFwiZGF0YS10ZXN0aWRcIiwgXCJzeXN0ZW1UZXN0aW5nQ29tcG9uZW50XCIpXG5zeXN0ZW1UZXN0aW5nQ29tcG9uZW50LnNldEF0dHJpYnV0ZShcImRhdGEtZm9jdXNzZWRcIiwgXCJ0cnVlXCIpXG5cbmNvbnN0IGJsYW5rVGV4dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIilcbmJsYW5rVGV4dC5zZXRBdHRyaWJ1dGUoXCJkYXRhLXRlc3RpZFwiLCBcImJsYW5rVGV4dFwiKVxuYmxhbmtUZXh0LnRleHRDb250ZW50ID0gXCJibGFua1wiXG5cbnN5c3RlbVRlc3RpbmdDb21wb25lbnQuYXBwZW5kQ2hpbGQoYmxhbmtUZXh0KVxucm9vdC5hcHBlbmRDaGlsZChzeXN0ZW1UZXN0aW5nQ29tcG9uZW50KVxuXG5jb25zdCBzeXN0ZW1UZXN0QnJvd3NlckhlbHBlciA9IG5ldyBTeXN0ZW1UZXN0QnJvd3NlckhlbHBlcigpXG5zeXN0ZW1UZXN0QnJvd3NlckhlbHBlci5lbmFibGVPbkJyb3dzZXIoKVxuXG5nbG9iYWxUaGlzLnZlbG9jaW91c0Jyb3dzZXJUZXN0ID0ge1xuICBCcm93c2VyRW52aXJvbm1lbnRIYW5kbGVyLFxuICBydW5Gcm9udGVuZE1vZGVsRXZlbnRIb29rU2NlbmFyaW8sXG4gIHN5c3RlbVRlc3RCcm93c2VySGVscGVyXG59XG4iXX0=
|