ngx-speculoos 4.1.0 → 7.1.0

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.
Files changed (41) hide show
  1. package/esm2020/jasmine-matchers.mjs +2 -0
  2. package/esm2020/lib/component-tester.mjs +147 -0
  3. package/esm2020/lib/matchers.mjs +283 -0
  4. package/esm2020/lib/mock.mjs +25 -0
  5. package/esm2020/lib/route.mjs +306 -0
  6. package/{esm2015/lib/test-button.js → esm2020/lib/test-button.mjs} +1 -1
  7. package/esm2020/lib/test-element-querier.mjs +140 -0
  8. package/esm2020/lib/test-element.mjs +142 -0
  9. package/{esm2015/lib/test-html-element.js → esm2020/lib/test-html-element.mjs} +1 -1
  10. package/{esm2015/lib/test-input.js → esm2020/lib/test-input.mjs} +1 -1
  11. package/{esm2015/lib/test-select.js → esm2020/lib/test-select.mjs} +1 -1
  12. package/{esm2015/lib/test-textarea.js → esm2020/lib/test-textarea.mjs} +1 -1
  13. package/{esm2015/ngx-speculoos.js → esm2020/ngx-speculoos.mjs} +0 -0
  14. package/{esm2015/public_api.js → esm2020/public_api.mjs} +3 -2
  15. package/fesm2015/ngx-speculoos.mjs +1244 -0
  16. package/fesm2015/ngx-speculoos.mjs.map +1 -0
  17. package/fesm2020/ngx-speculoos.mjs +1240 -0
  18. package/fesm2020/ngx-speculoos.mjs.map +1 -0
  19. package/jasmine-matchers.d.ts +5 -0
  20. package/lib/component-tester.d.ts +87 -49
  21. package/lib/mock.d.ts +10 -0
  22. package/lib/route.d.ts +144 -0
  23. package/lib/test-element-querier.d.ts +15 -15
  24. package/lib/test-element.d.ts +87 -49
  25. package/ngx-speculoos.d.ts +1 -0
  26. package/package.json +25 -13
  27. package/public_api.d.ts +1 -0
  28. package/CHANGELOG.md +0 -143
  29. package/bundles/ngx-speculoos.umd.js +0 -1257
  30. package/bundles/ngx-speculoos.umd.js.map +0 -1
  31. package/bundles/ngx-speculoos.umd.min.js +0 -16
  32. package/bundles/ngx-speculoos.umd.min.js.map +0 -1
  33. package/esm2015/jasmine-matchers.js +0 -2
  34. package/esm2015/lib/component-tester.js +0 -95
  35. package/esm2015/lib/matchers.js +0 -246
  36. package/esm2015/lib/route.js +0 -81
  37. package/esm2015/lib/test-element-querier.js +0 -129
  38. package/esm2015/lib/test-element.js +0 -91
  39. package/fesm2015/ngx-speculoos.js +0 -839
  40. package/fesm2015/ngx-speculoos.js.map +0 -1
  41. package/ngx-speculoos.metadata.json +0 -1
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiamFzbWluZS1tYXRjaGVycy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL25neC1zcGVjdWxvb3Mvc3JjL2phc21pbmUtbWF0Y2hlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1uYW1lc3BhY2UsQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzICovXG5kZWNsYXJlIG5hbWVzcGFjZSBqYXNtaW5lIHtcbiAgaW50ZXJmYWNlIE1hdGNoZXJzPFQ+IHtcbiAgICAvKipcbiAgICAgKiBDaGVja3MgdGhhdCB0aGUgcmVjZWl2ZXIgaXMgYSBUZXN0RWxlbWVudCB3cmFwcGluZyBhIERPTSBlbGVtZW50IGFuZCBoYXMgdGhlIGdpdmVuIENTUyBjbGFzc1xuICAgICAqL1xuICAgIHRvSGF2ZUNsYXNzKGNsYXNzTmFtZTogc3RyaW5nKTogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyB0aGF0IHRoZSByZWNlaXZlciBpcyBhIFRlc3RJbnB1dCBvciBhIFRlc3RUZXh0QXJlYSBhbmQgaGFzIHRoZSBnaXZlbiB2YWx1ZVxuICAgICAqL1xuICAgIHRvSGF2ZVZhbHVlKHZhbHVlOiBzdHJpbmcpOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIHRoYXQgdGhlIHJlY2VpdmVyIGlzIGEgVGVzdEVsZW1lbnQgd3JhcHBpbmcgYSBET00gZWxlbWVudCBhbmQgaGFzIHRoZSBleGFjdCBnaXZlbiB0ZXh0Q29udGVudFxuICAgICAqL1xuICAgIHRvSGF2ZVRleHQodGV4dENvbnRlbnQ6IHN0cmluZyk6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgdGhhdCB0aGUgcmVjZWl2ZXIgaXMgYSBUZXN0RWxlbWVudCB3cmFwcGluZyBhIERPTSBlbGVtZW50IGFuZCBoYXMgdGhlIGdpdmVuIHRleHRDb250ZW50XG4gICAgICogYWZ0ZXIgYm90aCBoYXZlIGJlZW4gdHJpbW1lZC5cbiAgICAgKi9cbiAgICB0b0hhdmVUcmltbWVkVGV4dCh0ZXh0Q29udGVudDogc3RyaW5nKTogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyB0aGF0IHRoZSByZWNlaXZlciBpcyBhIFRlc3RFbGVtZW50IHdyYXBwaW5nIGEgRE9NIGVsZW1lbnQgYW5kIGNvbnRhaW5zIHRoZSBnaXZlbiB0ZXh0Q29udGVudFxuICAgICAqL1xuICAgIHRvQ29udGFpblRleHQodGV4dENvbnRlbnQ6IHN0cmluZyk6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgdGhhdCB0aGUgcmVjZWl2ZXIgaXMgYSBUZXN0SW5wdXQgYW5kIGlzIGNoZWNrZWRcbiAgICAgKi9cbiAgICB0b0JlQ2hlY2tlZCgpOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIHRoYXQgdGhlIHJlY2VpdmVyIGlzIGEgVGVzdFNlbGVjdCB3cmFwcGluZyBhIERPTSBlbGVtZW50IGFuZCBoYXMgdGhlIGdpdmVuIHNlbGVjdGVkIGluZGV4XG4gICAgICovXG4gICAgdG9IYXZlU2VsZWN0ZWRJbmRleChpbmRleDogbnVtYmVyKTogYm9vbGVhbjtcblxuICAgIC8qKlxuICAgICAqIENoZWNrcyB0aGF0IHRoZSByZWNlaXZlciBpcyBhIFRlc3RTZWxlY3Qgd3JhcHBpbmcgYSBET00gZWxlbWVudCB3aXRoIHRoZSBzZWxlY3RlZCBvcHRpb24ncyB2YWx1ZSBlcXVhbCB0byB0aGUgZ2l2ZW4gdmFsdWVcbiAgICAgKi9cbiAgICB0b0hhdmVTZWxlY3RlZFZhbHVlKHZhbHVlOiBzdHJpbmcpOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIHRoYXQgdGhlIHJlY2VpdmVyIGlzIGEgVGVzdFNlbGVjdCB3cmFwcGluZyBhIERPTSBlbGVtZW50IHdpdGggdGhlIHNlbGVjdGVkIG9wdGlvbidzIGxhYmVsIGVxdWFsIHRvIHRoZSBnaXZlbiBsYWJlbFxuICAgICAqL1xuICAgIHRvSGF2ZVNlbGVjdGVkTGFiZWwobGFiZWw6IHN0cmluZyk6IGJvb2xlYW47XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3MgdGhhdCB0aGUgcmVjZWl2ZXIgaXMgYSBUZXN0SHRtbEVsZW1lbnQgd2hpY2ggaXMgdmlzaWJsZS5cbiAgICAgKi9cbiAgICB0b0JlVmlzaWJsZSgpOiBib29sZWFuO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,147 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ /* eslint-disable @typescript-eslint/no-explicit-any */
3
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
4
+ import { TestElementQuerier } from './test-element-querier';
5
+ /**
6
+ * The main entry point of the API. It wraps an Angular ComponentFixture<T>, and gives access to its
7
+ * most used properties and methods. It also allows getting elements wrapped in TestElement (and its subclasses)
8
+ * @param <C> the type of the component to test
9
+ */
10
+ export class ComponentTester {
11
+ /**
12
+ * Creates a ComponentFixture for the given component type using the TestBed, and creates a ComponentTester
13
+ * wrapping (and delegating) to this fixture. If a fixture is passed, then delegates to this fixture directly.
14
+ *
15
+ * Note that no `detectChanges()` call is made by this constructor. It's up to the subclass constructor,
16
+ * or to the user of the created ComponentTester, to call `detectChanges()` at least once to trigger change
17
+ * detection. This is necessary because some component templates can only be evaluated once inputs
18
+ * have been set on the component instance.
19
+ *
20
+ * @param arg the type of the component to wrap, or a component fixture to wrap
21
+ */
22
+ constructor(arg) {
23
+ this.fixture = arg instanceof ComponentFixture ? arg : TestBed.createComponent(arg);
24
+ this.testElement = TestElementQuerier.wrap(this.debugElement, this);
25
+ }
26
+ /**
27
+ * Creates a component fixture of the given type with the TestBed and wraps it into a ComponentTester
28
+ */
29
+ static create(componentType) {
30
+ const fixture = TestBed.createComponent(componentType);
31
+ return new ComponentTester(fixture);
32
+ }
33
+ /**
34
+ * The native DOM host element of the component
35
+ */
36
+ get nativeElement() {
37
+ return this.fixture.nativeElement;
38
+ }
39
+ /**
40
+ * Gets the instance of the tested component from the wrapped fixture
41
+ */
42
+ get componentInstance() {
43
+ return this.fixture.componentInstance;
44
+ }
45
+ /**
46
+ * Gets the debug element from the wrapped fixture
47
+ */
48
+ get debugElement() {
49
+ return this.fixture.debugElement;
50
+ }
51
+ element(selector) {
52
+ return this.testElement.element(selector);
53
+ }
54
+ elements(selector) {
55
+ return this.testElement.elements(selector);
56
+ }
57
+ /**
58
+ * Gets the first input matched by the given selector. Throws an Error if the matched element isn't actually an input.
59
+ * @param selector a CSS or directive selector
60
+ * @returns the wrapped input, or null if no element was matched
61
+ */
62
+ input(selector) {
63
+ return this.testElement.input(selector);
64
+ }
65
+ /**
66
+ * Gets the first select matched by the given selector. Throws an Error if the matched element isn't actually a select.
67
+ * @param selector a CSS or directive selector
68
+ * @returns the wrapped select, or null if no element was matched
69
+ */
70
+ select(selector) {
71
+ return this.testElement.select(selector);
72
+ }
73
+ /**
74
+ * Gets the first textarea matched by the given selector
75
+ * @param selector a CSS or directive selector
76
+ * @returns the wrapped textarea, or null if no element was matched. Throws an Error if the matched element isn't actually a textarea.
77
+ * @throws {Error} if the matched element isn't actually a textarea
78
+ */
79
+ textarea(selector) {
80
+ return this.testElement.textarea(selector);
81
+ }
82
+ /**
83
+ * Gets the first button matched by the given selector. Throws an Error if the matched element isn't actually a button.
84
+ * @param selector a CSS or directive selector
85
+ * @returns the wrapped button, or null if no element was matched
86
+ */
87
+ button(selector) {
88
+ return this.testElement.button(selector);
89
+ }
90
+ /**
91
+ * Gets the first directive matching the given component directive selector and returns its component instance
92
+ * @param selector the selector of a component directive
93
+ */
94
+ component(selector) {
95
+ return this.testElement.component(selector);
96
+ }
97
+ /**
98
+ * Gets the directives matching the given component directive selector and returns their component instance
99
+ * @param selector the selector of a component directive
100
+ */
101
+ components(selector) {
102
+ return this.testElement.components(selector);
103
+ }
104
+ /**
105
+ * Gets the first element matching the given selector, then gets the given token from its injector, or null if there is no such token
106
+ * @param selector a CSS or directive selector
107
+ * @param token the token to get from the matched element injector
108
+ */
109
+ token(selector, token) {
110
+ return this.testElement.token(selector, token);
111
+ }
112
+ /**
113
+ * Gets the elements matching the given selector, then gets their given token from their injector, or null if there is no such token
114
+ * @param selector a CSS or directive selector
115
+ * @param token the token to get from the matched element injector
116
+ */
117
+ tokens(selector, token) {
118
+ return this.testElement.tokens(selector, token);
119
+ }
120
+ /**
121
+ * Gets the element matching the given selector, and if found, creates and returns a custom TestElement of the provided
122
+ * type. This is useful to create custom higher-level abstractions similar to TestInput, TestSelect, etc. for
123
+ * custom elements or components.
124
+ * @param selector a CSS or directive selector
125
+ * @param customTestElementType the type of the TestElement subclass that will wrap the found element
126
+ */
127
+ custom(selector, customTestElementType) {
128
+ return this.testElement.custom(selector, customTestElementType);
129
+ }
130
+ /**
131
+ * Gets the elements matching the given selector, and creates and returns custom TestElements of the provided
132
+ * type. This is useful to create custom higher-level abstractions similar to TestInput, TestSelect, etc. for
133
+ * custom elements or components.
134
+ * @param selector a CSS or directive selector
135
+ * @param customTestElementType the type of the TestElement subclass that will wrap the found elements
136
+ */
137
+ customs(selector, customTestElementType) {
138
+ return this.testElement.customs(selector, customTestElementType);
139
+ }
140
+ /**
141
+ * Triggers a change detection using the wrapped fixture
142
+ */
143
+ detectChanges(checkNoChanges) {
144
+ this.fixture.detectChanges(checkNoChanges);
145
+ }
146
+ }
147
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9uZW50LXRlc3Rlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1zcGVjdWxvb3Mvc3JjL2xpYi9jb21wb25lbnQtdGVzdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHNEQUFzRDtBQUN0RCx1REFBdUQ7QUFDdkQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE9BQU8sRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBT2xFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRzVEOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sZUFBZTtJQW1CMUI7Ozs7Ozs7Ozs7T0FVRztJQUNILFlBQVksR0FBa0M7UUFDNUMsSUFBSSxDQUFDLE9BQU8sR0FBRyxHQUFHLFlBQVksZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNwRixJQUFJLENBQUMsV0FBVyxHQUFHLGtCQUFrQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBNkIsQ0FBQztJQUNsRyxDQUFDO0lBdEJEOztPQUVHO0lBQ0gsTUFBTSxDQUFDLE1BQU0sQ0FBSSxhQUFzQjtRQUNyQyxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsZUFBZSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQ3ZELE9BQU8sSUFBSSxlQUFlLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQWtCRDs7T0FFRztJQUNILElBQUksYUFBYTtRQUNmLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUM7SUFDcEMsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBSSxpQkFBaUI7UUFDbkIsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDO0lBQ3hDLENBQUM7SUFFRDs7T0FFRztJQUNILElBQUksWUFBWTtRQUNkLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUM7SUFDbkMsQ0FBQztJQThHRCxPQUFPLENBQUMsUUFBNEI7UUFDbEMsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM1QyxDQUFDO0lBOEdELFFBQVEsQ0FBQyxRQUE0QjtRQUNuQyxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQzdDLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFDLFFBQTRCO1FBQ2hDLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxNQUFNLENBQUMsUUFBNEI7UUFDakMsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxRQUFRLENBQUMsUUFBNEI7UUFDbkMsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM3QyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILE1BQU0sQ0FBQyxRQUE0QjtRQUNqQyxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFFRDs7O09BR0c7SUFDSCxTQUFTLENBQUksUUFBaUI7UUFDNUIsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM5QyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsVUFBVSxDQUFJLFFBQWlCO1FBQzdCLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxLQUFLLENBQUksUUFBNEIsRUFBRSxLQUF1QjtRQUM1RCxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILE1BQU0sQ0FBSSxRQUE0QixFQUFFLEtBQXVCO1FBQzdELE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSCxNQUFNLENBQXdCLFFBQTRCLEVBQUUscUJBQThCO1FBQ3hGLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLHFCQUFxQixDQUFDLENBQUM7SUFDbEUsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILE9BQU8sQ0FBd0IsUUFBNEIsRUFBRSxxQkFBOEI7UUFDekYsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUscUJBQXFCLENBQUMsQ0FBQztJQUNuRSxDQUFDO0lBRUQ7O09BRUc7SUFDSCxhQUFhLENBQUMsY0FBd0I7UUFDcEMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDN0MsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzICovXG4vKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55ICovXG5pbXBvcnQgeyBDb21wb25lbnRGaXh0dXJlLCBUZXN0QmVkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS90ZXN0aW5nJztcbmltcG9ydCB7IERlYnVnRWxlbWVudCwgUHJvdmlkZXJUb2tlbiwgVHlwZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgVGVzdFRleHRBcmVhIH0gZnJvbSAnLi90ZXN0LXRleHRhcmVhJztcbmltcG9ydCB7IFRlc3RFbGVtZW50IH0gZnJvbSAnLi90ZXN0LWVsZW1lbnQnO1xuaW1wb3J0IHsgVGVzdElucHV0IH0gZnJvbSAnLi90ZXN0LWlucHV0JztcbmltcG9ydCB7IFRlc3RTZWxlY3QgfSBmcm9tICcuL3Rlc3Qtc2VsZWN0JztcbmltcG9ydCB7IFRlc3RCdXR0b24gfSBmcm9tICcuL3Rlc3QtYnV0dG9uJztcbmltcG9ydCB7IFRlc3RFbGVtZW50UXVlcmllciB9IGZyb20gJy4vdGVzdC1lbGVtZW50LXF1ZXJpZXInO1xuaW1wb3J0IHsgVGVzdEh0bWxFbGVtZW50IH0gZnJvbSAnLi90ZXN0LWh0bWwtZWxlbWVudCc7XG5cbi8qKlxuICogVGhlIG1haW4gZW50cnkgcG9pbnQgb2YgdGhlIEFQSS4gSXQgd3JhcHMgYW4gQW5ndWxhciBDb21wb25lbnRGaXh0dXJlPFQ+LCBhbmQgZ2l2ZXMgYWNjZXNzIHRvIGl0c1xuICogbW9zdCB1c2VkIHByb3BlcnRpZXMgYW5kIG1ldGhvZHMuIEl0IGFsc28gYWxsb3dzIGdldHRpbmcgZWxlbWVudHMgd3JhcHBlZCBpbiBUZXN0RWxlbWVudCAoYW5kIGl0cyBzdWJjbGFzc2VzKVxuICogQHBhcmFtIDxDPiB0aGUgdHlwZSBvZiB0aGUgY29tcG9uZW50IHRvIHRlc3RcbiAqL1xuZXhwb3J0IGNsYXNzIENvbXBvbmVudFRlc3RlcjxDPiB7XG4gIC8qKlxuICAgKiBUaGUgdGVzdCBlbGVtZW50IG9mIHRoZSBjb21wb25lbnRcbiAgICovXG4gIHJlYWRvbmx5IHRlc3RFbGVtZW50OiBUZXN0RWxlbWVudDxIVE1MRWxlbWVudD47XG5cbiAgLyoqXG4gICAqIFRoZSBjb21wb25lbnQgZml4dHVyZSBvZiB0aGUgY29tcG9uZW50XG4gICAqL1xuICByZWFkb25seSBmaXh0dXJlOiBDb21wb25lbnRGaXh0dXJlPEM+O1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgY29tcG9uZW50IGZpeHR1cmUgb2YgdGhlIGdpdmVuIHR5cGUgd2l0aCB0aGUgVGVzdEJlZCBhbmQgd3JhcHMgaXQgaW50byBhIENvbXBvbmVudFRlc3RlclxuICAgKi9cbiAgc3RhdGljIGNyZWF0ZTxDPihjb21wb25lbnRUeXBlOiBUeXBlPEM+KTogQ29tcG9uZW50VGVzdGVyPEM+IHtcbiAgICBjb25zdCBmaXh0dXJlID0gVGVzdEJlZC5jcmVhdGVDb21wb25lbnQoY29tcG9uZW50VHlwZSk7XG4gICAgcmV0dXJuIG5ldyBDb21wb25lbnRUZXN0ZXIoZml4dHVyZSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIENvbXBvbmVudEZpeHR1cmUgZm9yIHRoZSBnaXZlbiBjb21wb25lbnQgdHlwZSB1c2luZyB0aGUgVGVzdEJlZCwgYW5kIGNyZWF0ZXMgYSBDb21wb25lbnRUZXN0ZXJcbiAgICogd3JhcHBpbmcgKGFuZCBkZWxlZ2F0aW5nKSB0byB0aGlzIGZpeHR1cmUuIElmIGEgZml4dHVyZSBpcyBwYXNzZWQsIHRoZW4gZGVsZWdhdGVzIHRvIHRoaXMgZml4dHVyZSBkaXJlY3RseS5cbiAgICpcbiAgICogTm90ZSB0aGF0IG5vIGBkZXRlY3RDaGFuZ2VzKClgIGNhbGwgaXMgbWFkZSBieSB0aGlzIGNvbnN0cnVjdG9yLiBJdCdzIHVwIHRvIHRoZSBzdWJjbGFzcyBjb25zdHJ1Y3RvcixcbiAgICogb3IgdG8gdGhlIHVzZXIgb2YgdGhlIGNyZWF0ZWQgQ29tcG9uZW50VGVzdGVyLCB0byBjYWxsIGBkZXRlY3RDaGFuZ2VzKClgIGF0IGxlYXN0IG9uY2UgdG8gdHJpZ2dlciBjaGFuZ2VcbiAgICogZGV0ZWN0aW9uLiBUaGlzIGlzIG5lY2Vzc2FyeSBiZWNhdXNlIHNvbWUgY29tcG9uZW50IHRlbXBsYXRlcyBjYW4gb25seSBiZSBldmFsdWF0ZWQgb25jZSBpbnB1dHNcbiAgICogaGF2ZSBiZWVuIHNldCBvbiB0aGUgY29tcG9uZW50IGluc3RhbmNlLlxuICAgKlxuICAgKiBAcGFyYW0gYXJnIHRoZSB0eXBlIG9mIHRoZSBjb21wb25lbnQgdG8gd3JhcCwgb3IgYSBjb21wb25lbnQgZml4dHVyZSB0byB3cmFwXG4gICAqL1xuICBjb25zdHJ1Y3Rvcihhcmc6IFR5cGU8Qz4gfCBDb21wb25lbnRGaXh0dXJlPEM+KSB7XG4gICAgdGhpcy5maXh0dXJlID0gYXJnIGluc3RhbmNlb2YgQ29tcG9uZW50Rml4dHVyZSA/IGFyZyA6IFRlc3RCZWQuY3JlYXRlQ29tcG9uZW50KGFyZyk7XG4gICAgdGhpcy50ZXN0RWxlbWVudCA9IFRlc3RFbGVtZW50UXVlcmllci53cmFwKHRoaXMuZGVidWdFbGVtZW50LCB0aGlzKSBhcyBUZXN0RWxlbWVudDxIVE1MRWxlbWVudD47XG4gIH1cblxuICAvKipcbiAgICogVGhlIG5hdGl2ZSBET00gaG9zdCBlbGVtZW50IG9mIHRoZSBjb21wb25lbnRcbiAgICovXG4gIGdldCBuYXRpdmVFbGVtZW50KCk6IEhUTUxFbGVtZW50IHtcbiAgICByZXR1cm4gdGhpcy5maXh0dXJlLm5hdGl2ZUVsZW1lbnQ7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgaW5zdGFuY2Ugb2YgdGhlIHRlc3RlZCBjb21wb25lbnQgZnJvbSB0aGUgd3JhcHBlZCBmaXh0dXJlXG4gICAqL1xuICBnZXQgY29tcG9uZW50SW5zdGFuY2UoKTogQyB7XG4gICAgcmV0dXJuIHRoaXMuZml4dHVyZS5jb21wb25lbnRJbnN0YW5jZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBkZWJ1ZyBlbGVtZW50IGZyb20gdGhlIHdyYXBwZWQgZml4dHVyZVxuICAgKi9cbiAgZ2V0IGRlYnVnRWxlbWVudCgpOiBEZWJ1Z0VsZW1lbnQge1xuICAgIHJldHVybiB0aGlzLmZpeHR1cmUuZGVidWdFbGVtZW50O1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGZpcnN0IGVsZW1lbnQgbWF0Y2hpbmcgdGhlIGdpdmVuIENTUyBzZWxlY3RvciBhbmQgd3JhcHMgaXQgaW50byBhIFRlc3RFbGVtZW50LiBUaGUgYWN0dWFsIHR5cGVcbiAgICogb2YgdGhlIHJldHVybmVkIHZhbHVlIGlzIHRoZSBUZXN0RWxlbWVudCBzdWJjbGFzcyBtYXRjaGluZyB0aGUgdHlwZSBvZiB0aGUgZm91bmQgZWxlbWVudC4gU28sIGlmIHRoZVxuICAgKiBtYXRjaGVkIGVsZW1lbnQgaXMgYW4gaW5wdXQgZm9yIGV4YW1wbGUsIHRoZSBtZXRob2Qgd2lsbCByZXR1cm4gYSBUZXN0SW5wdXQuXG4gICAqIDxwPlVzYWdlOjwvcD5cbiAgICogPGNvZGU+XG4gICAqIGNvbnN0IHRlc3RFbGVtZW50OiBUZXN0SHRtbEVsZW1lbnQmbHQ7SFRNTERpdkVsZW1lbnQ+IHwgbnVsbCA9IHRlc3Rlci5lbGVtZW50KCdkaXYnKTtcbiAgICogPC9jb2RlPlxuICAgKiBAcGFyYW0gc2VsZWN0b3IgYSBDU1Mgc2VsZWN0b3JcbiAgICogQHJldHVybnMgdGhlIHdyYXBwZWQgZWxlbWVudCwgb3IgbnVsbCBpZiBubyBlbGVtZW50IG1hdGNoZXMgdGhlIHNlbGVjdG9yLlxuICAgKi9cbiAgZWxlbWVudDxLIGV4dGVuZHMga2V5b2YgSFRNTEVsZW1lbnRUYWdOYW1lTWFwPihzZWxlY3RvcjogSyk6IFRlc3RIdG1sRWxlbWVudDxIVE1MRWxlbWVudFRhZ05hbWVNYXBbS10+IHwgbnVsbDtcbiAgLyoqXG4gICAqIEdldHMgdGhlIGZpcnN0IGVsZW1lbnQgbWF0Y2hpbmcgdGhlIGdpdmVuIENTUyBzZWxlY3RvciBhbmQgd3JhcHMgaXQgaW50byBhIFRlc3RFbGVtZW50LiBUaGUgYWN0dWFsIHR5cGVcbiAgICogb2YgdGhlIHJldHVybmVkIHZhbHVlIGlzIHRoZSBUZXN0RWxlbWVudCBzdWJjbGFzcyBtYXRjaGluZyB0aGUgdHlwZSBvZiB0aGUgZm91bmQgZWxlbWVudC4gU28sIGlmIHRoZVxuICAgKiBtYXRjaGVkIGVsZW1lbnQgaXMgYW4gaW5wdXQgZm9yIGV4YW1wbGUsIHRoZSBtZXRob2Qgd2lsbCByZXR1cm4gYSBUZXN0SW5wdXQuXG4gICAqIDxwPlVzYWdlOjwvcD5cbiAgICogPGNvZGU+XG4gICAqIGNvbnN0IHRlc3RFbGVtZW50OiBUZXN0RWxlbWVudCZsdDtTVkdMaW5lRWxlbWVudD4gfCBudWxsID0gdGVzdGVyLmVsZW1lbnQoJ2xpbmUnKTtcbiAgICogPC9jb2RlPlxuICAgKiBAcGFyYW0gc2VsZWN0b3IgYSBDU1Mgc2VsZWN0b3JcbiAgICogQHJldHVybnMgdGhlIHdyYXBwZWQgZWxlbWVudCwgb3IgbnVsbCBpZiBubyBlbGVtZW50IG1hdGNoZXMgdGhlIHNlbGVjdG9yLlxuICAgKi9cbiAgZWxlbWVudDxLIGV4dGVuZHMga2V5b2YgU1ZHRWxlbWVudFRhZ05hbWVNYXA+KHNlbGVjdG9yOiBLKTogVGVzdEVsZW1lbnQ8U1ZHRWxlbWVudFRhZ05hbWVNYXBbS10+IHwgbnVsbDtcbiAgLyoqXG4gICAqIEdldHMgdGhlIGZpcnN0IGVsZW1lbnQgbWF0Y2hpbmcgdGhlIGdpdmVuIENTUyBzZWxlY3RvciBhbmQgd3JhcHMgaXQgaW50byBhIFRlc3RFbGVtZW50LiBUaGUgYWN0dWFsIHR5cGVcbiAgICogb2YgdGhlIHJldHVybmVkIHZhbHVlIGlzIHRoZSBUZXN0RWxlbWVudCBzdWJjbGFzcyBtYXRjaGluZyB0aGUgdHlwZSBvZiB0aGUgZm91bmQgZWxlbWVudC4gU28sIGlmIHRoZVxuICAgKiBtYXRjaGVkIGVsZW1lbnQgaXMgYW4gaW5wdXQgZm9yIGV4YW1wbGUsIHRoZSBtZXRob2Qgd2lsbCByZXR1cm4gYSBUZXN0SW5wdXQuXG4gICAqIDxwPlVzYWdlOjwvcD5cbiAgICogPGNvZGU+XG4gICAqIGNvbnN0IHRlc3RFbGVtZW50OiBUZXN0RWxlbWVudCB8IG51bGwgPSB0ZXN0ZXIuZWxlbWVudCgnLnNlbGVjdG9yJyk7XG4gICAqIDwvY29kZT5cbiAgICogQHBhcmFtIHNlbGVjdG9yIGEgQ1NTIG9yIGRpcmVjdGl2ZSBzZWxlY3RvclxuICAgKiBAcmV0dXJucyB0aGUgd3JhcHBlZCBlbGVtZW50LCBvciBudWxsIGlmIG5vIGVsZW1lbnQgbWF0Y2hlcyB0aGUgc2VsZWN0b3IuXG4gICAqL1xuICBlbGVtZW50KHNlbGVjdG9yOiBzdHJpbmcgfCBUeXBlPGFueT4pOiBUZXN0RWxlbWVudCB8IG51bGw7XG4gIC8qKlxuICAgKiBHZXRzIHRoZSBmaXJzdCBlbGVtZW50IG1hdGNoaW5nIHRoZSBnaXZlbiBzZWxlY3RvciBhbmQgd3JhcHMgaXQgaW50byBhIFRlc3RFbGVtZW50LiBUaGUgYWN0dWFsIHR5cGVcbiAgICogb2YgdGhlIHJldHVybmVkIHZhbHVlIGlzIHRoZSBUZXN0RWxlbWVudCBzdWJjbGFzcyBtYXRjaGluZyB0aGUgdHlwZSBvZiB0aGUgZm91bmQgZWxlbWVudC4gU28sIGlmIHRoZVxuICAgKiBtYXRjaGVkIGVsZW1lbnQgaXMgYW4gaW5wdXQgZm9yIGV4YW1wbGUsIHRoZSBtZXRob2Qgd2lsbCByZXR1cm4gYSBUZXN0SW5wdXQuXG4gICAqIDxwPlVzYWdlOjwvcD5cbiAgICogPGNvZGU+XG4gICAqIGNvbnN0IHRlc3RFbGVtZW50OiBUZXN0SW5wdXQgfCBudWxsID0gdGVzdGVyLmVsZW1lbnQmbHQ7SFRNTElucHV0RWxlbWVudD4oJy5zZWxlY3RvcicpO1xuICAgKiA8L2NvZGU+XG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBvciBkaXJlY3RpdmUgc2VsZWN0b3JcbiAgICogQHJldHVybnMgdGhlIHdyYXBwZWQgZWxlbWVudCwgb3IgbnVsbCBpZiBubyBlbGVtZW50IG1hdGNoZXMgdGhlIHNlbGVjdG9yLlxuICAgKi9cbiAgZWxlbWVudDxUIGV4dGVuZHMgSFRNTElucHV0RWxlbWVudD4oc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IFRlc3RJbnB1dCB8IG51bGw7XG4gIC8qKlxuICAgKiBHZXRzIHRoZSBmaXJzdCBlbGVtZW50IG1hdGNoaW5nIHRoZSBnaXZlbiBzZWxlY3RvciBhbmQgd3JhcHMgaXQgaW50byBhIFRlc3RFbGVtZW50LiBUaGUgYWN0dWFsIHR5cGVcbiAgICogb2YgdGhlIHJldHVybmVkIHZhbHVlIGlzIHRoZSBUZXN0RWxlbWVudCBzdWJjbGFzcyBtYXRjaGluZyB0aGUgdHlwZSBvZiB0aGUgZm91bmQgZWxlbWVudC4gU28sIGlmIHRoZVxuICAgKiBtYXRjaGVkIGVsZW1lbnQgaXMgYW4gaW5wdXQgZm9yIGV4YW1wbGUsIHRoZSBtZXRob2Qgd2lsbCByZXR1cm4gYSBUZXN0SW5wdXQuXG4gICAqIDxwPlVzYWdlOjwvcD5cbiAgICogPGNvZGU+XG4gICAqIGNvbnN0IHRlc3RFbGVtZW50OiBUZXN0VGV4dEFyZWEgfCBudWxsID0gdGVzdGVyLmVsZW1lbnQmbHQ7SFRNTFRleHRBcmVhRWxlbWVudD4oJy5zZWxlY3RvcicpO1xuICAgKiA8L2NvZGU+XG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBvciBkaXJlY3RpdmUgc2VsZWN0b3JcbiAgICogQHJldHVybnMgdGhlIHdyYXBwZWQgZWxlbWVudCwgb3IgbnVsbCBpZiBubyBlbGVtZW50IG1hdGNoZXMgdGhlIHNlbGVjdG9yLlxuICAgKi9cbiAgZWxlbWVudDxUIGV4dGVuZHMgSFRNTFRleHRBcmVhRWxlbWVudD4oc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IFRlc3RUZXh0QXJlYSB8IG51bGw7XG4gIC8qKlxuICAgKiBHZXRzIHRoZSBmaXJzdCBlbGVtZW50IG1hdGNoaW5nIHRoZSBnaXZlbiBzZWxlY3RvciBhbmQgd3JhcHMgaXQgaW50byBhIFRlc3RFbGVtZW50LiBUaGUgYWN0dWFsIHR5cGVcbiAgICogb2YgdGhlIHJldHVybmVkIHZhbHVlIGlzIHRoZSBUZXN0RWxlbWVudCBzdWJjbGFzcyBtYXRjaGluZyB0aGUgdHlwZSBvZiB0aGUgZm91bmQgZWxlbWVudC4gU28sIGlmIHRoZVxuICAgKiBtYXRjaGVkIGVsZW1lbnQgaXMgYW4gaW5wdXQgZm9yIGV4YW1wbGUsIHRoZSBtZXRob2Qgd2lsbCByZXR1cm4gYSBUZXN0SW5wdXQuXG4gICAqIDxwPlVzYWdlOjwvcD5cbiAgICogPGNvZGU+XG4gICAqIGNvbnN0IHRlc3RFbGVtZW50OiBUZXN0U2VsZWN0IHwgbnVsbCA9IHRlc3Rlci5lbGVtZW50Jmx0O0hUTUxTZWxlY3RFbGVtZW50PignLnNlbGVjdG9yJyk7XG4gICAqIDwvY29kZT5cbiAgICogQHBhcmFtIHNlbGVjdG9yIGEgQ1NTIG9yIGRpcmVjdGl2ZSBzZWxlY3RvclxuICAgKiBAcmV0dXJucyB0aGUgd3JhcHBlZCBlbGVtZW50LCBvciBudWxsIGlmIG5vIGVsZW1lbnQgbWF0Y2hlcyB0aGUgc2VsZWN0b3IuXG4gICAqL1xuICBlbGVtZW50PFQgZXh0ZW5kcyBIVE1MU2VsZWN0RWxlbWVudD4oc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IFRlc3RTZWxlY3QgfCBudWxsO1xuICAvKipcbiAgICogR2V0cyB0aGUgZmlyc3QgZWxlbWVudCBtYXRjaGluZyB0aGUgZ2l2ZW4gc2VsZWN0b3IgYW5kIHdyYXBzIGl0IGludG8gYSBUZXN0RWxlbWVudC4gVGhlIGFjdHVhbCB0eXBlXG4gICAqIG9mIHRoZSByZXR1cm5lZCB2YWx1ZSBpcyB0aGUgVGVzdEVsZW1lbnQgc3ViY2xhc3MgbWF0Y2hpbmcgdGhlIHR5cGUgb2YgdGhlIGZvdW5kIGVsZW1lbnQuIFNvLCBpZiB0aGVcbiAgICogbWF0Y2hlZCBlbGVtZW50IGlzIGFuIGlucHV0IGZvciBleGFtcGxlLCB0aGUgbWV0aG9kIHdpbGwgcmV0dXJuIGEgVGVzdElucHV0LlxuICAgKiA8cD5Vc2FnZTo8L3A+XG4gICAqIDxjb2RlPlxuICAgKiBjb25zdCB0ZXN0RWxlbWVudDogVGVzdEJ1dHRvbiB8IG51bGwgPSB0ZXN0ZXIuZWxlbWVudCZsdDtIVE1MQnV0dG9uRWxlbWVudD4oJy5zZWxlY3RvcicpO1xuICAgKiA8L2NvZGU+XG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBvciBkaXJlY3RpdmUgc2VsZWN0b3JcbiAgICogQHJldHVybnMgdGhlIHdyYXBwZWQgZWxlbWVudCwgb3IgbnVsbCBpZiBubyBlbGVtZW50IG1hdGNoZXMgdGhlIHNlbGVjdG9yLlxuICAgKi9cbiAgZWxlbWVudDxUIGV4dGVuZHMgSFRNTEJ1dHRvbkVsZW1lbnQ+KHNlbGVjdG9yOiBzdHJpbmcgfCBUeXBlPGFueT4pOiBUZXN0QnV0dG9uIHwgbnVsbDtcbiAgLyoqXG4gICAqIEdldHMgdGhlIGZpcnN0IGVsZW1lbnQgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yIGFuZCB3cmFwcyBpdCBpbnRvIGEgVGVzdEVsZW1lbnQuIFRoZSBhY3R1YWwgdHlwZVxuICAgKiBvZiB0aGUgcmV0dXJuZWQgdmFsdWUgaXMgdGhlIFRlc3RFbGVtZW50IHN1YmNsYXNzIG1hdGNoaW5nIHRoZSB0eXBlIG9mIHRoZSBmb3VuZCBlbGVtZW50LiBTbywgaWYgdGhlXG4gICAqIG1hdGNoZWQgZWxlbWVudCBpcyBhbiBpbnB1dCBmb3IgZXhhbXBsZSwgdGhlIG1ldGhvZCB3aWxsIHJldHVybiBhIFRlc3RJbnB1dC5cbiAgICogPHA+VXNhZ2U6PC9wPlxuICAgKiA8Y29kZT5cbiAgICogY29uc3QgdGVzdEVsZW1lbnQ6IFRlc3RIdG1sRWxlbWVudCZsdDtIVE1MRGl2RWxlbWVudD4gfCBudWxsID0gdGVzdGVyLmVsZW1lbnQmbHQ7SFRNTERpdkVsZW1lbnQ+KCcuc2VsZWN0b3InKTtcbiAgICogPC9jb2RlPlxuICAgKiBAcGFyYW0gc2VsZWN0b3IgYSBDU1Mgb3IgZGlyZWN0aXZlIHNlbGVjdG9yXG4gICAqIEByZXR1cm5zIHRoZSB3cmFwcGVkIGVsZW1lbnQsIG9yIG51bGwgaWYgbm8gZWxlbWVudCBtYXRjaGVzIHRoZSBzZWxlY3Rvci5cbiAgICovXG4gIGVsZW1lbnQ8VCBleHRlbmRzIEhUTUxFbGVtZW50PihzZWxlY3Rvcjogc3RyaW5nIHwgVHlwZTxhbnk+KTogVGVzdEh0bWxFbGVtZW50PFQ+IHwgbnVsbDtcbiAgLyoqXG4gICAqIEdldHMgdGhlIGZpcnN0IGVsZW1lbnQgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yIGFuZCB3cmFwcyBpdCBpbnRvIGEgVGVzdEVsZW1lbnQuIFRoZSBhY3R1YWwgdHlwZVxuICAgKiBvZiB0aGUgcmV0dXJuZWQgdmFsdWUgaXMgdGhlIFRlc3RFbGVtZW50IHN1YmNsYXNzIG1hdGNoaW5nIHRoZSB0eXBlIG9mIHRoZSBmb3VuZCBlbGVtZW50LiBTbywgaWYgdGhlXG4gICAqIG1hdGNoZWQgZWxlbWVudCBpcyBhbiBpbnB1dCBmb3IgZXhhbXBsZSwgdGhlIG1ldGhvZCB3aWxsIHJldHVybiBhIFRlc3RJbnB1dC5cbiAgICogPHA+VXNhZ2U6PC9wPlxuICAgKiA8Y29kZT5cbiAgICogY29uc3QgdGVzdEVsZW1lbnQ6IFRlc3RFbGVtZW50Jmx0O1NWR0xpbmVFbGVtZW50PiB8IG51bGwgPSB0ZXN0ZXIuZWxlbWVudCZsdDtTVkdMaW5lRWxlbWVudD4oJy5zZWxlY3RvcicpO1xuICAgKiA8L2NvZGU+XG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBvciBkaXJlY3RpdmUgc2VsZWN0b3JcbiAgICogQHJldHVybnMgdGhlIHdyYXBwZWQgZWxlbWVudCwgb3IgbnVsbCBpZiBubyBlbGVtZW50IG1hdGNoZXMgdGhlIHNlbGVjdG9yLlxuICAgKi9cbiAgZWxlbWVudDxUIGV4dGVuZHMgRWxlbWVudD4oc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IFRlc3RFbGVtZW50PFQ+IHwgbnVsbDtcbiAgZWxlbWVudChzZWxlY3Rvcjogc3RyaW5nIHwgVHlwZTxhbnk+KTogVGVzdEVsZW1lbnQgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy50ZXN0RWxlbWVudC5lbGVtZW50KHNlbGVjdG9yKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIGFsbCB0aGUgZWxlbWVudHMgbWF0Y2hpbmcgdGhlIGdpdmVuIENTUyBzZWxlY3RvciBhbmQgd3JhcHMgdGhlbSBpbnRvIGEgVGVzdEVsZW1lbnQuIFRoZSBhY3R1YWwgdHlwZVxuICAgKiBvZiB0aGUgcmV0dXJuZWQgZWxlbWVudHMgaXMgdGhlIFRlc3RFbGVtZW50IHN1YmNsYXNzIG1hdGNoaW5nIHRoZSB0eXBlIG9mIHRoZSBmb3VuZCBlbGVtZW50LiBTbywgaWYgdGhlXG4gICAqIG1hdGNoZWQgZWxlbWVudHMgYXJlIGlucHV0cyBmb3IgZXhhbXBsZSwgdGhlIG1ldGhvZCB3aWxsIHJldHVybiBhbiBhcnJheSBvZiBUZXN0SW5wdXQuXG4gICAqIDxwPlVzYWdlOjwvcD5cbiAgICogPGNvZGU+XG4gICAqIGNvbnN0IHRlc3RFbGVtZW50czogQXJyYXkmbHQ7VGVzdEh0bWxFbGVtZW50Jmx0O0hUTUxEaXZFbGVtZW50Pj4gPSB0ZXN0ZXIuZWxlbWVudHMoJ2RpdicpO1xuICAgKiA8L2NvZGU+XG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBzZWxlY3RvclxuICAgKiBAcmV0dXJucyB0aGUgYXJyYXkgb2YgbWF0Y2hlZCBlbGVtZW50cywgZW1wdHkgaWYgbm8gZWxlbWVudCB3YXMgbWF0Y2hlZFxuICAgKi9cbiAgZWxlbWVudHM8SyBleHRlbmRzIGtleW9mIEhUTUxFbGVtZW50VGFnTmFtZU1hcD4oc2VsZWN0b3I6IEspOiBBcnJheTxUZXN0SHRtbEVsZW1lbnQ8SFRNTEVsZW1lbnRUYWdOYW1lTWFwW0tdPj47XG4gIC8qKlxuICAgKiBHZXRzIGFsbCB0aGUgZWxlbWVudHMgbWF0Y2hpbmcgdGhlIGdpdmVuIENTUyBzZWxlY3RvciBhbmQgd3JhcHMgdGhlbSBpbnRvIGEgVGVzdEVsZW1lbnQuIFRoZSBhY3R1YWwgdHlwZVxuICAgKiBvZiB0aGUgcmV0dXJuZWQgZWxlbWVudHMgaXMgdGhlIFRlc3RFbGVtZW50IHN1YmNsYXNzIG1hdGNoaW5nIHRoZSB0eXBlIG9mIHRoZSBmb3VuZCBlbGVtZW50LiBTbywgaWYgdGhlXG4gICAqIG1hdGNoZWQgZWxlbWVudHMgYXJlIGlucHV0cyBmb3IgZXhhbXBsZSwgdGhlIG1ldGhvZCB3aWxsIHJldHVybiBhbiBhcnJheSBvZiBUZXN0SW5wdXQuXG4gICAqIDxwPlVzYWdlOjwvcD5cbiAgICogPGNvZGU+XG4gICAqIGNvbnN0IHRlc3RFbGVtZW50czogQXJyYXkmbHQ7VGVzdEVsZW1lbnQmbHQ7U1ZHTGluZUVsZW1lbnQ+PiA9IHRlc3Rlci5lbGVtZW50cygnbGluZScpO1xuICAgKiA8L2NvZGU+XG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBzZWxlY3RvclxuICAgKiBAcmV0dXJucyB0aGUgYXJyYXkgb2YgbWF0Y2hlZCBlbGVtZW50cywgZW1wdHkgaWYgbm8gZWxlbWVudCB3YXMgbWF0Y2hlZFxuICAgKi9cbiAgZWxlbWVudHM8SyBleHRlbmRzIGtleW9mIFNWR0VsZW1lbnRUYWdOYW1lTWFwPihzZWxlY3RvcjogSyk6IEFycmF5PFRlc3RFbGVtZW50PFNWR0VsZW1lbnRUYWdOYW1lTWFwW0tdPj47XG4gIC8qKlxuICAgKiBHZXRzIGFsbCB0aGUgZWxlbWVudHMgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yIGFuZCB3cmFwcyB0aGVtIGludG8gYSBUZXN0RWxlbWVudC4gVGhlIGFjdHVhbCB0eXBlXG4gICAqIG9mIHRoZSByZXR1cm5lZCBlbGVtZW50cyBpcyB0aGUgVGVzdEVsZW1lbnQgc3ViY2xhc3MgbWF0Y2hpbmcgdGhlIHR5cGUgb2YgdGhlIGZvdW5kIGVsZW1lbnQuIFNvLCBpZiB0aGVcbiAgICogbWF0Y2hlZCBlbGVtZW50cyBhcmUgaW5wdXRzIGZvciBleGFtcGxlLCB0aGUgbWV0aG9kIHdpbGwgcmV0dXJuIGFuIGFycmF5IG9mIFRlc3RJbnB1dC5cbiAgICogPHA+VXNhZ2U6PC9wPlxuICAgKiA8Y29kZT5cbiAgICogY29uc3QgdGVzdEVsZW1lbnRzOiBBcnJheSZsdDtUZXN0RWxlbWVudD4gPSB0ZXN0ZXIuZWxlbWVudHMoJy5zZWxlY3RvcicpO1xuICAgKiA8L2NvZGU+XG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBvciBkaXJlY3RpdmUgc2VsZWN0b3JcbiAgICogQHJldHVybnMgdGhlIGFycmF5IG9mIG1hdGNoZWQgZWxlbWVudHMsIGVtcHR5IGlmIG5vIGVsZW1lbnQgd2FzIG1hdGNoZWRcbiAgICovXG4gIGVsZW1lbnRzKHNlbGVjdG9yOiBzdHJpbmcgfCBUeXBlPGFueT4pOiBBcnJheTxUZXN0RWxlbWVudD47XG4gIC8qKlxuICAgKiBHZXRzIGFsbCB0aGUgZWxlbWVudHMgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yIGFuZCB3cmFwcyB0aGVtIGludG8gYSBUZXN0RWxlbWVudC4gVGhlIGFjdHVhbCB0eXBlXG4gICAqIG9mIHRoZSByZXR1cm5lZCBlbGVtZW50cyBpcyB0aGUgVGVzdEVsZW1lbnQgc3ViY2xhc3MgbWF0Y2hpbmcgdGhlIHR5cGUgb2YgdGhlIGZvdW5kIGVsZW1lbnQuIFNvLCBpZiB0aGVcbiAgICogbWF0Y2hlZCBlbGVtZW50cyBhcmUgaW5wdXRzIGZvciBleGFtcGxlLCB0aGUgbWV0aG9kIHdpbGwgcmV0dXJuIGFuIGFycmF5IG9mIFRlc3RJbnB1dC5cbiAgICogPHA+VXNhZ2U6PC9wPlxuICAgKiA8Y29kZT5cbiAgICogY29uc3QgdGVzdEVsZW1lbnRzOiBBcnJheSZsdDtUZXN0SW5wdXQ+ID0gdGVzdGVyLmVsZW1lbnRzJmx0O0hUTUxJbnB1dEVsZW1lbnQ+KCcuc2VsZWN0b3InKTtcbiAgICogPC9jb2RlPlxuICAgKiBAcGFyYW0gc2VsZWN0b3IgYSBDU1Mgb3IgZGlyZWN0aXZlIHNlbGVjdG9yXG4gICAqIEByZXR1cm5zIHRoZSBhcnJheSBvZiBtYXRjaGVkIGVsZW1lbnRzLCBlbXB0eSBpZiBubyBlbGVtZW50IHdhcyBtYXRjaGVkXG4gICAqL1xuICBlbGVtZW50czxUIGV4dGVuZHMgSFRNTElucHV0RWxlbWVudD4oc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IEFycmF5PFRlc3RJbnB1dD47XG4gIC8qKlxuICAgKiBHZXRzIGFsbCB0aGUgZWxlbWVudHMgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yIGFuZCB3cmFwcyB0aGVtIGludG8gYSBUZXN0RWxlbWVudC4gVGhlIGFjdHVhbCB0eXBlXG4gICAqIG9mIHRoZSByZXR1cm5lZCBlbGVtZW50cyBpcyB0aGUgVGVzdEVsZW1lbnQgc3ViY2xhc3MgbWF0Y2hpbmcgdGhlIHR5cGUgb2YgdGhlIGZvdW5kIGVsZW1lbnQuIFNvLCBpZiB0aGVcbiAgICogbWF0Y2hlZCBlbGVtZW50cyBhcmUgaW5wdXRzIGZvciBleGFtcGxlLCB0aGUgbWV0aG9kIHdpbGwgcmV0dXJuIGFuIGFycmF5IG9mIFRlc3RJbnB1dC5cbiAgICogPHA+VXNhZ2U6PC9wPlxuICAgKiA8Y29kZT5cbiAgICogY29uc3QgdGVzdEVsZW1lbnRzOiBBcnJheSZsdDtUZXN0VGV4dEFyZWE+ID0gdGVzdGVyLmVsZW1lbnRzJmx0O0hUTUxUZXh0QXJlYUVsZW1lbnQ+KCcuc2VsZWN0b3InKTtcbiAgICogPC9jb2RlPlxuICAgKiBAcGFyYW0gc2VsZWN0b3IgYSBDU1Mgb3IgZGlyZWN0aXZlIHNlbGVjdG9yXG4gICAqIEByZXR1cm5zIHRoZSBhcnJheSBvZiBtYXRjaGVkIGVsZW1lbnRzLCBlbXB0eSBpZiBubyBlbGVtZW50IHdhcyBtYXRjaGVkXG4gICAqL1xuICBlbGVtZW50czxUIGV4dGVuZHMgSFRNTFRleHRBcmVhRWxlbWVudD4oc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IEFycmF5PFRlc3RUZXh0QXJlYT47XG4gIC8qKlxuICAgKiBHZXRzIGFsbCB0aGUgZWxlbWVudHMgbWF0Y2hpbmcgdGhlIGdpdmVuIENTUyBzZWxlY3RvciBhbmQgd3JhcHMgdGhlbSBpbnRvIGEgVGVzdEVsZW1lbnQuIFRoZSBhY3R1YWwgdHlwZVxuICAgKiBvZiB0aGUgcmV0dXJuZWQgZWxlbWVudHMgaXMgdGhlIFRlc3RFbGVtZW50IHN1YmNsYXNzIG1hdGNoaW5nIHRoZSB0eXBlIG9mIHRoZSBmb3VuZCBlbGVtZW50LiBTbywgaWYgdGhlXG4gICAqIG1hdGNoZWQgZWxlbWVudHMgYXJlIGlucHV0cyBmb3IgZXhhbXBsZSwgdGhlIG1ldGhvZCB3aWxsIHJldHVybiBhbiBhcnJheSBvZiBUZXN0SW5wdXQuXG4gICAqIDxwPlVzYWdlOjwvcD5cbiAgICogPGNvZGU+XG4gICAqIGNvbnN0IHRlc3RFbGVtZW50czogQXJyYXkmbHQ7VGVzdEJ1dHRvbj4gPSB0ZXN0ZXIuZWxlbWVudHMmbHQ7SFRNTEJ1dHRvbkVsZW1lbnQ+KCcuc2VsZWN0b3InKTtcbiAgICogPC9jb2RlPlxuICAgKiBAcGFyYW0gc2VsZWN0b3IgYSBDU1Mgb3IgZGlyZWN0aXZlIHNlbGVjdG9yXG4gICAqIEByZXR1cm5zIHRoZSBhcnJheSBvZiBtYXRjaGVkIGVsZW1lbnRzLCBlbXB0eSBpZiBubyBlbGVtZW50IHdhcyBtYXRjaGVkXG4gICAqL1xuICBlbGVtZW50czxUIGV4dGVuZHMgSFRNTEJ1dHRvbkVsZW1lbnQ+KHNlbGVjdG9yOiBzdHJpbmcgfCBUeXBlPGFueT4pOiBBcnJheTxUZXN0QnV0dG9uPjtcbiAgLyoqXG4gICAqIEdldHMgYWxsIHRoZSBlbGVtZW50cyBtYXRjaGluZyB0aGUgZ2l2ZW4gc2VsZWN0b3IgYW5kIHdyYXBzIHRoZW0gaW50byBhIFRlc3RFbGVtZW50LiBUaGUgYWN0dWFsIHR5cGVcbiAgICogb2YgdGhlIHJldHVybmVkIGVsZW1lbnRzIGlzIHRoZSBUZXN0RWxlbWVudCBzdWJjbGFzcyBtYXRjaGluZyB0aGUgdHlwZSBvZiB0aGUgZm91bmQgZWxlbWVudC4gU28sIGlmIHRoZVxuICAgKiBtYXRjaGVkIGVsZW1lbnRzIGFyZSBpbnB1dHMgZm9yIGV4YW1wbGUsIHRoZSBtZXRob2Qgd2lsbCByZXR1cm4gYW4gYXJyYXkgb2YgVGVzdElucHV0LlxuICAgKiA8cD5Vc2FnZTo8L3A+XG4gICAqIDxjb2RlPlxuICAgKiBjb25zdCB0ZXN0RWxlbWVudHM6IEFycmF5Jmx0O1Rlc3RTZWxlY3Q+ID0gdGVzdGVyLmVsZW1lbnRzPEhUTUxTZWxlY3RFbGVtZW50PignLnNlbGVjdG9yJyk7XG4gICAqIDwvY29kZT5cbiAgICogQHBhcmFtIHNlbGVjdG9yIGEgQ1NTIG9yIGRpcmVjdGl2ZSBzZWxlY3RvclxuICAgKiBAcmV0dXJucyB0aGUgYXJyYXkgb2YgbWF0Y2hlZCBlbGVtZW50cywgZW1wdHkgaWYgbm8gZWxlbWVudCB3YXMgbWF0Y2hlZFxuICAgKi9cbiAgZWxlbWVudHM8VCBleHRlbmRzIEhUTUxTZWxlY3RFbGVtZW50PihzZWxlY3Rvcjogc3RyaW5nIHwgVHlwZTxhbnk+KTogQXJyYXk8VGVzdFNlbGVjdD47XG4gIC8qKlxuICAgKiBHZXRzIGFsbCB0aGUgZWxlbWVudHMgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yIGFuZCB3cmFwcyB0aGVtIGludG8gYSBUZXN0RWxlbWVudC4gVGhlIGFjdHVhbCB0eXBlXG4gICAqIG9mIHRoZSByZXR1cm5lZCBlbGVtZW50cyBpcyB0aGUgVGVzdEVsZW1lbnQgc3ViY2xhc3MgbWF0Y2hpbmcgdGhlIHR5cGUgb2YgdGhlIGZvdW5kIGVsZW1lbnQuIFNvLCBpZiB0aGVcbiAgICogbWF0Y2hlZCBlbGVtZW50cyBhcmUgaW5wdXRzIGZvciBleGFtcGxlLCB0aGUgbWV0aG9kIHdpbGwgcmV0dXJuIGFuIGFycmF5IG9mIFRlc3RJbnB1dC5cbiAgICogPHA+VXNhZ2U6PC9wPlxuICAgKiA8Y29kZT5cbiAgICogY29uc3QgdGVzdEVsZW1lbnRzOiBBcnJheSZsdDtUZXN0SHRtbEVsZW1lbnQmbHQ7SFRNTERpdkVsZW1lbnQ+PiA9IHRlc3Rlci5lbGVtZW50cyZsdDtIVE1MRGl2RWxlbWVudD4oJy5zZWxlY3RvcicpO1xuICAgKiA8L2NvZGU+XG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBvciBkaXJlY3RpdmUgc2VsZWN0b3JcbiAgICogQHJldHVybnMgdGhlIGFycmF5IG9mIG1hdGNoZWQgZWxlbWVudHMsIGVtcHR5IGlmIG5vIGVsZW1lbnQgd2FzIG1hdGNoZWRcbiAgICovXG4gIGVsZW1lbnRzPFQgZXh0ZW5kcyBIVE1MRWxlbWVudD4oc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IEFycmF5PFRlc3RIdG1sRWxlbWVudDxUPj47XG4gIC8qKlxuICAgKiBHZXRzIGFsbCB0aGUgZWxlbWVudHMgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yIGFuZCB3cmFwcyB0aGVtIGludG8gYSBUZXN0RWxlbWVudC4gVGhlIGFjdHVhbCB0eXBlXG4gICAqIG9mIHRoZSByZXR1cm5lZCBlbGVtZW50cyBpcyB0aGUgVGVzdEVsZW1lbnQgc3ViY2xhc3MgbWF0Y2hpbmcgdGhlIHR5cGUgb2YgdGhlIGZvdW5kIGVsZW1lbnQuIFNvLCBpZiB0aGVcbiAgICogbWF0Y2hlZCBlbGVtZW50cyBhcmUgaW5wdXRzIGZvciBleGFtcGxlLCB0aGUgbWV0aG9kIHdpbGwgcmV0dXJuIGFuIGFycmF5IG9mIFRlc3RJbnB1dC5cbiAgICogPHA+VXNhZ2U6PC9wPlxuICAgKiA8Y29kZT5cbiAgICogY29uc3QgdGVzdEVsZW1lbnRzOiBBcnJheSZsdDtUZXN0RWxlbWVudCZsdDtTVkdMaW5lRWxlbWVudD4+ID0gdGVzdGVyLmVsZW1lbnRzJmx0O1NWR0xpbmVFbGVtZW50PignLnNlbGVjdG9yJyk7XG4gICAqIDwvY29kZT5cbiAgICogQHBhcmFtIHNlbGVjdG9yIGEgQ1NTIG9yIGRpcmVjdGl2ZSBzZWxlY3RvclxuICAgKiBAcmV0dXJucyB0aGUgYXJyYXkgb2YgbWF0Y2hlZCBlbGVtZW50cywgZW1wdHkgaWYgbm8gZWxlbWVudCB3YXMgbWF0Y2hlZFxuICAgKi9cbiAgZWxlbWVudHM8VCBleHRlbmRzIEVsZW1lbnQ+KHNlbGVjdG9yOiBzdHJpbmcgfCBUeXBlPGFueT4pOiBBcnJheTxUZXN0RWxlbWVudDxUPj47XG4gIGVsZW1lbnRzKHNlbGVjdG9yOiBzdHJpbmcgfCBUeXBlPGFueT4pOiBBcnJheTxUZXN0RWxlbWVudD4ge1xuICAgIHJldHVybiB0aGlzLnRlc3RFbGVtZW50LmVsZW1lbnRzKHNlbGVjdG9yKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBmaXJzdCBpbnB1dCBtYXRjaGVkIGJ5IHRoZSBnaXZlbiBzZWxlY3Rvci4gVGhyb3dzIGFuIEVycm9yIGlmIHRoZSBtYXRjaGVkIGVsZW1lbnQgaXNuJ3QgYWN0dWFsbHkgYW4gaW5wdXQuXG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBvciBkaXJlY3RpdmUgc2VsZWN0b3JcbiAgICogQHJldHVybnMgdGhlIHdyYXBwZWQgaW5wdXQsIG9yIG51bGwgaWYgbm8gZWxlbWVudCB3YXMgbWF0Y2hlZFxuICAgKi9cbiAgaW5wdXQoc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IFRlc3RJbnB1dCB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLnRlc3RFbGVtZW50LmlucHV0KHNlbGVjdG9yKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBmaXJzdCBzZWxlY3QgbWF0Y2hlZCBieSB0aGUgZ2l2ZW4gc2VsZWN0b3IuIFRocm93cyBhbiBFcnJvciBpZiB0aGUgbWF0Y2hlZCBlbGVtZW50IGlzbid0IGFjdHVhbGx5IGEgc2VsZWN0LlxuICAgKiBAcGFyYW0gc2VsZWN0b3IgYSBDU1Mgb3IgZGlyZWN0aXZlIHNlbGVjdG9yXG4gICAqIEByZXR1cm5zIHRoZSB3cmFwcGVkIHNlbGVjdCwgb3IgbnVsbCBpZiBubyBlbGVtZW50IHdhcyBtYXRjaGVkXG4gICAqL1xuICBzZWxlY3Qoc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IFRlc3RTZWxlY3QgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy50ZXN0RWxlbWVudC5zZWxlY3Qoc2VsZWN0b3IpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGZpcnN0IHRleHRhcmVhIG1hdGNoZWQgYnkgdGhlIGdpdmVuIHNlbGVjdG9yXG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBvciBkaXJlY3RpdmUgc2VsZWN0b3JcbiAgICogQHJldHVybnMgdGhlIHdyYXBwZWQgdGV4dGFyZWEsIG9yIG51bGwgaWYgbm8gZWxlbWVudCB3YXMgbWF0Y2hlZC4gVGhyb3dzIGFuIEVycm9yIGlmIHRoZSBtYXRjaGVkIGVsZW1lbnQgaXNuJ3QgYWN0dWFsbHkgYSB0ZXh0YXJlYS5cbiAgICogQHRocm93cyB7RXJyb3J9IGlmIHRoZSBtYXRjaGVkIGVsZW1lbnQgaXNuJ3QgYWN0dWFsbHkgYSB0ZXh0YXJlYVxuICAgKi9cbiAgdGV4dGFyZWEoc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IFRlc3RUZXh0QXJlYSB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLnRlc3RFbGVtZW50LnRleHRhcmVhKHNlbGVjdG9yKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBmaXJzdCBidXR0b24gbWF0Y2hlZCBieSB0aGUgZ2l2ZW4gc2VsZWN0b3IuIFRocm93cyBhbiBFcnJvciBpZiB0aGUgbWF0Y2hlZCBlbGVtZW50IGlzbid0IGFjdHVhbGx5IGEgYnV0dG9uLlxuICAgKiBAcGFyYW0gc2VsZWN0b3IgYSBDU1Mgb3IgZGlyZWN0aXZlIHNlbGVjdG9yXG4gICAqIEByZXR1cm5zIHRoZSB3cmFwcGVkIGJ1dHRvbiwgb3IgbnVsbCBpZiBubyBlbGVtZW50IHdhcyBtYXRjaGVkXG4gICAqL1xuICBidXR0b24oc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55Pik6IFRlc3RCdXR0b24gfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy50ZXN0RWxlbWVudC5idXR0b24oc2VsZWN0b3IpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGZpcnN0IGRpcmVjdGl2ZSBtYXRjaGluZyB0aGUgZ2l2ZW4gY29tcG9uZW50IGRpcmVjdGl2ZSBzZWxlY3RvciBhbmQgcmV0dXJucyBpdHMgY29tcG9uZW50IGluc3RhbmNlXG4gICAqIEBwYXJhbSBzZWxlY3RvciB0aGUgc2VsZWN0b3Igb2YgYSBjb21wb25lbnQgZGlyZWN0aXZlXG4gICAqL1xuICBjb21wb25lbnQ8Uj4oc2VsZWN0b3I6IFR5cGU8Uj4pOiBSIHtcbiAgICByZXR1cm4gdGhpcy50ZXN0RWxlbWVudC5jb21wb25lbnQoc2VsZWN0b3IpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGRpcmVjdGl2ZXMgbWF0Y2hpbmcgdGhlIGdpdmVuIGNvbXBvbmVudCBkaXJlY3RpdmUgc2VsZWN0b3IgYW5kIHJldHVybnMgdGhlaXIgY29tcG9uZW50IGluc3RhbmNlXG4gICAqIEBwYXJhbSBzZWxlY3RvciB0aGUgc2VsZWN0b3Igb2YgYSBjb21wb25lbnQgZGlyZWN0aXZlXG4gICAqL1xuICBjb21wb25lbnRzPFI+KHNlbGVjdG9yOiBUeXBlPFI+KTogQXJyYXk8Uj4ge1xuICAgIHJldHVybiB0aGlzLnRlc3RFbGVtZW50LmNvbXBvbmVudHMoc2VsZWN0b3IpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGZpcnN0IGVsZW1lbnQgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yLCB0aGVuIGdldHMgdGhlIGdpdmVuIHRva2VuIGZyb20gaXRzIGluamVjdG9yLCBvciBudWxsIGlmIHRoZXJlIGlzIG5vIHN1Y2ggdG9rZW5cbiAgICogQHBhcmFtIHNlbGVjdG9yIGEgQ1NTIG9yIGRpcmVjdGl2ZSBzZWxlY3RvclxuICAgKiBAcGFyYW0gdG9rZW4gdGhlIHRva2VuIHRvIGdldCBmcm9tIHRoZSBtYXRjaGVkIGVsZW1lbnQgaW5qZWN0b3JcbiAgICovXG4gIHRva2VuPFI+KHNlbGVjdG9yOiBzdHJpbmcgfCBUeXBlPGFueT4sIHRva2VuOiBQcm92aWRlclRva2VuPFI+KTogUiB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLnRlc3RFbGVtZW50LnRva2VuKHNlbGVjdG9yLCB0b2tlbik7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgZWxlbWVudHMgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yLCB0aGVuIGdldHMgdGhlaXIgZ2l2ZW4gdG9rZW4gZnJvbSB0aGVpciBpbmplY3Rvciwgb3IgbnVsbCBpZiB0aGVyZSBpcyBubyBzdWNoIHRva2VuXG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBvciBkaXJlY3RpdmUgc2VsZWN0b3JcbiAgICogQHBhcmFtIHRva2VuIHRoZSB0b2tlbiB0byBnZXQgZnJvbSB0aGUgbWF0Y2hlZCBlbGVtZW50IGluamVjdG9yXG4gICAqL1xuICB0b2tlbnM8Uj4oc2VsZWN0b3I6IHN0cmluZyB8IFR5cGU8YW55PiwgdG9rZW46IFByb3ZpZGVyVG9rZW48Uj4pOiBBcnJheTxSIHwgbnVsbD4ge1xuICAgIHJldHVybiB0aGlzLnRlc3RFbGVtZW50LnRva2VucyhzZWxlY3RvciwgdG9rZW4pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGVsZW1lbnQgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yLCBhbmQgaWYgZm91bmQsIGNyZWF0ZXMgYW5kIHJldHVybnMgYSBjdXN0b20gVGVzdEVsZW1lbnQgb2YgdGhlIHByb3ZpZGVkXG4gICAqIHR5cGUuIFRoaXMgaXMgdXNlZnVsIHRvIGNyZWF0ZSBjdXN0b20gaGlnaGVyLWxldmVsIGFic3RyYWN0aW9ucyBzaW1pbGFyIHRvIFRlc3RJbnB1dCwgVGVzdFNlbGVjdCwgZXRjLiBmb3JcbiAgICogY3VzdG9tIGVsZW1lbnRzIG9yIGNvbXBvbmVudHMuXG4gICAqIEBwYXJhbSBzZWxlY3RvciBhIENTUyBvciBkaXJlY3RpdmUgc2VsZWN0b3JcbiAgICogQHBhcmFtIGN1c3RvbVRlc3RFbGVtZW50VHlwZSB0aGUgdHlwZSBvZiB0aGUgVGVzdEVsZW1lbnQgc3ViY2xhc3MgdGhhdCB3aWxsIHdyYXAgdGhlIGZvdW5kIGVsZW1lbnRcbiAgICovXG4gIGN1c3RvbTxFIGV4dGVuZHMgVGVzdEVsZW1lbnQ+KHNlbGVjdG9yOiBzdHJpbmcgfCBUeXBlPGFueT4sIGN1c3RvbVRlc3RFbGVtZW50VHlwZTogVHlwZTxFPik6IEUgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy50ZXN0RWxlbWVudC5jdXN0b20oc2VsZWN0b3IsIGN1c3RvbVRlc3RFbGVtZW50VHlwZSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgZWxlbWVudHMgbWF0Y2hpbmcgdGhlIGdpdmVuIHNlbGVjdG9yLCBhbmQgY3JlYXRlcyBhbmQgcmV0dXJucyBjdXN0b20gVGVzdEVsZW1lbnRzIG9mIHRoZSBwcm92aWRlZFxuICAgKiB0eXBlLiBUaGlzIGlzIHVzZWZ1bCB0byBjcmVhdGUgY3VzdG9tIGhpZ2hlci1sZXZlbCBhYnN0cmFjdGlvbnMgc2ltaWxhciB0byBUZXN0SW5wdXQsIFRlc3RTZWxlY3QsIGV0Yy4gZm9yXG4gICAqIGN1c3RvbSBlbGVtZW50cyBvciBjb21wb25lbnRzLlxuICAgKiBAcGFyYW0gc2VsZWN0b3IgYSBDU1Mgb3IgZGlyZWN0aXZlIHNlbGVjdG9yXG4gICAqIEBwYXJhbSBjdXN0b21UZXN0RWxlbWVudFR5cGUgdGhlIHR5cGUgb2YgdGhlIFRlc3RFbGVtZW50IHN1YmNsYXNzIHRoYXQgd2lsbCB3cmFwIHRoZSBmb3VuZCBlbGVtZW50c1xuICAgKi9cbiAgY3VzdG9tczxFIGV4dGVuZHMgVGVzdEVsZW1lbnQ+KHNlbGVjdG9yOiBzdHJpbmcgfCBUeXBlPGFueT4sIGN1c3RvbVRlc3RFbGVtZW50VHlwZTogVHlwZTxFPik6IEFycmF5PEU+IHtcbiAgICByZXR1cm4gdGhpcy50ZXN0RWxlbWVudC5jdXN0b21zKHNlbGVjdG9yLCBjdXN0b21UZXN0RWxlbWVudFR5cGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyaWdnZXJzIGEgY2hhbmdlIGRldGVjdGlvbiB1c2luZyB0aGUgd3JhcHBlZCBmaXh0dXJlXG4gICAqL1xuICBkZXRlY3RDaGFuZ2VzKGNoZWNrTm9DaGFuZ2VzPzogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuZml4dHVyZS5kZXRlY3RDaGFuZ2VzKGNoZWNrTm9DaGFuZ2VzKTtcbiAgfVxufVxuIl19
@@ -0,0 +1,283 @@
1
+ import { TestTextArea } from './test-textarea';
2
+ import { TestInput } from './test-input';
3
+ import { TestElement } from './test-element';
4
+ import { TestSelect } from './test-select';
5
+ import { TestHtmlElement } from './test-html-element';
6
+ const speculoosMatchers = {
7
+ /**
8
+ * Checks that the receiver is a TestElement wrapping a DOM element and as the given CSS class
9
+ */
10
+ toHaveClass: () => {
11
+ const assert = (isNegative, el, expected) => {
12
+ if (!el) {
13
+ return { pass: false, message: `Expected to check class '${expected}' on element, but element was falsy` };
14
+ }
15
+ if (!(el instanceof TestElement)) {
16
+ return { pass: false, message: `Expected to check class '${expected}' on element, but element was not a TestElement` };
17
+ }
18
+ const actual = el.classes;
19
+ const pass = actual.indexOf(expected) !== -1;
20
+ const message = `Expected element to ${isNegative ? 'not ' : ''}have class '${expected}', ` +
21
+ `but had ${actual.length ? "'" + actual.join(', ') + "'" : 'none'}`;
22
+ return { pass: isNegative ? !pass : pass, message };
23
+ };
24
+ return {
25
+ compare: (el, expected) => {
26
+ return assert(false, el, expected);
27
+ },
28
+ negativeCompare: (el, expected) => {
29
+ return assert(true, el, expected);
30
+ }
31
+ };
32
+ },
33
+ /**
34
+ * Checks that the receiver is a TestInput or a TestTextArea and has the given value
35
+ */
36
+ toHaveValue: () => {
37
+ const assert = (isNegative, el, expected) => {
38
+ if (!el) {
39
+ return { pass: false, message: `Expected to check value '${expected}' on element, but element was falsy` };
40
+ }
41
+ if (!(el instanceof TestInput) && !(el instanceof TestTextArea)) {
42
+ return {
43
+ pass: false,
44
+ message: `Expected to check value '${expected}' on element, but element was neither a TestInput nor a TestTextArea`
45
+ };
46
+ }
47
+ const actual = el.value;
48
+ const pass = actual === expected;
49
+ const message = `Expected element to ${isNegative ? 'not ' : ''}have value '${expected}', but had value '${actual}'`;
50
+ return { pass: isNegative ? !pass : pass, message };
51
+ };
52
+ return {
53
+ compare: (el, expected) => {
54
+ return assert(false, el, expected);
55
+ },
56
+ negativeCompare: (el, expected) => {
57
+ return assert(true, el, expected);
58
+ }
59
+ };
60
+ },
61
+ /**
62
+ * Checks that the receiver is a TestElement wrapping a DOM element and has the exact given textContent
63
+ */
64
+ toHaveText: () => {
65
+ const assert = (isNegative, el, expected) => {
66
+ if (!el) {
67
+ return { pass: false, message: `Expected to check text '${expected}' on element, but element was falsy` };
68
+ }
69
+ if (!(el instanceof TestElement)) {
70
+ return { pass: false, message: `Expected to check text '${expected}' on element, but element was not a TestElement` };
71
+ }
72
+ const actual = el.textContent;
73
+ const pass = actual === expected;
74
+ const message = `Expected element to ${isNegative ? 'not ' : ''}have text '${expected}', but had '${actual}'`;
75
+ return { pass: isNegative ? !pass : pass, message };
76
+ };
77
+ return {
78
+ compare: (el, expected) => {
79
+ return assert(false, el, expected);
80
+ },
81
+ negativeCompare: (el, expected) => {
82
+ return assert(true, el, expected);
83
+ }
84
+ };
85
+ },
86
+ /**
87
+ * Checks that the receiver is a TestElement wrapping a DOM element and has the given textContent, after both have been trimmed.
88
+ * So, An element such as
89
+ * ```
90
+ * <h1>
91
+ * Some title
92
+ * </h1>
93
+ * ```
94
+ * will pass the test
95
+ * ```
96
+ * expect(tester.title).toHaveTrimmedText('Some title')
97
+ * ```
98
+ */
99
+ toHaveTrimmedText: () => {
100
+ const assert = (isNegative, el, expected) => {
101
+ const trimmedExpected = expected.trim();
102
+ if (!el) {
103
+ return { pass: false, message: `Expected to check trimmed text '${trimmedExpected}' on element, but element was falsy` };
104
+ }
105
+ if (!(el instanceof TestElement)) {
106
+ return {
107
+ pass: false,
108
+ message: `Expected to check trimmed text '${trimmedExpected}' on element, but element was not a TestElement`
109
+ };
110
+ }
111
+ const actual = el.textContent?.trim();
112
+ const pass = actual === trimmedExpected;
113
+ const message = `Expected element to ${isNegative ? 'not ' : ''}have trimmed text '${trimmedExpected}', but had '${actual}'`;
114
+ return { pass: isNegative ? !pass : pass, message };
115
+ };
116
+ return {
117
+ compare: (el, expected) => {
118
+ return assert(false, el, expected);
119
+ },
120
+ negativeCompare: (el, expected) => {
121
+ return assert(true, el, expected);
122
+ }
123
+ };
124
+ },
125
+ /**
126
+ * Checks that the receiver is a TestElement wrapping a DOM element and contains the given textContent
127
+ */
128
+ toContainText: () => {
129
+ const assert = (isNegative, el, expected) => {
130
+ if (!el) {
131
+ return { pass: false, message: `Expected to check text '${expected}' on element, but element was falsy` };
132
+ }
133
+ if (!(el instanceof TestElement)) {
134
+ return { pass: false, message: `Expected to check text '${expected}' on element, but element was not a TestElement` };
135
+ }
136
+ const actual = el.textContent;
137
+ if (!actual) {
138
+ return {
139
+ pass: isNegative,
140
+ message: `Expected element to ${isNegative ? 'not ' : ''}contain text '${expected}', but had no text`
141
+ };
142
+ }
143
+ const pass = actual.indexOf(expected) !== -1;
144
+ const message = `Expected element to ${isNegative ? 'not ' : ''}contain text '${expected}', but had text '${actual}'`;
145
+ return { pass: isNegative ? !pass : pass, message };
146
+ };
147
+ return {
148
+ compare: (el, expected) => {
149
+ return assert(false, el, expected);
150
+ },
151
+ negativeCompare: (el, expected) => {
152
+ return assert(true, el, expected);
153
+ }
154
+ };
155
+ },
156
+ /**
157
+ * Checks that the receiver is a TestElement wrapping a DOM element and contains the given textContent
158
+ */
159
+ toBeChecked: () => {
160
+ const assert = (isNegative, el) => {
161
+ if (!el) {
162
+ return { pass: false, message: `Expected to check if element was checked, but element was falsy` };
163
+ }
164
+ if (!(el instanceof TestInput)) {
165
+ return { pass: false, message: `Expected to check if element was checked, but element was not a TestInput` };
166
+ }
167
+ const pass = el.checked;
168
+ const message = `Expected element to be ${isNegative ? 'not ' : ''}checked, but was${!isNegative ? ' not' : ''}`;
169
+ return { pass: isNegative ? !pass : pass, message };
170
+ };
171
+ return {
172
+ compare: (el) => {
173
+ return assert(false, el);
174
+ },
175
+ negativeCompare: (el) => {
176
+ return assert(true, el);
177
+ }
178
+ };
179
+ },
180
+ /**
181
+ * Checks that the receiver is a TestSelect wrapping a DOM element and has the given selected index
182
+ */
183
+ toHaveSelectedIndex: () => {
184
+ const assert = (isNegative, el, expected) => {
185
+ if (!el) {
186
+ return { pass: false, message: `Expected to check selected index ${expected} on element, but element was falsy` };
187
+ }
188
+ if (!(el instanceof TestSelect)) {
189
+ return { pass: false, message: `Expected to check selected index ${expected} on element, but element was not a TestSelect` };
190
+ }
191
+ const actual = el.selectedIndex;
192
+ const pass = actual === expected;
193
+ const message = `Expected element to ${isNegative ? 'not ' : ''}have selected index ${expected}, but had ${actual}`;
194
+ return { pass: isNegative ? !pass : pass, message };
195
+ };
196
+ return {
197
+ compare: (el, expected) => {
198
+ return assert(false, el, expected);
199
+ },
200
+ negativeCompare: (el, expected) => {
201
+ return assert(true, el, expected);
202
+ }
203
+ };
204
+ },
205
+ /**
206
+ * Checks that the receiver is a TestSelect wrapping a DOM element with the selected option's value equal to the given value
207
+ */
208
+ toHaveSelectedValue: () => {
209
+ const assert = (isNegative, el, expected) => {
210
+ if (!el) {
211
+ return { pass: false, message: `Expected to check selected value '${expected}' on element, but element was falsy` };
212
+ }
213
+ if (!(el instanceof TestSelect)) {
214
+ return { pass: false, message: `Expected to check selected value '${expected}' on element, but element was not a TestSelect` };
215
+ }
216
+ const actual = el.selectedValue;
217
+ const pass = actual === expected;
218
+ const message = `Expected element to ${isNegative ? 'not ' : ''}have selected value '${expected}', but had '${actual}'`;
219
+ return { pass: isNegative ? !pass : pass, message };
220
+ };
221
+ return {
222
+ compare: (el, expected) => {
223
+ return assert(false, el, expected);
224
+ },
225
+ negativeCompare: (el, expected) => {
226
+ return assert(true, el, expected);
227
+ }
228
+ };
229
+ },
230
+ /**
231
+ * Checks that the receiver is a TestSelect wrapping a DOM element with the selected option's label equal to the given label
232
+ */
233
+ toHaveSelectedLabel: () => {
234
+ const assert = (isNegative, el, expected) => {
235
+ if (!el) {
236
+ return { pass: false, message: `Expected to check selected label '${expected}' on element, but element was falsy` };
237
+ }
238
+ if (!(el instanceof TestSelect)) {
239
+ return { pass: false, message: `Expected to check selected label '${expected}' on element, but element was not a TestSelect` };
240
+ }
241
+ const actual = el.selectedLabel;
242
+ const pass = actual === expected;
243
+ const message = `Expected element to ${isNegative ? 'not ' : ''}have selected label '${expected}', but had '${actual}'`;
244
+ return { pass: isNegative ? !pass : pass, message };
245
+ };
246
+ return {
247
+ compare: (el, expected) => {
248
+ return assert(false, el, expected);
249
+ },
250
+ negativeCompare: (el, expected) => {
251
+ return assert(true, el, expected);
252
+ }
253
+ };
254
+ },
255
+ /**
256
+ * Checks that the receiver is a TestHtmlElement which is visible
257
+ */
258
+ toBeVisible: () => {
259
+ const assert = (isNegative, el) => {
260
+ const expectedState = `${isNegative ? 'in' : ''}visible`;
261
+ const inverseState = `${isNegative ? '' : 'in'}visible`;
262
+ if (!el) {
263
+ return { pass: false, message: `Expected to check if element was ${expectedState}, but element was falsy` };
264
+ }
265
+ if (!(el instanceof TestHtmlElement)) {
266
+ return { pass: false, message: `Expected to check if element was ${expectedState}, but element was not a TestHtmlElement` };
267
+ }
268
+ const pass = el.visible;
269
+ const message = `Expected element to be ${expectedState}, but was ${inverseState}`;
270
+ return { pass: isNegative ? !pass : pass, message };
271
+ };
272
+ return {
273
+ compare: (el) => {
274
+ return assert(false, el);
275
+ },
276
+ negativeCompare: (el) => {
277
+ return assert(true, el);
278
+ }
279
+ };
280
+ }
281
+ };
282
+ export { speculoosMatchers };
283
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0Y2hlcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtc3BlY3Vsb29zL3NyYy9saWIvbWF0Y2hlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDekMsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzdDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRXRELE1BQU0saUJBQWlCLEdBQW1DO0lBQ3hEOztPQUVHO0lBQ0gsV0FBVyxFQUFFLEdBQTBCLEVBQUU7UUFDdkMsTUFBTSxNQUFNLEdBQUcsQ0FBQyxVQUFtQixFQUFFLEVBQVcsRUFBRSxRQUFnQixFQUFFLEVBQUU7WUFDcEUsSUFBSSxDQUFDLEVBQUUsRUFBRTtnQkFDUCxPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsNEJBQTRCLFFBQVEscUNBQXFDLEVBQUUsQ0FBQzthQUM1RztZQUNELElBQUksQ0FBQyxDQUFDLEVBQUUsWUFBWSxXQUFXLENBQUMsRUFBRTtnQkFDaEMsT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLDRCQUE0QixRQUFRLGlEQUFpRCxFQUFFLENBQUM7YUFDeEg7WUFDRCxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDO1lBQzFCLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFDN0MsTUFBTSxPQUFPLEdBQ1gsdUJBQXVCLFVBQVUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLGVBQWUsUUFBUSxLQUFLO2dCQUMzRSxXQUFXLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDdEUsT0FBTyxFQUFFLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUM7UUFDdEQsQ0FBQyxDQUFDO1FBQ0YsT0FBTztZQUNMLE9BQU8sRUFBRSxDQUFDLEVBQVcsRUFBRSxRQUFnQixFQUErQixFQUFFO2dCQUN0RSxPQUFPLE1BQU0sQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQ3JDLENBQUM7WUFDRCxlQUFlLEVBQUUsQ0FBQyxFQUFXLEVBQUUsUUFBZ0IsRUFBK0IsRUFBRTtnQkFDOUUsT0FBTyxNQUFNLENBQUMsSUFBSSxFQUFFLEVBQUUsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUNwQyxDQUFDO1NBQ0YsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNILFdBQVcsRUFBRSxHQUEwQixFQUFFO1FBQ3ZDLE1BQU0sTUFBTSxHQUFHLENBQUMsVUFBbUIsRUFBRSxFQUFXLEVBQUUsUUFBZ0IsRUFBRSxFQUFFO1lBQ3BFLElBQUksQ0FBQyxFQUFFLEVBQUU7Z0JBQ1AsT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLDRCQUE0QixRQUFRLHFDQUFxQyxFQUFFLENBQUM7YUFDNUc7WUFDRCxJQUFJLENBQUMsQ0FBQyxFQUFFLFlBQVksU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsWUFBWSxZQUFZLENBQUMsRUFBRTtnQkFDL0QsT0FBTztvQkFDTCxJQUFJLEVBQUUsS0FBSztvQkFDWCxPQUFPLEVBQUUsNEJBQTRCLFFBQVEsc0VBQXNFO2lCQUNwSCxDQUFDO2FBQ0g7WUFDRCxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDO1lBQ3hCLE1BQU0sSUFBSSxHQUFHLE1BQU0sS0FBSyxRQUFRLENBQUM7WUFDakMsTUFBTSxPQUFPLEdBQUcsdUJBQXVCLFVBQVUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLGVBQWUsUUFBUSxxQkFBcUIsTUFBTSxHQUFHLENBQUM7WUFDckgsT0FBTyxFQUFFLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUM7UUFDdEQsQ0FBQyxDQUFDO1FBQ0YsT0FBTztZQUNMLE9BQU8sRUFBRSxDQUFDLEVBQVcsRUFBRSxRQUFnQixFQUErQixFQUFFO2dCQUN0RSxPQUFPLE1BQU0sQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQ3JDLENBQUM7WUFDRCxlQUFlLEVBQUUsQ0FBQyxFQUFXLEVBQUUsUUFBZ0IsRUFBK0IsRUFBRTtnQkFDOUUsT0FBTyxNQUFNLENBQUMsSUFBSSxFQUFFLEVBQUUsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUNwQyxDQUFDO1NBQ0YsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNILFVBQVUsRUFBRSxHQUEwQixFQUFFO1FBQ3RDLE1BQU0sTUFBTSxHQUFHLENBQUMsVUFBbUIsRUFBRSxFQUFXLEVBQUUsUUFBZ0IsRUFBRSxFQUFFO1lBQ3BFLElBQUksQ0FBQyxFQUFFLEVBQUU7Z0JBQ1AsT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLDJCQUEyQixRQUFRLHFDQUFxQyxFQUFFLENBQUM7YUFDM0c7WUFDRCxJQUFJLENBQUMsQ0FBQyxFQUFFLFlBQVksV0FBVyxDQUFDLEVBQUU7Z0JBQ2hDLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSwyQkFBMkIsUUFBUSxpREFBaUQsRUFBRSxDQUFDO2FBQ3ZIO1lBQ0QsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDLFdBQVcsQ0FBQztZQUM5QixNQUFNLElBQUksR0FBRyxNQUFNLEtBQUssUUFBUSxDQUFDO1lBQ2pDLE1BQU0sT0FBTyxHQUFHLHVCQUF1QixVQUFVLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxjQUFjLFFBQVEsZUFBZSxNQUFNLEdBQUcsQ0FBQztZQUM5RyxPQUFPLEVBQUUsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQztRQUN0RCxDQUFDLENBQUM7UUFDRixPQUFPO1lBQ0wsT0FBTyxFQUFFLENBQUMsRUFBVyxFQUFFLFFBQWdCLEVBQStCLEVBQUU7Z0JBQ3RFLE9BQU8sTUFBTSxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDckMsQ0FBQztZQUNELGVBQWUsRUFBRSxDQUFDLEVBQVcsRUFBRSxRQUFnQixFQUErQixFQUFFO2dCQUM5RSxPQUFPLE1BQU0sQ0FBQyxJQUFJLEVBQUUsRUFBRSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQ3BDLENBQUM7U0FDRixDQUFDO0lBQ0osQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7T0FZRztJQUNILGlCQUFpQixFQUFFLEdBQTBCLEVBQUU7UUFDN0MsTUFBTSxNQUFNLEdBQUcsQ0FBQyxVQUFtQixFQUFFLEVBQVcsRUFBRSxRQUFnQixFQUFFLEVBQUU7WUFDcEUsTUFBTSxlQUFlLEdBQUcsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ3hDLElBQUksQ0FBQyxFQUFFLEVBQUU7Z0JBQ1AsT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLG1DQUFtQyxlQUFlLHFDQUFxQyxFQUFFLENBQUM7YUFDMUg7WUFDRCxJQUFJLENBQUMsQ0FBQyxFQUFFLFlBQVksV0FBVyxDQUFDLEVBQUU7Z0JBQ2hDLE9BQU87b0JBQ0wsSUFBSSxFQUFFLEtBQUs7b0JBQ1gsT0FBTyxFQUFFLG1DQUFtQyxlQUFlLGlEQUFpRDtpQkFDN0csQ0FBQzthQUNIO1lBQ0QsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDLFdBQVcsRUFBRSxJQUFJLEVBQUUsQ0FBQztZQUN0QyxNQUFNLElBQUksR0FBRyxNQUFNLEtBQUssZUFBZSxDQUFDO1lBQ3hDLE1BQU0sT0FBTyxHQUFHLHVCQUF1QixVQUFVLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxzQkFBc0IsZUFBZSxlQUFlLE1BQU0sR0FBRyxDQUFDO1lBQzdILE9BQU8sRUFBRSxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLE9BQU8sRUFBRSxDQUFDO1FBQ3RELENBQUMsQ0FBQztRQUNGLE9BQU87WUFDTCxPQUFPLEVBQUUsQ0FBQyxFQUFXLEVBQUUsUUFBZ0IsRUFBK0IsRUFBRTtnQkFDdEUsT0FBTyxNQUFNLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUNyQyxDQUFDO1lBQ0QsZUFBZSxFQUFFLENBQUMsRUFBVyxFQUFFLFFBQWdCLEVBQStCLEVBQUU7Z0JBQzlFLE9BQU8sTUFBTSxDQUFDLElBQUksRUFBRSxFQUFFLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDcEMsQ0FBQztTQUNGLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSCxhQUFhLEVBQUUsR0FBMEIsRUFBRTtRQUN6QyxNQUFNLE1BQU0sR0FBRyxDQUFDLFVBQW1CLEVBQUUsRUFBVyxFQUFFLFFBQWdCLEVBQUUsRUFBRTtZQUNwRSxJQUFJLENBQUMsRUFBRSxFQUFFO2dCQUNQLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSwyQkFBMkIsUUFBUSxxQ0FBcUMsRUFBRSxDQUFDO2FBQzNHO1lBQ0QsSUFBSSxDQUFDLENBQUMsRUFBRSxZQUFZLFdBQVcsQ0FBQyxFQUFFO2dCQUNoQyxPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsMkJBQTJCLFFBQVEsaURBQWlELEVBQUUsQ0FBQzthQUN2SDtZQUNELE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQyxXQUFXLENBQUM7WUFDOUIsSUFBSSxDQUFDLE1BQU0sRUFBRTtnQkFDWCxPQUFPO29CQUNMLElBQUksRUFBRSxVQUFVO29CQUNoQixPQUFPLEVBQUUsdUJBQXVCLFVBQVUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLGlCQUFpQixRQUFRLG9CQUFvQjtpQkFDdEcsQ0FBQzthQUNIO1lBQ0QsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztZQUM3QyxNQUFNLE9BQU8sR0FBRyx1QkFBdUIsVUFBVSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsaUJBQWlCLFFBQVEsb0JBQW9CLE1BQU0sR0FBRyxDQUFDO1lBQ3RILE9BQU8sRUFBRSxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLE9BQU8sRUFBRSxDQUFDO1FBQ3RELENBQUMsQ0FBQztRQUNGLE9BQU87WUFDTCxPQUFPLEVBQUUsQ0FBQyxFQUFXLEVBQUUsUUFBZ0IsRUFBK0IsRUFBRTtnQkFDdEUsT0FBTyxNQUFNLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUNyQyxDQUFDO1lBQ0QsZUFBZSxFQUFFLENBQUMsRUFBVyxFQUFFLFFBQWdCLEVBQStCLEVBQUU7Z0JBQzlFLE9BQU8sTUFBTSxDQUFDLElBQUksRUFBRSxFQUFFLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDcEMsQ0FBQztTQUNGLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSCxXQUFXLEVBQUUsR0FBMEIsRUFBRTtRQUN2QyxNQUFNLE1BQU0sR0FBRyxDQUFDLFVBQW1CLEVBQUUsRUFBVyxFQUFFLEVBQUU7WUFDbEQsSUFBSSxDQUFDLEVBQUUsRUFBRTtnQkFDUCxPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsaUVBQWlFLEVBQUUsQ0FBQzthQUNwRztZQUNELElBQUksQ0FBQyxDQUFDLEVBQUUsWUFBWSxTQUFTLENBQUMsRUFBRTtnQkFDOUIsT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLDJFQUEyRSxFQUFFLENBQUM7YUFDOUc7WUFDRCxNQUFNLElBQUksR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDO1lBQ3hCLE1BQU0sT0FBTyxHQUFHLDBCQUEwQixVQUFVLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxtQkFBbUIsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDakgsT0FBTyxFQUFFLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUM7UUFDdEQsQ0FBQyxDQUFDO1FBQ0YsT0FBTztZQUNMLE9BQU8sRUFBRSxDQUFDLEVBQVcsRUFBK0IsRUFBRTtnQkFDcEQsT0FBTyxNQUFNLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQzNCLENBQUM7WUFDRCxlQUFlLEVBQUUsQ0FBQyxFQUFXLEVBQStCLEVBQUU7Z0JBQzVELE9BQU8sTUFBTSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQztZQUMxQixDQUFDO1NBQ0YsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNILG1CQUFtQixFQUFFLEdBQTBCLEVBQUU7UUFDL0MsTUFBTSxNQUFNLEdBQUcsQ0FBQyxVQUFtQixFQUFFLEVBQVcsRUFBRSxRQUFnQixFQUFFLEVBQUU7WUFDcEUsSUFBSSxDQUFDLEVBQUUsRUFBRTtnQkFDUCxPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsb0NBQW9DLFFBQVEsb0NBQW9DLEVBQUUsQ0FBQzthQUNuSDtZQUNELElBQUksQ0FBQyxDQUFDLEVBQUUsWUFBWSxVQUFVLENBQUMsRUFBRTtnQkFDL0IsT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLG9DQUFvQyxRQUFRLCtDQUErQyxFQUFFLENBQUM7YUFDOUg7WUFDRCxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsYUFBYSxDQUFDO1lBQ2hDLE1BQU0sSUFBSSxHQUFHLE1BQU0sS0FBSyxRQUFRLENBQUM7WUFDakMsTUFBTSxPQUFPLEdBQUcsdUJBQXVCLFVBQVUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLHVCQUF1QixRQUFRLGFBQWEsTUFBTSxFQUFFLENBQUM7WUFDcEgsT0FBTyxFQUFFLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUM7UUFDdEQsQ0FBQyxDQUFDO1FBQ0YsT0FBTztZQUNMLE9BQU8sRUFBRSxDQUFDLEVBQVcsRUFBRSxRQUFnQixFQUErQixFQUFFO2dCQUN0RSxPQUFPLE1BQU0sQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQ3JDLENBQUM7WUFDRCxlQUFlLEVBQUUsQ0FBQyxFQUFXLEVBQUUsUUFBZ0IsRUFBK0IsRUFBRTtnQkFDOUUsT0FBTyxNQUFNLENBQUMsSUFBSSxFQUFFLEVBQUUsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUNwQyxDQUFDO1NBQ0YsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNILG1CQUFtQixFQUFFLEdBQTBCLEVBQUU7UUFDL0MsTUFBTSxNQUFNLEdBQUcsQ0FBQyxVQUFtQixFQUFFLEVBQVcsRUFBRSxRQUFnQixFQUFFLEVBQUU7WUFDcEUsSUFBSSxDQUFDLEVBQUUsRUFBRTtnQkFDUCxPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUscUNBQXFDLFFBQVEscUNBQXFDLEVBQUUsQ0FBQzthQUNySDtZQUNELElBQUksQ0FBQyxDQUFDLEVBQUUsWUFBWSxVQUFVLENBQUMsRUFBRTtnQkFDL0IsT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLHFDQUFxQyxRQUFRLGdEQUFnRCxFQUFFLENBQUM7YUFDaEk7WUFDRCxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsYUFBYSxDQUFDO1lBQ2hDLE1BQU0sSUFBSSxHQUFHLE1BQU0sS0FBSyxRQUFRLENBQUM7WUFDakMsTUFBTSxPQUFPLEdBQUcsdUJBQXVCLFVBQVUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLHdCQUF3QixRQUFRLGVBQWUsTUFBTSxHQUFHLENBQUM7WUFDeEgsT0FBTyxFQUFFLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUM7UUFDdEQsQ0FBQyxDQUFDO1FBQ0YsT0FBTztZQUNMLE9BQU8sRUFBRSxDQUFDLEVBQVcsRUFBRSxRQUFnQixFQUErQixFQUFFO2dCQUN0RSxPQUFPLE1BQU0sQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQ3JDLENBQUM7WUFDRCxlQUFlLEVBQUUsQ0FBQyxFQUFXLEVBQUUsUUFBZ0IsRUFBK0IsRUFBRTtnQkFDOUUsT0FBTyxNQUFNLENBQUMsSUFBSSxFQUFFLEVBQUUsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUNwQyxDQUFDO1NBQ0YsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNILG1CQUFtQixFQUFFLEdBQTBCLEVBQUU7UUFDL0MsTUFBTSxNQUFNLEdBQUcsQ0FBQyxVQUFtQixFQUFFLEVBQVcsRUFBRSxRQUFnQixFQUFFLEVBQUU7WUFDcEUsSUFBSSxDQUFDLEVBQUUsRUFBRTtnQkFDUCxPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUscUNBQXFDLFFBQVEscUNBQXFDLEVBQUUsQ0FBQzthQUNySDtZQUNELElBQUksQ0FBQyxDQUFDLEVBQUUsWUFBWSxVQUFVLENBQUMsRUFBRTtnQkFDL0IsT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLHFDQUFxQyxRQUFRLGdEQUFnRCxFQUFFLENBQUM7YUFDaEk7WUFDRCxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsYUFBYSxDQUFDO1lBQ2hDLE1BQU0sSUFBSSxHQUFHLE1BQU0sS0FBSyxRQUFRLENBQUM7WUFDakMsTUFBTSxPQUFPLEdBQUcsdUJBQXVCLFVBQVUsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLHdCQUF3QixRQUFRLGVBQWUsTUFBTSxHQUFHLENBQUM7WUFDeEgsT0FBTyxFQUFFLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUM7UUFDdEQsQ0FBQyxDQUFDO1FBQ0YsT0FBTztZQUNMLE9BQU8sRUFBRSxDQUFDLEVBQVcsRUFBRSxRQUFnQixFQUErQixFQUFFO2dCQUN0RSxPQUFPLE1BQU0sQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQ3JDLENBQUM7WUFDRCxlQUFlLEVBQUUsQ0FBQyxFQUFXLEVBQUUsUUFBZ0IsRUFBK0IsRUFBRTtnQkFDOUUsT0FBTyxNQUFNLENBQUMsSUFBSSxFQUFFLEVBQUUsRUFBRSxRQUFRLENBQUMsQ0FBQztZQUNwQyxDQUFDO1NBQ0YsQ0FBQztJQUNKLENBQUM7SUFFRDs7T0FFRztJQUNILFdBQVcsRUFBRSxHQUEwQixFQUFFO1FBQ3ZDLE1BQU0sTUFBTSxHQUFHLENBQUMsVUFBbUIsRUFBRSxFQUFXLEVBQUUsRUFBRTtZQUNsRCxNQUFNLGFBQWEsR0FBRyxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLFNBQVMsQ0FBQztZQUN6RCxNQUFNLFlBQVksR0FBRyxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLFNBQVMsQ0FBQztZQUN4RCxJQUFJLENBQUMsRUFBRSxFQUFFO2dCQUNQLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxvQ0FBb0MsYUFBYSx5QkFBeUIsRUFBRSxDQUFDO2FBQzdHO1lBQ0QsSUFBSSxDQUFDLENBQUMsRUFBRSxZQUFZLGVBQWUsQ0FBQyxFQUFFO2dCQUNwQyxPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsb0NBQW9DLGFBQWEseUNBQXlDLEVBQUUsQ0FBQzthQUM3SDtZQUNELE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUM7WUFDeEIsTUFBTSxPQUFPLEdBQUcsMEJBQTBCLGFBQWEsYUFBYSxZQUFZLEVBQUUsQ0FBQztZQUNuRixPQUFPLEVBQUUsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQztRQUN0RCxDQUFDLENBQUM7UUFDRixPQUFPO1lBQ0wsT0FBTyxFQUFFLENBQUMsRUFBVyxFQUErQixFQUFFO2dCQUNwRCxPQUFPLE1BQU0sQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDM0IsQ0FBQztZQUNELGVBQWUsRUFBRSxDQUFDLEVBQVcsRUFBK0IsRUFBRTtnQkFDNUQsT0FBTyxNQUFNLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQzFCLENBQUM7U0FDRixDQUFDO0lBQ0osQ0FBQztDQUNGLENBQUM7QUFFRixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFRlc3RUZXh0QXJlYSB9IGZyb20gJy4vdGVzdC10ZXh0YXJlYSc7XG5pbXBvcnQgeyBUZXN0SW5wdXQgfSBmcm9tICcuL3Rlc3QtaW5wdXQnO1xuaW1wb3J0IHsgVGVzdEVsZW1lbnQgfSBmcm9tICcuL3Rlc3QtZWxlbWVudCc7XG5pbXBvcnQgeyBUZXN0U2VsZWN0IH0gZnJvbSAnLi90ZXN0LXNlbGVjdCc7XG5pbXBvcnQgeyBUZXN0SHRtbEVsZW1lbnQgfSBmcm9tICcuL3Rlc3QtaHRtbC1lbGVtZW50JztcblxuY29uc3Qgc3BlY3Vsb29zTWF0Y2hlcnM6IGphc21pbmUuQ3VzdG9tTWF0Y2hlckZhY3RvcmllcyA9IHtcbiAgLyoqXG4gICAqIENoZWNrcyB0aGF0IHRoZSByZWNlaXZlciBpcyBhIFRlc3RFbGVtZW50IHdyYXBwaW5nIGEgRE9NIGVsZW1lbnQgYW5kIGFzIHRoZSBnaXZlbiBDU1MgY2xhc3NcbiAgICovXG4gIHRvSGF2ZUNsYXNzOiAoKTogamFzbWluZS5DdXN0b21NYXRjaGVyID0+IHtcbiAgICBjb25zdCBhc3NlcnQgPSAoaXNOZWdhdGl2ZTogYm9vbGVhbiwgZWw6IHVua25vd24sIGV4cGVjdGVkOiBzdHJpbmcpID0+IHtcbiAgICAgIGlmICghZWwpIHtcbiAgICAgICAgcmV0dXJuIHsgcGFzczogZmFsc2UsIG1lc3NhZ2U6IGBFeHBlY3RlZCB0byBjaGVjayBjbGFzcyAnJHtleHBlY3RlZH0nIG9uIGVsZW1lbnQsIGJ1dCBlbGVtZW50IHdhcyBmYWxzeWAgfTtcbiAgICAgIH1cbiAgICAgIGlmICghKGVsIGluc3RhbmNlb2YgVGVzdEVsZW1lbnQpKSB7XG4gICAgICAgIHJldHVybiB7IHBhc3M6IGZhbHNlLCBtZXNzYWdlOiBgRXhwZWN0ZWQgdG8gY2hlY2sgY2xhc3MgJyR7ZXhwZWN0ZWR9JyBvbiBlbGVtZW50LCBidXQgZWxlbWVudCB3YXMgbm90IGEgVGVzdEVsZW1lbnRgIH07XG4gICAgICB9XG4gICAgICBjb25zdCBhY3R1YWwgPSBlbC5jbGFzc2VzO1xuICAgICAgY29uc3QgcGFzcyA9IGFjdHVhbC5pbmRleE9mKGV4cGVjdGVkKSAhPT0gLTE7XG4gICAgICBjb25zdCBtZXNzYWdlID1cbiAgICAgICAgYEV4cGVjdGVkIGVsZW1lbnQgdG8gJHtpc05lZ2F0aXZlID8gJ25vdCAnIDogJyd9aGF2ZSBjbGFzcyAnJHtleHBlY3RlZH0nLCBgICtcbiAgICAgICAgYGJ1dCBoYWQgJHthY3R1YWwubGVuZ3RoID8gXCInXCIgKyBhY3R1YWwuam9pbignLCAnKSArIFwiJ1wiIDogJ25vbmUnfWA7XG4gICAgICByZXR1cm4geyBwYXNzOiBpc05lZ2F0aXZlID8gIXBhc3MgOiBwYXNzLCBtZXNzYWdlIH07XG4gICAgfTtcbiAgICByZXR1cm4ge1xuICAgICAgY29tcGFyZTogKGVsOiB1bmtub3duLCBleHBlY3RlZDogc3RyaW5nKTogamFzbWluZS5DdXN0b21NYXRjaGVyUmVzdWx0ID0+IHtcbiAgICAgICAgcmV0dXJuIGFzc2VydChmYWxzZSwgZWwsIGV4cGVjdGVkKTtcbiAgICAgIH0sXG4gICAgICBuZWdhdGl2ZUNvbXBhcmU6IChlbDogdW5rbm93biwgZXhwZWN0ZWQ6IHN0cmluZyk6IGphc21pbmUuQ3VzdG9tTWF0Y2hlclJlc3VsdCA9PiB7XG4gICAgICAgIHJldHVybiBhc3NlcnQodHJ1ZSwgZWwsIGV4cGVjdGVkKTtcbiAgICAgIH1cbiAgICB9O1xuICB9LFxuXG4gIC8qKlxuICAgKiBDaGVja3MgdGhhdCB0aGUgcmVjZWl2ZXIgaXMgYSBUZXN0SW5wdXQgb3IgYSBUZXN0VGV4dEFyZWEgYW5kIGhhcyB0aGUgZ2l2ZW4gdmFsdWVcbiAgICovXG4gIHRvSGF2ZVZhbHVlOiAoKTogamFzbWluZS5DdXN0b21NYXRjaGVyID0+IHtcbiAgICBjb25zdCBhc3NlcnQgPSAoaXNOZWdhdGl2ZTogYm9vbGVhbiwgZWw6IHVua25vd24sIGV4cGVjdGVkOiBzdHJpbmcpID0+IHtcbiAgICAgIGlmICghZWwpIHtcbiAgICAgICAgcmV0dXJuIHsgcGFzczogZmFsc2UsIG1lc3NhZ2U6IGBFeHBlY3RlZCB0byBjaGVjayB2YWx1ZSAnJHtleHBlY3RlZH0nIG9uIGVsZW1lbnQsIGJ1dCBlbGVtZW50IHdhcyBmYWxzeWAgfTtcbiAgICAgIH1cbiAgICAgIGlmICghKGVsIGluc3RhbmNlb2YgVGVzdElucHV0KSAmJiAhKGVsIGluc3RhbmNlb2YgVGVzdFRleHRBcmVhKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHBhc3M6IGZhbHNlLFxuICAgICAgICAgIG1lc3NhZ2U6IGBFeHBlY3RlZCB0byBjaGVjayB2YWx1ZSAnJHtleHBlY3RlZH0nIG9uIGVsZW1lbnQsIGJ1dCBlbGVtZW50IHdhcyBuZWl0aGVyIGEgVGVzdElucHV0IG5vciBhIFRlc3RUZXh0QXJlYWBcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGFjdHVhbCA9IGVsLnZhbHVlO1xuICAgICAgY29uc3QgcGFzcyA9IGFjdHVhbCA9PT0gZXhwZWN0ZWQ7XG4gICAgICBjb25zdCBtZXNzYWdlID0gYEV4cGVjdGVkIGVsZW1lbnQgdG8gJHtpc05lZ2F0aXZlID8gJ25vdCAnIDogJyd9aGF2ZSB2YWx1ZSAnJHtleHBlY3RlZH0nLCBidXQgaGFkIHZhbHVlICcke2FjdHVhbH0nYDtcbiAgICAgIHJldHVybiB7IHBhc3M6IGlzTmVnYXRpdmUgPyAhcGFzcyA6IHBhc3MsIG1lc3NhZ2UgfTtcbiAgICB9O1xuICAgIHJldHVybiB7XG4gICAgICBjb21wYXJlOiAoZWw6IHVua25vd24sIGV4cGVjdGVkOiBzdHJpbmcpOiBqYXNtaW5lLkN1c3RvbU1hdGNoZXJSZXN1bHQgPT4ge1xuICAgICAgICByZXR1cm4gYXNzZXJ0KGZhbHNlLCBlbCwgZXhwZWN0ZWQpO1xuICAgICAgfSxcbiAgICAgIG5lZ2F0aXZlQ29tcGFyZTogKGVsOiB1bmtub3duLCBleHBlY3RlZDogc3RyaW5nKTogamFzbWluZS5DdXN0b21NYXRjaGVyUmVzdWx0ID0+IHtcbiAgICAgICAgcmV0dXJuIGFzc2VydCh0cnVlLCBlbCwgZXhwZWN0ZWQpO1xuICAgICAgfVxuICAgIH07XG4gIH0sXG5cbiAgLyoqXG4gICAqIENoZWNrcyB0aGF0IHRoZSByZWNlaXZlciBpcyBhIFRlc3RFbGVtZW50IHdyYXBwaW5nIGEgRE9NIGVsZW1lbnQgYW5kIGhhcyB0aGUgZXhhY3QgZ2l2ZW4gdGV4dENvbnRlbnRcbiAgICovXG4gIHRvSGF2ZVRleHQ6ICgpOiBqYXNtaW5lLkN1c3RvbU1hdGNoZXIgPT4ge1xuICAgIGNvbnN0IGFzc2VydCA9IChpc05lZ2F0aXZlOiBib29sZWFuLCBlbDogdW5rbm93biwgZXhwZWN0ZWQ6IHN0cmluZykgPT4ge1xuICAgICAgaWYgKCFlbCkge1xuICAgICAgICByZXR1cm4geyBwYXNzOiBmYWxzZSwgbWVzc2FnZTogYEV4cGVjdGVkIHRvIGNoZWNrIHRleHQgJyR7ZXhwZWN0ZWR9JyBvbiBlbGVtZW50LCBidXQgZWxlbWVudCB3YXMgZmFsc3lgIH07XG4gICAgICB9XG4gICAgICBpZiAoIShlbCBpbnN0YW5jZW9mIFRlc3RFbGVtZW50KSkge1xuICAgICAgICByZXR1cm4geyBwYXNzOiBmYWxzZSwgbWVzc2FnZTogYEV4cGVjdGVkIHRvIGNoZWNrIHRleHQgJyR7ZXhwZWN0ZWR9JyBvbiBlbGVtZW50LCBidXQgZWxlbWVudCB3YXMgbm90IGEgVGVzdEVsZW1lbnRgIH07XG4gICAgICB9XG4gICAgICBjb25zdCBhY3R1YWwgPSBlbC50ZXh0Q29udGVudDtcbiAgICAgIGNvbnN0IHBhc3MgPSBhY3R1YWwgPT09IGV4cGVjdGVkO1xuICAgICAgY29uc3QgbWVzc2FnZSA9IGBFeHBlY3RlZCBlbGVtZW50IHRvICR7aXNOZWdhdGl2ZSA/ICdub3QgJyA6ICcnfWhhdmUgdGV4dCAnJHtleHBlY3RlZH0nLCBidXQgaGFkICcke2FjdHVhbH0nYDtcbiAgICAgIHJldHVybiB7IHBhc3M6IGlzTmVnYXRpdmUgPyAhcGFzcyA6IHBhc3MsIG1lc3NhZ2UgfTtcbiAgICB9O1xuICAgIHJldHVybiB7XG4gICAgICBjb21wYXJlOiAoZWw6IHVua25vd24sIGV4cGVjdGVkOiBzdHJpbmcpOiBqYXNtaW5lLkN1c3RvbU1hdGNoZXJSZXN1bHQgPT4ge1xuICAgICAgICByZXR1cm4gYXNzZXJ0KGZhbHNlLCBlbCwgZXhwZWN0ZWQpO1xuICAgICAgfSxcbiAgICAgIG5lZ2F0aXZlQ29tcGFyZTogKGVsOiB1bmtub3duLCBleHBlY3RlZDogc3RyaW5nKTogamFzbWluZS5DdXN0b21NYXRjaGVyUmVzdWx0ID0+IHtcbiAgICAgICAgcmV0dXJuIGFzc2VydCh0cnVlLCBlbCwgZXhwZWN0ZWQpO1xuICAgICAgfVxuICAgIH07XG4gIH0sXG5cbiAgLyoqXG4gICAqIENoZWNrcyB0aGF0IHRoZSByZWNlaXZlciBpcyBhIFRlc3RFbGVtZW50IHdyYXBwaW5nIGEgRE9NIGVsZW1lbnQgYW5kIGhhcyB0aGUgZ2l2ZW4gdGV4dENvbnRlbnQsIGFmdGVyIGJvdGggaGF2ZSBiZWVuIHRyaW1tZWQuXG4gICAqIFNvLCBBbiBlbGVtZW50IHN1Y2ggYXNcbiAgICogYGBgXG4gICAqIDxoMT5cbiAgICogICBTb21lIHRpdGxlXG4gICAqIDwvaDE+XG4gICAqIGBgYFxuICAgKiB3aWxsIHBhc3MgdGhlIHRlc3RcbiAgICogYGBgXG4gICAqIGV4cGVjdCh0ZXN0ZXIudGl0bGUpLnRvSGF2ZVRyaW1tZWRUZXh0KCdTb21lIHRpdGxlJylcbiAgICogYGBgXG4gICAqL1xuICB0b0hhdmVUcmltbWVkVGV4dDogKCk6IGphc21pbmUuQ3VzdG9tTWF0Y2hlciA9PiB7XG4gICAgY29uc3QgYXNzZXJ0ID0gKGlzTmVnYXRpdmU6IGJvb2xlYW4sIGVsOiB1bmtub3duLCBleHBlY3RlZDogc3RyaW5nKSA9PiB7XG4gICAgICBjb25zdCB0cmltbWVkRXhwZWN0ZWQgPSBleHBlY3RlZC50cmltKCk7XG4gICAgICBpZiAoIWVsKSB7XG4gICAgICAgIHJldHVybiB7IHBhc3M6IGZhbHNlLCBtZXNzYWdlOiBgRXhwZWN0ZWQgdG8gY2hlY2sgdHJpbW1lZCB0ZXh0ICcke3RyaW1tZWRFeHBlY3RlZH0nIG9uIGVsZW1lbnQsIGJ1dCBlbGVtZW50IHdhcyBmYWxzeWAgfTtcbiAgICAgIH1cbiAgICAgIGlmICghKGVsIGluc3RhbmNlb2YgVGVzdEVsZW1lbnQpKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgcGFzczogZmFsc2UsXG4gICAgICAgICAgbWVzc2FnZTogYEV4cGVjdGVkIHRvIGNoZWNrIHRyaW1tZWQgdGV4dCAnJHt0cmltbWVkRXhwZWN0ZWR9JyBvbiBlbGVtZW50LCBidXQgZWxlbWVudCB3YXMgbm90IGEgVGVzdEVsZW1lbnRgXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCBhY3R1YWwgPSBlbC50ZXh0Q29udGVudD8udHJpbSgpO1xuICAgICAgY29uc3QgcGFzcyA9IGFjdHVhbCA9PT0gdHJpbW1lZEV4cGVjdGVkO1xuICAgICAgY29uc3QgbWVzc2FnZSA9IGBFeHBlY3RlZCBlbGVtZW50IHRvICR7aXNOZWdhdGl2ZSA/ICdub3QgJyA6ICcnfWhhdmUgdHJpbW1lZCB0ZXh0ICcke3RyaW1tZWRFeHBlY3RlZH0nLCBidXQgaGFkICcke2FjdHVhbH0nYDtcbiAgICAgIHJldHVybiB7IHBhc3M6IGlzTmVnYXRpdmUgPyAhcGFzcyA6IHBhc3MsIG1lc3NhZ2UgfTtcbiAgICB9O1xuICAgIHJldHVybiB7XG4gICAgICBjb21wYXJlOiAoZWw6IHVua25vd24sIGV4cGVjdGVkOiBzdHJpbmcpOiBqYXNtaW5lLkN1c3RvbU1hdGNoZXJSZXN1bHQgPT4ge1xuICAgICAgICByZXR1cm4gYXNzZXJ0KGZhbHNlLCBlbCwgZXhwZWN0ZWQpO1xuICAgICAgfSxcbiAgICAgIG5lZ2F0aXZlQ29tcGFyZTogKGVsOiB1bmtub3duLCBleHBlY3RlZDogc3RyaW5nKTogamFzbWluZS5DdXN0b21NYXRjaGVyUmVzdWx0ID0+IHtcbiAgICAgICAgcmV0dXJuIGFzc2VydCh0cnVlLCBlbCwgZXhwZWN0ZWQpO1xuICAgICAgfVxuICAgIH07XG4gIH0sXG5cbiAgLyoqXG4gICAqIENoZWNrcyB0aGF0IHRoZSByZWNlaXZlciBpcyBhIFRlc3RFbGVtZW50IHdyYXBwaW5nIGEgRE9NIGVsZW1lbnQgYW5kIGNvbnRhaW5zIHRoZSBnaXZlbiB0ZXh0Q29udGVudFxuICAgKi9cbiAgdG9Db250YWluVGV4dDogKCk6IGphc21pbmUuQ3VzdG9tTWF0Y2hlciA9PiB7XG4gICAgY29uc3QgYXNzZXJ0ID0gKGlzTmVnYXRpdmU6IGJvb2xlYW4sIGVsOiB1bmtub3duLCBleHBlY3RlZDogc3RyaW5nKSA9PiB7XG4gICAgICBpZiAoIWVsKSB7XG4gICAgICAgIHJldHVybiB7IHBhc3M6IGZhbHNlLCBtZXNzYWdlOiBgRXhwZWN0ZWQgdG8gY2hlY2sgdGV4dCAnJHtleHBlY3RlZH0nIG9uIGVsZW1lbnQsIGJ1dCBlbGVtZW50IHdhcyBmYWxzeWAgfTtcbiAgICAgIH1cbiAgICAgIGlmICghKGVsIGluc3RhbmNlb2YgVGVzdEVsZW1lbnQpKSB7XG4gICAgICAgIHJldHVybiB7IHBhc3M6IGZhbHNlLCBtZXNzYWdlOiBgRXhwZWN0ZWQgdG8gY2hlY2sgdGV4dCAnJHtleHBlY3RlZH0nIG9uIGVsZW1lbnQsIGJ1dCBlbGVtZW50IHdhcyBub3QgYSBUZXN0RWxlbWVudGAgfTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGFjdHVhbCA9IGVsLnRleHRDb250ZW50O1xuICAgICAgaWYgKCFhY3R1YWwpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBwYXNzOiBpc05lZ2F0aXZlLFxuICAgICAgICAgIG1lc3NhZ2U6IGBFeHBlY3RlZCBlbGVtZW50IHRvICR7aXNOZWdhdGl2ZSA/ICdub3QgJyA6ICcnfWNvbnRhaW4gdGV4dCAnJHtleHBlY3RlZH0nLCBidXQgaGFkIG5vIHRleHRgXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBjb25zdCBwYXNzID0gYWN0dWFsLmluZGV4T2YoZXhwZWN0ZWQpICE9PSAtMTtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBgRXhwZWN0ZWQgZWxlbWVudCB0byAke2lzTmVnYXRpdmUgPyAnbm90ICcgOiAnJ31jb250YWluIHRleHQgJyR7ZXhwZWN0ZWR9JywgYnV0IGhhZCB0ZXh0ICcke2FjdHVhbH0nYDtcbiAgICAgIHJldHVybiB7IHBhc3M6IGlzTmVnYXRpdmUgPyAhcGFzcyA6IHBhc3MsIG1lc3NhZ2UgfTtcbiAgICB9O1xuICAgIHJldHVybiB7XG4gICAgICBjb21wYXJlOiAoZWw6IHVua25vd24sIGV4cGVjdGVkOiBzdHJpbmcpOiBqYXNtaW5lLkN1c3RvbU1hdGNoZXJSZXN1bHQgPT4ge1xuICAgICAgICByZXR1cm4gYXNzZXJ0KGZhbHNlLCBlbCwgZXhwZWN0ZWQpO1xuICAgICAgfSxcbiAgICAgIG5lZ2F0aXZlQ29tcGFyZTogKGVsOiB1bmtub3duLCBleHBlY3RlZDogc3RyaW5nKTogamFzbWluZS5DdXN0b21NYXRjaGVyUmVzdWx0ID0+IHtcbiAgICAgICAgcmV0dXJuIGFzc2VydCh0cnVlLCBlbCwgZXhwZWN0ZWQpO1xuICAgICAgfVxuICAgIH07XG4gIH0sXG5cbiAgLyoqXG4gICAqIENoZWNrcyB0aGF0IHRoZSByZWNlaXZlciBpcyBhIFRlc3RFbGVtZW50IHdyYXBwaW5nIGEgRE9NIGVsZW1lbnQgYW5kIGNvbnRhaW5zIHRoZSBnaXZlbiB0ZXh0Q29udGVudFxuICAgKi9cbiAgdG9CZUNoZWNrZWQ6ICgpOiBqYXNtaW5lLkN1c3RvbU1hdGNoZXIgPT4ge1xuICAgIGNvbnN0IGFzc2VydCA9IChpc05lZ2F0aXZlOiBib29sZWFuLCBlbDogdW5rbm93bikgPT4ge1xuICAgICAgaWYgKCFlbCkge1xuICAgICAgICByZXR1cm4geyBwYXNzOiBmYWxzZSwgbWVzc2FnZTogYEV4cGVjdGVkIHRvIGNoZWNrIGlmIGVsZW1lbnQgd2FzIGNoZWNrZWQsIGJ1dCBlbGVtZW50IHdhcyBmYWxzeWAgfTtcbiAgICAgIH1cbiAgICAgIGlmICghKGVsIGluc3RhbmNlb2YgVGVzdElucHV0KSkge1xuICAgICAgICByZXR1cm4geyBwYXNzOiBmYWxzZSwgbWVzc2FnZTogYEV4cGVjdGVkIHRvIGNoZWNrIGlmIGVsZW1lbnQgd2FzIGNoZWNrZWQsIGJ1dCBlbGVtZW50IHdhcyBub3QgYSBUZXN0SW5wdXRgIH07XG4gICAgICB9XG4gICAgICBjb25zdCBwYXNzID0gZWwuY2hlY2tlZDtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBgRXhwZWN0ZWQgZWxlbWVudCB0byBiZSAke2lzTmVnYXRpdmUgPyAnbm90ICcgOiAnJ31jaGVja2VkLCBidXQgd2FzJHshaXNOZWdhdGl2ZSA/ICcgbm90JyA6ICcnfWA7XG4gICAgICByZXR1cm4geyBwYXNzOiBpc05lZ2F0aXZlID8gIXBhc3MgOiBwYXNzLCBtZXNzYWdlIH07XG4gICAgfTtcbiAgICByZXR1cm4ge1xuICAgICAgY29tcGFyZTogKGVsOiB1bmtub3duKTogamFzbWluZS5DdXN0b21NYXRjaGVyUmVzdWx0ID0+IHtcbiAgICAgICAgcmV0dXJuIGFzc2VydChmYWxzZSwgZWwpO1xuICAgICAgfSxcbiAgICAgIG5lZ2F0aXZlQ29tcGFyZTogKGVsOiB1bmtub3duKTogamFzbWluZS5DdXN0b21NYXRjaGVyUmVzdWx0ID0+IHtcbiAgICAgICAgcmV0dXJuIGFzc2VydCh0cnVlLCBlbCk7XG4gICAgICB9XG4gICAgfTtcbiAgfSxcblxuICAvKipcbiAgICogQ2hlY2tzIHRoYXQgdGhlIHJlY2VpdmVyIGlzIGEgVGVzdFNlbGVjdCB3cmFwcGluZyBhIERPTSBlbGVtZW50IGFuZCBoYXMgdGhlIGdpdmVuIHNlbGVjdGVkIGluZGV4XG4gICAqL1xuICB0b0hhdmVTZWxlY3RlZEluZGV4OiAoKTogamFzbWluZS5DdXN0b21NYXRjaGVyID0+IHtcbiAgICBjb25zdCBhc3NlcnQgPSAoaXNOZWdhdGl2ZTogYm9vbGVhbiwgZWw6IHVua25vd24sIGV4cGVjdGVkOiBudW1iZXIpID0+IHtcbiAgICAgIGlmICghZWwpIHtcbiAgICAgICAgcmV0dXJuIHsgcGFzczogZmFsc2UsIG1lc3NhZ2U6IGBFeHBlY3RlZCB0byBjaGVjayBzZWxlY3RlZCBpbmRleCAke2V4cGVjdGVkfSBvbiBlbGVtZW50LCBidXQgZWxlbWVudCB3YXMgZmFsc3lgIH07XG4gICAgICB9XG4gICAgICBpZiAoIShlbCBpbnN0YW5jZW9mIFRlc3RTZWxlY3QpKSB7XG4gICAgICAgIHJldHVybiB7IHBhc3M6IGZhbHNlLCBtZXNzYWdlOiBgRXhwZWN0ZWQgdG8gY2hlY2sgc2VsZWN0ZWQgaW5kZXggJHtleHBlY3RlZH0gb24gZWxlbWVudCwgYnV0IGVsZW1lbnQgd2FzIG5vdCBhIFRlc3RTZWxlY3RgIH07XG4gICAgICB9XG4gICAgICBjb25zdCBhY3R1YWwgPSBlbC5zZWxlY3RlZEluZGV4O1xuICAgICAgY29uc3QgcGFzcyA9IGFjdHVhbCA9PT0gZXhwZWN0ZWQ7XG4gICAgICBjb25zdCBtZXNzYWdlID0gYEV4cGVjdGVkIGVsZW1lbnQgdG8gJHtpc05lZ2F0aXZlID8gJ25vdCAnIDogJyd9aGF2ZSBzZWxlY3RlZCBpbmRleCAke2V4cGVjdGVkfSwgYnV0IGhhZCAke2FjdHVhbH1gO1xuICAgICAgcmV0dXJuIHsgcGFzczogaXNOZWdhdGl2ZSA/ICFwYXNzIDogcGFzcywgbWVzc2FnZSB9O1xuICAgIH07XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbXBhcmU6IChlbDogdW5rbm93biwgZXhwZWN0ZWQ6IG51bWJlcik6IGphc21pbmUuQ3VzdG9tTWF0Y2hlclJlc3VsdCA9PiB7XG4gICAgICAgIHJldHVybiBhc3NlcnQoZmFsc2UsIGVsLCBleHBlY3RlZCk7XG4gICAgICB9LFxuICAgICAgbmVnYXRpdmVDb21wYXJlOiAoZWw6IHVua25vd24sIGV4cGVjdGVkOiBudW1iZXIpOiBqYXNtaW5lLkN1c3RvbU1hdGNoZXJSZXN1bHQgPT4ge1xuICAgICAgICByZXR1cm4gYXNzZXJ0KHRydWUsIGVsLCBleHBlY3RlZCk7XG4gICAgICB9XG4gICAgfTtcbiAgfSxcblxuICAvKipcbiAgICogQ2hlY2tzIHRoYXQgdGhlIHJlY2VpdmVyIGlzIGEgVGVzdFNlbGVjdCB3cmFwcGluZyBhIERPTSBlbGVtZW50IHdpdGggdGhlIHNlbGVjdGVkIG9wdGlvbidzIHZhbHVlIGVxdWFsIHRvIHRoZSBnaXZlbiB2YWx1ZVxuICAgKi9cbiAgdG9IYXZlU2VsZWN0ZWRWYWx1ZTogKCk6IGphc21pbmUuQ3VzdG9tTWF0Y2hlciA9PiB7XG4gICAgY29uc3QgYXNzZXJ0ID0gKGlzTmVnYXRpdmU6IGJvb2xlYW4sIGVsOiB1bmtub3duLCBleHBlY3RlZDogc3RyaW5nKSA9PiB7XG4gICAgICBpZiAoIWVsKSB7XG4gICAgICAgIHJldHVybiB7IHBhc3M6IGZhbHNlLCBtZXNzYWdlOiBgRXhwZWN0ZWQgdG8gY2hlY2sgc2VsZWN0ZWQgdmFsdWUgJyR7ZXhwZWN0ZWR9JyBvbiBlbGVtZW50LCBidXQgZWxlbWVudCB3YXMgZmFsc3lgIH07XG4gICAgICB9XG4gICAgICBpZiAoIShlbCBpbnN0YW5jZW9mIFRlc3RTZWxlY3QpKSB7XG4gICAgICAgIHJldHVybiB7IHBhc3M6IGZhbHNlLCBtZXNzYWdlOiBgRXhwZWN0ZWQgdG8gY2hlY2sgc2VsZWN0ZWQgdmFsdWUgJyR7ZXhwZWN0ZWR9JyBvbiBlbGVtZW50LCBidXQgZWxlbWVudCB3YXMgbm90IGEgVGVzdFNlbGVjdGAgfTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGFjdHVhbCA9IGVsLnNlbGVjdGVkVmFsdWU7XG4gICAgICBjb25zdCBwYXNzID0gYWN0dWFsID09PSBleHBlY3RlZDtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBgRXhwZWN0ZWQgZWxlbWVudCB0byAke2lzTmVnYXRpdmUgPyAnbm90ICcgOiAnJ31oYXZlIHNlbGVjdGVkIHZhbHVlICcke2V4cGVjdGVkfScsIGJ1dCBoYWQgJyR7YWN0dWFsfSdgO1xuICAgICAgcmV0dXJuIHsgcGFzczogaXNOZWdhdGl2ZSA/ICFwYXNzIDogcGFzcywgbWVzc2FnZSB9O1xuICAgIH07XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbXBhcmU6IChlbDogdW5rbm93biwgZXhwZWN0ZWQ6IHN0cmluZyk6IGphc21pbmUuQ3VzdG9tTWF0Y2hlclJlc3VsdCA9PiB7XG4gICAgICAgIHJldHVybiBhc3NlcnQoZmFsc2UsIGVsLCBleHBlY3RlZCk7XG4gICAgICB9LFxuICAgICAgbmVnYXRpdmVDb21wYXJlOiAoZWw6IHVua25vd24sIGV4cGVjdGVkOiBzdHJpbmcpOiBqYXNtaW5lLkN1c3RvbU1hdGNoZXJSZXN1bHQgPT4ge1xuICAgICAgICByZXR1cm4gYXNzZXJ0KHRydWUsIGVsLCBleHBlY3RlZCk7XG4gICAgICB9XG4gICAgfTtcbiAgfSxcblxuICAvKipcbiAgICogQ2hlY2tzIHRoYXQgdGhlIHJlY2VpdmVyIGlzIGEgVGVzdFNlbGVjdCB3cmFwcGluZyBhIERPTSBlbGVtZW50IHdpdGggdGhlIHNlbGVjdGVkIG9wdGlvbidzIGxhYmVsIGVxdWFsIHRvIHRoZSBnaXZlbiBsYWJlbFxuICAgKi9cbiAgdG9IYXZlU2VsZWN0ZWRMYWJlbDogKCk6IGphc21pbmUuQ3VzdG9tTWF0Y2hlciA9PiB7XG4gICAgY29uc3QgYXNzZXJ0ID0gKGlzTmVnYXRpdmU6IGJvb2xlYW4sIGVsOiB1bmtub3duLCBleHBlY3RlZDogc3RyaW5nKSA9PiB7XG4gICAgICBpZiAoIWVsKSB7XG4gICAgICAgIHJldHVybiB7IHBhc3M6IGZhbHNlLCBtZXNzYWdlOiBgRXhwZWN0ZWQgdG8gY2hlY2sgc2VsZWN0ZWQgbGFiZWwgJyR7ZXhwZWN0ZWR9JyBvbiBlbGVtZW50LCBidXQgZWxlbWVudCB3YXMgZmFsc3lgIH07XG4gICAgICB9XG4gICAgICBpZiAoIShlbCBpbnN0YW5jZW9mIFRlc3RTZWxlY3QpKSB7XG4gICAgICAgIHJldHVybiB7IHBhc3M6IGZhbHNlLCBtZXNzYWdlOiBgRXhwZWN0ZWQgdG8gY2hlY2sgc2VsZWN0ZWQgbGFiZWwgJyR7ZXhwZWN0ZWR9JyBvbiBlbGVtZW50LCBidXQgZWxlbWVudCB3YXMgbm90IGEgVGVzdFNlbGVjdGAgfTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGFjdHVhbCA9IGVsLnNlbGVjdGVkTGFiZWw7XG4gICAgICBjb25zdCBwYXNzID0gYWN0dWFsID09PSBleHBlY3RlZDtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBgRXhwZWN0ZWQgZWxlbWVudCB0byAke2lzTmVnYXRpdmUgPyAnbm90ICcgOiAnJ31oYXZlIHNlbGVjdGVkIGxhYmVsICcke2V4cGVjdGVkfScsIGJ1dCBoYWQgJyR7YWN0dWFsfSdgO1xuICAgICAgcmV0dXJuIHsgcGFzczogaXNOZWdhdGl2ZSA/ICFwYXNzIDogcGFzcywgbWVzc2FnZSB9O1xuICAgIH07XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbXBhcmU6IChlbDogdW5rbm93biwgZXhwZWN0ZWQ6IHN0cmluZyk6IGphc21pbmUuQ3VzdG9tTWF0Y2hlclJlc3VsdCA9PiB7XG4gICAgICAgIHJldHVybiBhc3NlcnQoZmFsc2UsIGVsLCBleHBlY3RlZCk7XG4gICAgICB9LFxuICAgICAgbmVnYXRpdmVDb21wYXJlOiAoZWw6IHVua25vd24sIGV4cGVjdGVkOiBzdHJpbmcpOiBqYXNtaW5lLkN1c3RvbU1hdGNoZXJSZXN1bHQgPT4ge1xuICAgICAgICByZXR1cm4gYXNzZXJ0KHRydWUsIGVsLCBleHBlY3RlZCk7XG4gICAgICB9XG4gICAgfTtcbiAgfSxcblxuICAvKipcbiAgICogQ2hlY2tzIHRoYXQgdGhlIHJlY2VpdmVyIGlzIGEgVGVzdEh0bWxFbGVtZW50IHdoaWNoIGlzIHZpc2libGVcbiAgICovXG4gIHRvQmVWaXNpYmxlOiAoKTogamFzbWluZS5DdXN0b21NYXRjaGVyID0+IHtcbiAgICBjb25zdCBhc3NlcnQgPSAoaXNOZWdhdGl2ZTogYm9vbGVhbiwgZWw6IHVua25vd24pID0+IHtcbiAgICAgIGNvbnN0IGV4cGVjdGVkU3RhdGUgPSBgJHtpc05lZ2F0aXZlID8gJ2luJyA6ICcnfXZpc2libGVgO1xuICAgICAgY29uc3QgaW52ZXJzZVN0YXRlID0gYCR7aXNOZWdhdGl2ZSA/ICcnIDogJ2luJ312aXNpYmxlYDtcbiAgICAgIGlmICghZWwpIHtcbiAgICAgICAgcmV0dXJuIHsgcGFzczogZmFsc2UsIG1lc3NhZ2U6IGBFeHBlY3RlZCB0byBjaGVjayBpZiBlbGVtZW50IHdhcyAke2V4cGVjdGVkU3RhdGV9LCBidXQgZWxlbWVudCB3YXMgZmFsc3lgIH07XG4gICAgICB9XG4gICAgICBpZiAoIShlbCBpbnN0YW5jZW9mIFRlc3RIdG1sRWxlbWVudCkpIHtcbiAgICAgICAgcmV0dXJuIHsgcGFzczogZmFsc2UsIG1lc3NhZ2U6IGBFeHBlY3RlZCB0byBjaGVjayBpZiBlbGVtZW50IHdhcyAke2V4cGVjdGVkU3RhdGV9LCBidXQgZWxlbWVudCB3YXMgbm90IGEgVGVzdEh0bWxFbGVtZW50YCB9O1xuICAgICAgfVxuICAgICAgY29uc3QgcGFzcyA9IGVsLnZpc2libGU7XG4gICAgICBjb25zdCBtZXNzYWdlID0gYEV4cGVjdGVkIGVsZW1lbnQgdG8gYmUgJHtleHBlY3RlZFN0YXRlfSwgYnV0IHdhcyAke2ludmVyc2VTdGF0ZX1gO1xuICAgICAgcmV0dXJuIHsgcGFzczogaXNOZWdhdGl2ZSA/ICFwYXNzIDogcGFzcywgbWVzc2FnZSB9O1xuICAgIH07XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbXBhcmU6IChlbDogdW5rbm93bik6IGphc21pbmUuQ3VzdG9tTWF0Y2hlclJlc3VsdCA9PiB7XG4gICAgICAgIHJldHVybiBhc3NlcnQoZmFsc2UsIGVsKTtcbiAgICAgIH0sXG4gICAgICBuZWdhdGl2ZUNvbXBhcmU6IChlbDogdW5rbm93bik6IGphc21pbmUuQ3VzdG9tTWF0Y2hlclJlc3VsdCA9PiB7XG4gICAgICAgIHJldHVybiBhc3NlcnQodHJ1ZSwgZWwpO1xuICAgICAgfVxuICAgIH07XG4gIH1cbn07XG5cbmV4cG9ydCB7IHNwZWN1bG9vc01hdGNoZXJzIH07XG4iXX0=
@@ -0,0 +1,25 @@
1
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2
+ function collectMethodNames(proto) {
3
+ if (!proto || proto === Object.prototype) {
4
+ return [];
5
+ }
6
+ const methodNames = [];
7
+ for (const key of Object.getOwnPropertyNames(proto)) {
8
+ const descriptor = Object.getOwnPropertyDescriptor(proto, key);
9
+ if (descriptor && typeof descriptor.value === 'function' && key !== 'constructor') {
10
+ methodNames.push(key);
11
+ }
12
+ }
13
+ return [...methodNames, ...collectMethodNames(Object.getPrototypeOf(proto))];
14
+ }
15
+ /**
16
+ * Creates a spy object for a class where all the methods of the class (and of its superclasses) are spies.
17
+ * I.e., for a class `UserService` with methods `get()`, `create()`, `update()` and `delete()`, calling
18
+ * `createMock(UserService)` is equivalent to calling
19
+ * `jasmine.createSpyObj<UserService>('UserService', ['get', 'create', 'update', 'delete']).
20
+ * @param type the type to mock (usually a service class)
21
+ */
22
+ export function createMock(type) {
23
+ return jasmine.createSpyObj(type.name, collectMethodNames(type.prototype));
24
+ }
25
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9jay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1zcGVjdWxvb3Mvc3JjL2xpYi9tb2NrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLDhEQUE4RDtBQUM5RCxTQUFTLGtCQUFrQixDQUFDLEtBQWM7SUFDeEMsSUFBSSxDQUFDLEtBQUssSUFBSSxLQUFLLEtBQUssTUFBTSxDQUFDLFNBQVMsRUFBRTtRQUN4QyxPQUFPLEVBQUUsQ0FBQztLQUNYO0lBQ0QsTUFBTSxXQUFXLEdBQWtCLEVBQUUsQ0FBQztJQUN0QyxLQUFLLE1BQU0sR0FBRyxJQUFJLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxLQUFLLENBQUMsRUFBRTtRQUNuRCxNQUFNLFVBQVUsR0FBRyxNQUFNLENBQUMsd0JBQXdCLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQy9ELElBQUksVUFBVSxJQUFJLE9BQU8sVUFBVSxDQUFDLEtBQUssS0FBSyxVQUFVLElBQUksR0FBRyxLQUFLLGFBQWEsRUFBRTtZQUNqRixXQUFXLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQ3ZCO0tBQ0Y7SUFDRCxPQUFPLENBQUMsR0FBRyxXQUFXLEVBQUUsR0FBRyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUMvRSxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLFVBQVUsQ0FBSSxJQUFhO0lBQ3pDLE9BQU8sT0FBTyxDQUFDLFlBQVksQ0FBSSxJQUFJLENBQUMsSUFBSSxFQUFFLGtCQUFrQixDQUFDLElBQUksQ0FBQyxTQUFTLENBQTRDLENBQUMsQ0FBQztBQUMzSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgVHlwZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuZnVuY3Rpb24gY29sbGVjdE1ldGhvZE5hbWVzKHByb3RvOiB1bmtub3duKTogQXJyYXk8c3RyaW5nPiB7XG4gIGlmICghcHJvdG8gfHwgcHJvdG8gPT09IE9iamVjdC5wcm90b3R5cGUpIHtcbiAgICByZXR1cm4gW107XG4gIH1cbiAgY29uc3QgbWV0aG9kTmFtZXM6IEFycmF5PHN0cmluZz4gPSBbXTtcbiAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMocHJvdG8pKSB7XG4gICAgY29uc3QgZGVzY3JpcHRvciA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IocHJvdG8sIGtleSk7XG4gICAgaWYgKGRlc2NyaXB0b3IgJiYgdHlwZW9mIGRlc2NyaXB0b3IudmFsdWUgPT09ICdmdW5jdGlvbicgJiYga2V5ICE9PSAnY29uc3RydWN0b3InKSB7XG4gICAgICBtZXRob2ROYW1lcy5wdXNoKGtleSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBbLi4ubWV0aG9kTmFtZXMsIC4uLmNvbGxlY3RNZXRob2ROYW1lcyhPYmplY3QuZ2V0UHJvdG90eXBlT2YocHJvdG8pKV07XG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIHNweSBvYmplY3QgZm9yIGEgY2xhc3Mgd2hlcmUgYWxsIHRoZSBtZXRob2RzIG9mIHRoZSBjbGFzcyAoYW5kIG9mIGl0cyBzdXBlcmNsYXNzZXMpIGFyZSBzcGllcy5cbiAqIEkuZS4sIGZvciBhIGNsYXNzIGBVc2VyU2VydmljZWAgd2l0aCBtZXRob2RzIGBnZXQoKWAsIGBjcmVhdGUoKWAsIGB1cGRhdGUoKWAgYW5kIGBkZWxldGUoKWAsIGNhbGxpbmdcbiAqIGBjcmVhdGVNb2NrKFVzZXJTZXJ2aWNlKWAgaXMgZXF1aXZhbGVudCB0byBjYWxsaW5nXG4gKiBgamFzbWluZS5jcmVhdGVTcHlPYmo8VXNlclNlcnZpY2U+KCdVc2VyU2VydmljZScsIFsnZ2V0JywgJ2NyZWF0ZScsICd1cGRhdGUnLCAnZGVsZXRlJ10pLlxuICogQHBhcmFtIHR5cGUgdGhlIHR5cGUgdG8gbW9jayAodXN1YWxseSBhIHNlcnZpY2UgY2xhc3MpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVNb2NrPFQ+KHR5cGU6IFR5cGU8VD4pOiBqYXNtaW5lLlNweU9iajxUPiB7XG4gIHJldHVybiBqYXNtaW5lLmNyZWF0ZVNweU9iajxUPih0eXBlLm5hbWUsIGNvbGxlY3RNZXRob2ROYW1lcyh0eXBlLnByb3RvdHlwZSkgYXMgdW5rbm93biBhcyBqYXNtaW5lLlNweU9iak1ldGhvZE5hbWVzPFQ+KTtcbn1cbiJdfQ==