@fluidframework/telemetry-utils 2.0.0-internal.4.2.1 → 2.0.0-internal.4.4.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # @fluidframework/telemetry-utils
2
2
 
3
+ ## 2.0.0-internal.4.4.0
4
+
5
+ Dependency updates only.
6
+
3
7
  ## 2.0.0-internal.4.1.0
4
8
 
5
9
  Dependency updates only.
@@ -17,35 +17,38 @@ export declare class MockLogger extends TelemetryLogger implements ITelemetryLog
17
17
  * Search events logged since the last time matchEvents was called, looking for the given expected
18
18
  * events in order.
19
19
  * @param expectedEvents - events in order that are expected to appear in the recorded log.
20
+ * @param inlineDetailsProp - true if the "details" property in the actual event should be extracted and inlined.
20
21
  * These event objects may be subsets of the logged events.
21
22
  * Note: category is omitted from the type because it's usually uninteresting and tedious to type.
22
23
  */
23
- matchEvents(expectedEvents: Omit<ITelemetryBaseEvent, "category">[]): boolean;
24
+ matchEvents(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], inlineDetailsProp?: boolean): boolean;
24
25
  /** Asserts that matchEvents is true, and prints the actual/expected output if not */
25
- assertMatch(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string): void;
26
+ assertMatch(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string, inlineDetailsProp?: boolean): void;
26
27
  /**
27
28
  * Search events logged since the last time matchEvents was called, looking for any of the given
28
29
  * expected events.
29
30
  * @param expectedEvents - events that are expected to appear in the recorded log.
31
+ * @param inlineDetailsProp - true if the "details" property in the actual event should be extracted and inlined.
30
32
  * These event objects may be subsets of the logged events.
31
33
  * Note: category is omitted from the type because it's usually uninteresting and tedious to type.
32
34
  * @returns if any of the expected events is found.
33
35
  */
34
- matchAnyEvent(expectedEvents: Omit<ITelemetryBaseEvent, "category">[]): boolean;
36
+ matchAnyEvent(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], inlineDetailsProp?: boolean): boolean;
35
37
  /** Asserts that matchAnyEvent is true, and prints the actual/expected output if not */
36
- assertMatchAny(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string): void;
38
+ assertMatchAny(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string, inlineDetailsProp?: boolean): void;
37
39
  /**
38
40
  * Search events logged since the last time matchEvents was called, looking only for the given expected
39
41
  * events in order.
40
42
  * @param expectedEvents - events in order that are expected to be the only events in the recorded log.
43
+ * @param inlineDetailsProp - true if the "details" property in the actual event should be extracted and inlined.
41
44
  * These event objects may be subsets of the logged events.
42
45
  * Note: category is omitted from the type because it's usually uninteresting and tedious to type.
43
46
  */
44
- matchEventStrict(expectedEvents: Omit<ITelemetryBaseEvent, "category">[]): boolean;
47
+ matchEventStrict(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], inlineDetailsProp?: boolean): boolean;
45
48
  /** Asserts that matchEvents is true, and prints the actual/expected output if not */
46
- assertMatchStrict(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string): void;
49
+ assertMatchStrict(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string, inlineDetailsProp?: boolean): void;
47
50
  /** Asserts that matchAnyEvent is false for the given events, and prints the actual/expected output if not */
48
- assertMatchNone(disallowedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string): void;
51
+ assertMatchNone(disallowedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string, inlineDetailsProp?: boolean): void;
49
52
  private getMatchedEventsCount;
50
53
  /**
51
54
  * Ensure the expected event is a strict subset of the actual event
@@ -1 +1 @@
1
- {"version":3,"file":"mockLogger.d.ts","sourceRoot":"","sources":["../src/mockLogger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAC3F,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C;;;GAGG;AACH,qBAAa,UAAW,SAAQ,eAAgB,YAAW,gBAAgB;IAC1E,MAAM,EAAE,mBAAmB,EAAE,CAAM;;IAMnC,KAAK;IAIL,IAAI,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI;IAItC;;;;;;OAMG;IACH,WAAW,CAAC,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,GAAG,OAAO;IAO7E,qFAAqF;IACrF,WAAW,CAAC,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM;IAYrF;;;;;;;OAOG;IACH,aAAa,CAAC,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,GAAG,OAAO;IAK/E,uFAAuF;IACvF,cAAc,CAAC,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM;IAYxF;;;;;;OAMG;IACH,gBAAgB,CAAC,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,GAAG,OAAO;IAIlF,qFAAqF;IACrF,iBAAiB,CAAC,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM;IAY3F,6GAA6G;IAC7G,eAAe,CAAC,gBAAgB,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM;IAY3F,OAAO,CAAC,qBAAqB;IAmB7B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;CAO1B"}
1
+ {"version":3,"file":"mockLogger.d.ts","sourceRoot":"","sources":["../src/mockLogger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAE3F,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C;;;GAGG;AACH,qBAAa,UAAW,SAAQ,eAAgB,YAAW,gBAAgB;IAC1E,MAAM,EAAE,mBAAmB,EAAE,CAAM;;IAMnC,KAAK;IAIL,IAAI,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI;IAItC;;;;;;;OAOG;IACH,WAAW,CACV,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EACvD,iBAAiB,GAAE,OAAe,GAChC,OAAO;IAUV,qFAAqF;IACrF,WAAW,CACV,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EACvD,OAAO,CAAC,EAAE,MAAM,EAChB,iBAAiB,GAAE,OAAe;IAanC;;;;;;;;OAQG;IACH,aAAa,CACZ,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EACvD,iBAAiB,GAAE,OAAe,GAChC,OAAO;IAQV,uFAAuF;IACvF,cAAc,CACb,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EACvD,OAAO,CAAC,EAAE,MAAM,EAChB,iBAAiB,GAAE,OAAe;IAanC;;;;;;;OAOG;IACH,gBAAgB,CACf,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EACvD,iBAAiB,GAAE,OAAe,GAChC,OAAO;IAOV,qFAAqF;IACrF,iBAAiB,CAChB,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EACvD,OAAO,CAAC,EAAE,MAAM,EAChB,iBAAiB,GAAE,OAAe;IAanC,6GAA6G;IAC7G,eAAe,CACd,gBAAgB,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EACzD,OAAO,CAAC,EAAE,MAAM,EAChB,iBAAiB,GAAE,OAAe;IAanC,OAAO,CAAC,qBAAqB;IAsB7B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;CAqB1B"}
@@ -3,8 +3,20 @@
3
3
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
4
4
  * Licensed under the MIT License.
5
5
  */
6
+ var __rest = (this && this.__rest) || function (s, e) {
7
+ var t = {};
8
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
9
+ t[p] = s[p];
10
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
11
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
12
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
13
+ t[p[i]] = s[p[i]];
14
+ }
15
+ return t;
16
+ };
6
17
  Object.defineProperty(exports, "__esModule", { value: true });
7
18
  exports.MockLogger = void 0;
19
+ const common_utils_1 = require("@fluidframework/common-utils");
8
20
  const logger_1 = require("./logger");
9
21
  /**
10
22
  * The MockLogger records events sent to it, and then can walk back over those events
@@ -25,19 +37,20 @@ class MockLogger extends logger_1.TelemetryLogger {
25
37
  * Search events logged since the last time matchEvents was called, looking for the given expected
26
38
  * events in order.
27
39
  * @param expectedEvents - events in order that are expected to appear in the recorded log.
40
+ * @param inlineDetailsProp - true if the "details" property in the actual event should be extracted and inlined.
28
41
  * These event objects may be subsets of the logged events.
29
42
  * Note: category is omitted from the type because it's usually uninteresting and tedious to type.
30
43
  */
31
- matchEvents(expectedEvents) {
32
- const matchedExpectedEventCount = this.getMatchedEventsCount(expectedEvents);
44
+ matchEvents(expectedEvents, inlineDetailsProp = false) {
45
+ const matchedExpectedEventCount = this.getMatchedEventsCount(expectedEvents, inlineDetailsProp);
33
46
  // How many expected events were left over? Hopefully none.
34
47
  const unmatchedExpectedEventCount = expectedEvents.length - matchedExpectedEventCount;
35
48
  return unmatchedExpectedEventCount === 0;
36
49
  }
37
50
  /** Asserts that matchEvents is true, and prints the actual/expected output if not */
38
- assertMatch(expectedEvents, message) {
51
+ assertMatch(expectedEvents, message, inlineDetailsProp = false) {
39
52
  const actualEvents = this.events;
40
- if (!this.matchEvents(expectedEvents)) {
53
+ if (!this.matchEvents(expectedEvents, inlineDetailsProp)) {
41
54
  throw new Error(`${message}
42
55
  expected:
43
56
  ${JSON.stringify(expectedEvents)}
@@ -50,18 +63,19 @@ ${JSON.stringify(actualEvents)}`);
50
63
  * Search events logged since the last time matchEvents was called, looking for any of the given
51
64
  * expected events.
52
65
  * @param expectedEvents - events that are expected to appear in the recorded log.
66
+ * @param inlineDetailsProp - true if the "details" property in the actual event should be extracted and inlined.
53
67
  * These event objects may be subsets of the logged events.
54
68
  * Note: category is omitted from the type because it's usually uninteresting and tedious to type.
55
69
  * @returns if any of the expected events is found.
56
70
  */
57
- matchAnyEvent(expectedEvents) {
58
- const matchedExpectedEventCount = this.getMatchedEventsCount(expectedEvents);
71
+ matchAnyEvent(expectedEvents, inlineDetailsProp = false) {
72
+ const matchedExpectedEventCount = this.getMatchedEventsCount(expectedEvents, inlineDetailsProp);
59
73
  return matchedExpectedEventCount > 0;
60
74
  }
61
75
  /** Asserts that matchAnyEvent is true, and prints the actual/expected output if not */
62
- assertMatchAny(expectedEvents, message) {
76
+ assertMatchAny(expectedEvents, message, inlineDetailsProp = false) {
63
77
  const actualEvents = this.events;
64
- if (!this.matchAnyEvent(expectedEvents)) {
78
+ if (!this.matchAnyEvent(expectedEvents, inlineDetailsProp)) {
65
79
  throw new Error(`${message}
66
80
  expected:
67
81
  ${JSON.stringify(expectedEvents)}
@@ -74,16 +88,18 @@ ${JSON.stringify(actualEvents)}`);
74
88
  * Search events logged since the last time matchEvents was called, looking only for the given expected
75
89
  * events in order.
76
90
  * @param expectedEvents - events in order that are expected to be the only events in the recorded log.
91
+ * @param inlineDetailsProp - true if the "details" property in the actual event should be extracted and inlined.
77
92
  * These event objects may be subsets of the logged events.
78
93
  * Note: category is omitted from the type because it's usually uninteresting and tedious to type.
79
94
  */
80
- matchEventStrict(expectedEvents) {
81
- return expectedEvents.length === this.events.length && this.matchEvents(expectedEvents);
95
+ matchEventStrict(expectedEvents, inlineDetailsProp = false) {
96
+ return (expectedEvents.length === this.events.length &&
97
+ this.matchEvents(expectedEvents, inlineDetailsProp));
82
98
  }
83
99
  /** Asserts that matchEvents is true, and prints the actual/expected output if not */
84
- assertMatchStrict(expectedEvents, message) {
100
+ assertMatchStrict(expectedEvents, message, inlineDetailsProp = false) {
85
101
  const actualEvents = this.events;
86
- if (!this.matchEventStrict(expectedEvents)) {
102
+ if (!this.matchEventStrict(expectedEvents, inlineDetailsProp)) {
87
103
  throw new Error(`${message}
88
104
  expected:
89
105
  ${JSON.stringify(expectedEvents)}
@@ -93,9 +109,9 @@ ${JSON.stringify(actualEvents)}`);
93
109
  }
94
110
  }
95
111
  /** Asserts that matchAnyEvent is false for the given events, and prints the actual/expected output if not */
96
- assertMatchNone(disallowedEvents, message) {
112
+ assertMatchNone(disallowedEvents, message, inlineDetailsProp = false) {
97
113
  const actualEvents = this.events;
98
- if (this.matchAnyEvent(disallowedEvents)) {
114
+ if (this.matchAnyEvent(disallowedEvents, inlineDetailsProp)) {
99
115
  throw new Error(`${message}
100
116
  disallowed events:
101
117
  ${JSON.stringify(disallowedEvents)}
@@ -104,11 +120,11 @@ actual:
104
120
  ${JSON.stringify(actualEvents)}`);
105
121
  }
106
122
  }
107
- getMatchedEventsCount(expectedEvents) {
123
+ getMatchedEventsCount(expectedEvents, inlineDetailsProp) {
108
124
  let iExpectedEvent = 0;
109
125
  this.events.forEach((event) => {
110
126
  if (iExpectedEvent < expectedEvents.length &&
111
- MockLogger.eventsMatch(event, expectedEvents[iExpectedEvent])) {
127
+ MockLogger.eventsMatch(event, expectedEvents[iExpectedEvent], inlineDetailsProp)) {
112
128
  // We found the next expected event; increment
113
129
  ++iExpectedEvent;
114
130
  }
@@ -121,9 +137,19 @@ ${JSON.stringify(actualEvents)}`);
121
137
  /**
122
138
  * Ensure the expected event is a strict subset of the actual event
123
139
  */
124
- static eventsMatch(actual, expected) {
125
- const masked = Object.assign(Object.assign({}, actual), expected);
126
- return JSON.stringify(masked) === JSON.stringify(actual);
140
+ static eventsMatch(actual, expected, inlineDetailsProp) {
141
+ const { details } = actual, actualForMatching = __rest(actual, ["details"]);
142
+ let detailsExpanded = { details };
143
+ // "details" is used in a lot of telemetry logs to group a bunch of properties together and stringify them.
144
+ // Some of the properties in the expected event may be inside "details". So, if inlineDetailsProp is true,
145
+ // extract the properties from "details" in the actual event and inline them in the actual event.
146
+ if (inlineDetailsProp && details !== undefined) {
147
+ (0, common_utils_1.assert)(typeof details === "string", 0x6c9 /* Details should a JSON stringified string if inlineDetailsProp is true */);
148
+ detailsExpanded = JSON.parse(details);
149
+ }
150
+ const actualExpanded = Object.assign(Object.assign({}, actualForMatching), detailsExpanded);
151
+ const masked = Object.assign(Object.assign({}, actualExpanded), expected);
152
+ return JSON.stringify(masked) === JSON.stringify(actualExpanded);
127
153
  }
128
154
  }
129
155
  exports.MockLogger = MockLogger;
@@ -1 +1 @@
1
- {"version":3,"file":"mockLogger.js","sourceRoot":"","sources":["../src/mockLogger.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLogger, ITelemetryBaseEvent } from \"@fluidframework/common-definitions\";\nimport { TelemetryLogger } from \"./logger\";\n\n/**\n * The MockLogger records events sent to it, and then can walk back over those events\n * searching for a set of expected events to match against the logged events.\n */\nexport class MockLogger extends TelemetryLogger implements ITelemetryLogger {\n\tevents: ITelemetryBaseEvent[] = [];\n\n\tconstructor() {\n\t\tsuper();\n\t}\n\n\tclear() {\n\t\tthis.events = [];\n\t}\n\n\tsend(event: ITelemetryBaseEvent): void {\n\t\tthis.events.push(event);\n\t}\n\n\t/**\n\t * Search events logged since the last time matchEvents was called, looking for the given expected\n\t * events in order.\n\t * @param expectedEvents - events in order that are expected to appear in the recorded log.\n\t * These event objects may be subsets of the logged events.\n\t * Note: category is omitted from the type because it's usually uninteresting and tedious to type.\n\t */\n\tmatchEvents(expectedEvents: Omit<ITelemetryBaseEvent, \"category\">[]): boolean {\n\t\tconst matchedExpectedEventCount = this.getMatchedEventsCount(expectedEvents);\n\t\t// How many expected events were left over? Hopefully none.\n\t\tconst unmatchedExpectedEventCount = expectedEvents.length - matchedExpectedEventCount;\n\t\treturn unmatchedExpectedEventCount === 0;\n\t}\n\n\t/** Asserts that matchEvents is true, and prints the actual/expected output if not */\n\tassertMatch(expectedEvents: Omit<ITelemetryBaseEvent, \"category\">[], message?: string) {\n\t\tconst actualEvents = this.events;\n\t\tif (!this.matchEvents(expectedEvents)) {\n\t\t\tthrow new Error(`${message}\nexpected:\n${JSON.stringify(expectedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\t/**\n\t * Search events logged since the last time matchEvents was called, looking for any of the given\n\t * expected events.\n\t * @param expectedEvents - events that are expected to appear in the recorded log.\n\t * These event objects may be subsets of the logged events.\n\t * Note: category is omitted from the type because it's usually uninteresting and tedious to type.\n\t * @returns if any of the expected events is found.\n\t */\n\tmatchAnyEvent(expectedEvents: Omit<ITelemetryBaseEvent, \"category\">[]): boolean {\n\t\tconst matchedExpectedEventCount = this.getMatchedEventsCount(expectedEvents);\n\t\treturn matchedExpectedEventCount > 0;\n\t}\n\n\t/** Asserts that matchAnyEvent is true, and prints the actual/expected output if not */\n\tassertMatchAny(expectedEvents: Omit<ITelemetryBaseEvent, \"category\">[], message?: string) {\n\t\tconst actualEvents = this.events;\n\t\tif (!this.matchAnyEvent(expectedEvents)) {\n\t\t\tthrow new Error(`${message}\nexpected:\n${JSON.stringify(expectedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\t/**\n\t * Search events logged since the last time matchEvents was called, looking only for the given expected\n\t * events in order.\n\t * @param expectedEvents - events in order that are expected to be the only events in the recorded log.\n\t * These event objects may be subsets of the logged events.\n\t * Note: category is omitted from the type because it's usually uninteresting and tedious to type.\n\t */\n\tmatchEventStrict(expectedEvents: Omit<ITelemetryBaseEvent, \"category\">[]): boolean {\n\t\treturn expectedEvents.length === this.events.length && this.matchEvents(expectedEvents);\n\t}\n\n\t/** Asserts that matchEvents is true, and prints the actual/expected output if not */\n\tassertMatchStrict(expectedEvents: Omit<ITelemetryBaseEvent, \"category\">[], message?: string) {\n\t\tconst actualEvents = this.events;\n\t\tif (!this.matchEventStrict(expectedEvents)) {\n\t\t\tthrow new Error(`${message}\nexpected:\n${JSON.stringify(expectedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\t/** Asserts that matchAnyEvent is false for the given events, and prints the actual/expected output if not */\n\tassertMatchNone(disallowedEvents: Omit<ITelemetryBaseEvent, \"category\">[], message?: string) {\n\t\tconst actualEvents = this.events;\n\t\tif (this.matchAnyEvent(disallowedEvents)) {\n\t\t\tthrow new Error(`${message}\ndisallowed events:\n${JSON.stringify(disallowedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\tprivate getMatchedEventsCount(expectedEvents: Omit<ITelemetryBaseEvent, \"category\">[]): number {\n\t\tlet iExpectedEvent = 0;\n\t\tthis.events.forEach((event) => {\n\t\t\tif (\n\t\t\t\tiExpectedEvent < expectedEvents.length &&\n\t\t\t\tMockLogger.eventsMatch(event, expectedEvents[iExpectedEvent])\n\t\t\t) {\n\t\t\t\t// We found the next expected event; increment\n\t\t\t\t++iExpectedEvent;\n\t\t\t}\n\t\t});\n\n\t\t// Remove the events so far; next call will just compare subsequent events from here\n\t\tthis.events = [];\n\n\t\t// Return the count of matched events.\n\t\treturn iExpectedEvent;\n\t}\n\n\t/**\n\t * Ensure the expected event is a strict subset of the actual event\n\t */\n\tprivate static eventsMatch(\n\t\tactual: ITelemetryBaseEvent,\n\t\texpected: Omit<ITelemetryBaseEvent, \"category\">,\n\t): boolean {\n\t\tconst masked = { ...actual, ...expected };\n\t\treturn JSON.stringify(masked) === JSON.stringify(actual);\n\t}\n}\n"]}
1
+ {"version":3,"file":"mockLogger.js","sourceRoot":"","sources":["../src/mockLogger.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLogger, ITelemetryBaseEvent } from \"@fluidframework/common-definitions\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { TelemetryLogger } from \"./logger\";\n\n/**\n * The MockLogger records events sent to it, and then can walk back over those events\n * searching for a set of expected events to match against the logged events.\n */\nexport class MockLogger extends TelemetryLogger implements ITelemetryLogger {\n\tevents: ITelemetryBaseEvent[] = [];\n\n\tconstructor() {\n\t\tsuper();\n\t}\n\n\tclear() {\n\t\tthis.events = [];\n\t}\n\n\tsend(event: ITelemetryBaseEvent): void {\n\t\tthis.events.push(event);\n\t}\n\n\t/**\n\t * Search events logged since the last time matchEvents was called, looking for the given expected\n\t * events in order.\n\t * @param expectedEvents - events in order that are expected to appear in the recorded log.\n\t * @param inlineDetailsProp - true if the \"details\" property in the actual event should be extracted and inlined.\n\t * These event objects may be subsets of the logged events.\n\t * Note: category is omitted from the type because it's usually uninteresting and tedious to type.\n\t */\n\tmatchEvents(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tinlineDetailsProp: boolean = false,\n\t): boolean {\n\t\tconst matchedExpectedEventCount = this.getMatchedEventsCount(\n\t\t\texpectedEvents,\n\t\t\tinlineDetailsProp,\n\t\t);\n\t\t// How many expected events were left over? Hopefully none.\n\t\tconst unmatchedExpectedEventCount = expectedEvents.length - matchedExpectedEventCount;\n\t\treturn unmatchedExpectedEventCount === 0;\n\t}\n\n\t/** Asserts that matchEvents is true, and prints the actual/expected output if not */\n\tassertMatch(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tmessage?: string,\n\t\tinlineDetailsProp: boolean = false,\n\t) {\n\t\tconst actualEvents = this.events;\n\t\tif (!this.matchEvents(expectedEvents, inlineDetailsProp)) {\n\t\t\tthrow new Error(`${message}\nexpected:\n${JSON.stringify(expectedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\t/**\n\t * Search events logged since the last time matchEvents was called, looking for any of the given\n\t * expected events.\n\t * @param expectedEvents - events that are expected to appear in the recorded log.\n\t * @param inlineDetailsProp - true if the \"details\" property in the actual event should be extracted and inlined.\n\t * These event objects may be subsets of the logged events.\n\t * Note: category is omitted from the type because it's usually uninteresting and tedious to type.\n\t * @returns if any of the expected events is found.\n\t */\n\tmatchAnyEvent(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tinlineDetailsProp: boolean = false,\n\t): boolean {\n\t\tconst matchedExpectedEventCount = this.getMatchedEventsCount(\n\t\t\texpectedEvents,\n\t\t\tinlineDetailsProp,\n\t\t);\n\t\treturn matchedExpectedEventCount > 0;\n\t}\n\n\t/** Asserts that matchAnyEvent is true, and prints the actual/expected output if not */\n\tassertMatchAny(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tmessage?: string,\n\t\tinlineDetailsProp: boolean = false,\n\t) {\n\t\tconst actualEvents = this.events;\n\t\tif (!this.matchAnyEvent(expectedEvents, inlineDetailsProp)) {\n\t\t\tthrow new Error(`${message}\nexpected:\n${JSON.stringify(expectedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\t/**\n\t * Search events logged since the last time matchEvents was called, looking only for the given expected\n\t * events in order.\n\t * @param expectedEvents - events in order that are expected to be the only events in the recorded log.\n\t * @param inlineDetailsProp - true if the \"details\" property in the actual event should be extracted and inlined.\n\t * These event objects may be subsets of the logged events.\n\t * Note: category is omitted from the type because it's usually uninteresting and tedious to type.\n\t */\n\tmatchEventStrict(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tinlineDetailsProp: boolean = false,\n\t): boolean {\n\t\treturn (\n\t\t\texpectedEvents.length === this.events.length &&\n\t\t\tthis.matchEvents(expectedEvents, inlineDetailsProp)\n\t\t);\n\t}\n\n\t/** Asserts that matchEvents is true, and prints the actual/expected output if not */\n\tassertMatchStrict(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tmessage?: string,\n\t\tinlineDetailsProp: boolean = false,\n\t) {\n\t\tconst actualEvents = this.events;\n\t\tif (!this.matchEventStrict(expectedEvents, inlineDetailsProp)) {\n\t\t\tthrow new Error(`${message}\nexpected:\n${JSON.stringify(expectedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\t/** Asserts that matchAnyEvent is false for the given events, and prints the actual/expected output if not */\n\tassertMatchNone(\n\t\tdisallowedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tmessage?: string,\n\t\tinlineDetailsProp: boolean = false,\n\t) {\n\t\tconst actualEvents = this.events;\n\t\tif (this.matchAnyEvent(disallowedEvents, inlineDetailsProp)) {\n\t\t\tthrow new Error(`${message}\ndisallowed events:\n${JSON.stringify(disallowedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\tprivate getMatchedEventsCount(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tinlineDetailsProp: boolean,\n\t): number {\n\t\tlet iExpectedEvent = 0;\n\t\tthis.events.forEach((event) => {\n\t\t\tif (\n\t\t\t\tiExpectedEvent < expectedEvents.length &&\n\t\t\t\tMockLogger.eventsMatch(event, expectedEvents[iExpectedEvent], inlineDetailsProp)\n\t\t\t) {\n\t\t\t\t// We found the next expected event; increment\n\t\t\t\t++iExpectedEvent;\n\t\t\t}\n\t\t});\n\n\t\t// Remove the events so far; next call will just compare subsequent events from here\n\t\tthis.events = [];\n\n\t\t// Return the count of matched events.\n\t\treturn iExpectedEvent;\n\t}\n\n\t/**\n\t * Ensure the expected event is a strict subset of the actual event\n\t */\n\tprivate static eventsMatch(\n\t\tactual: ITelemetryBaseEvent,\n\t\texpected: Omit<ITelemetryBaseEvent, \"category\">,\n\t\tinlineDetailsProp: boolean,\n\t): boolean {\n\t\tconst { details, ...actualForMatching } = actual;\n\t\tlet detailsExpanded = { details };\n\t\t// \"details\" is used in a lot of telemetry logs to group a bunch of properties together and stringify them.\n\t\t// Some of the properties in the expected event may be inside \"details\". So, if inlineDetailsProp is true,\n\t\t// extract the properties from \"details\" in the actual event and inline them in the actual event.\n\t\tif (inlineDetailsProp && details !== undefined) {\n\t\t\tassert(\n\t\t\t\ttypeof details === \"string\",\n\t\t\t\t0x6c9 /* Details should a JSON stringified string if inlineDetailsProp is true */,\n\t\t\t);\n\t\t\tdetailsExpanded = JSON.parse(details);\n\t\t}\n\t\tconst actualExpanded: ITelemetryBaseEvent = { ...actualForMatching, ...detailsExpanded };\n\t\tconst masked = { ...actualExpanded, ...expected };\n\t\treturn JSON.stringify(masked) === JSON.stringify(actualExpanded);\n\t}\n}\n"]}
@@ -17,35 +17,38 @@ export declare class MockLogger extends TelemetryLogger implements ITelemetryLog
17
17
  * Search events logged since the last time matchEvents was called, looking for the given expected
18
18
  * events in order.
19
19
  * @param expectedEvents - events in order that are expected to appear in the recorded log.
20
+ * @param inlineDetailsProp - true if the "details" property in the actual event should be extracted and inlined.
20
21
  * These event objects may be subsets of the logged events.
21
22
  * Note: category is omitted from the type because it's usually uninteresting and tedious to type.
22
23
  */
23
- matchEvents(expectedEvents: Omit<ITelemetryBaseEvent, "category">[]): boolean;
24
+ matchEvents(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], inlineDetailsProp?: boolean): boolean;
24
25
  /** Asserts that matchEvents is true, and prints the actual/expected output if not */
25
- assertMatch(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string): void;
26
+ assertMatch(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string, inlineDetailsProp?: boolean): void;
26
27
  /**
27
28
  * Search events logged since the last time matchEvents was called, looking for any of the given
28
29
  * expected events.
29
30
  * @param expectedEvents - events that are expected to appear in the recorded log.
31
+ * @param inlineDetailsProp - true if the "details" property in the actual event should be extracted and inlined.
30
32
  * These event objects may be subsets of the logged events.
31
33
  * Note: category is omitted from the type because it's usually uninteresting and tedious to type.
32
34
  * @returns if any of the expected events is found.
33
35
  */
34
- matchAnyEvent(expectedEvents: Omit<ITelemetryBaseEvent, "category">[]): boolean;
36
+ matchAnyEvent(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], inlineDetailsProp?: boolean): boolean;
35
37
  /** Asserts that matchAnyEvent is true, and prints the actual/expected output if not */
36
- assertMatchAny(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string): void;
38
+ assertMatchAny(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string, inlineDetailsProp?: boolean): void;
37
39
  /**
38
40
  * Search events logged since the last time matchEvents was called, looking only for the given expected
39
41
  * events in order.
40
42
  * @param expectedEvents - events in order that are expected to be the only events in the recorded log.
43
+ * @param inlineDetailsProp - true if the "details" property in the actual event should be extracted and inlined.
41
44
  * These event objects may be subsets of the logged events.
42
45
  * Note: category is omitted from the type because it's usually uninteresting and tedious to type.
43
46
  */
44
- matchEventStrict(expectedEvents: Omit<ITelemetryBaseEvent, "category">[]): boolean;
47
+ matchEventStrict(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], inlineDetailsProp?: boolean): boolean;
45
48
  /** Asserts that matchEvents is true, and prints the actual/expected output if not */
46
- assertMatchStrict(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string): void;
49
+ assertMatchStrict(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string, inlineDetailsProp?: boolean): void;
47
50
  /** Asserts that matchAnyEvent is false for the given events, and prints the actual/expected output if not */
48
- assertMatchNone(disallowedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string): void;
51
+ assertMatchNone(disallowedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string, inlineDetailsProp?: boolean): void;
49
52
  private getMatchedEventsCount;
50
53
  /**
51
54
  * Ensure the expected event is a strict subset of the actual event
@@ -1 +1 @@
1
- {"version":3,"file":"mockLogger.d.ts","sourceRoot":"","sources":["../src/mockLogger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAC3F,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C;;;GAGG;AACH,qBAAa,UAAW,SAAQ,eAAgB,YAAW,gBAAgB;IAC1E,MAAM,EAAE,mBAAmB,EAAE,CAAM;;IAMnC,KAAK;IAIL,IAAI,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI;IAItC;;;;;;OAMG;IACH,WAAW,CAAC,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,GAAG,OAAO;IAO7E,qFAAqF;IACrF,WAAW,CAAC,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM;IAYrF;;;;;;;OAOG;IACH,aAAa,CAAC,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,GAAG,OAAO;IAK/E,uFAAuF;IACvF,cAAc,CAAC,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM;IAYxF;;;;;;OAMG;IACH,gBAAgB,CAAC,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,GAAG,OAAO;IAIlF,qFAAqF;IACrF,iBAAiB,CAAC,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM;IAY3F,6GAA6G;IAC7G,eAAe,CAAC,gBAAgB,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM;IAY3F,OAAO,CAAC,qBAAqB;IAmB7B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;CAO1B"}
1
+ {"version":3,"file":"mockLogger.d.ts","sourceRoot":"","sources":["../src/mockLogger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAE3F,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C;;;GAGG;AACH,qBAAa,UAAW,SAAQ,eAAgB,YAAW,gBAAgB;IAC1E,MAAM,EAAE,mBAAmB,EAAE,CAAM;;IAMnC,KAAK;IAIL,IAAI,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI;IAItC;;;;;;;OAOG;IACH,WAAW,CACV,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EACvD,iBAAiB,GAAE,OAAe,GAChC,OAAO;IAUV,qFAAqF;IACrF,WAAW,CACV,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EACvD,OAAO,CAAC,EAAE,MAAM,EAChB,iBAAiB,GAAE,OAAe;IAanC;;;;;;;;OAQG;IACH,aAAa,CACZ,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EACvD,iBAAiB,GAAE,OAAe,GAChC,OAAO;IAQV,uFAAuF;IACvF,cAAc,CACb,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EACvD,OAAO,CAAC,EAAE,MAAM,EAChB,iBAAiB,GAAE,OAAe;IAanC;;;;;;;OAOG;IACH,gBAAgB,CACf,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EACvD,iBAAiB,GAAE,OAAe,GAChC,OAAO;IAOV,qFAAqF;IACrF,iBAAiB,CAChB,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EACvD,OAAO,CAAC,EAAE,MAAM,EAChB,iBAAiB,GAAE,OAAe;IAanC,6GAA6G;IAC7G,eAAe,CACd,gBAAgB,EAAE,IAAI,CAAC,mBAAmB,EAAE,UAAU,CAAC,EAAE,EACzD,OAAO,CAAC,EAAE,MAAM,EAChB,iBAAiB,GAAE,OAAe;IAanC,OAAO,CAAC,qBAAqB;IAsB7B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;CAqB1B"}
package/lib/mockLogger.js CHANGED
@@ -2,6 +2,18 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
+ var __rest = (this && this.__rest) || function (s, e) {
6
+ var t = {};
7
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
8
+ t[p] = s[p];
9
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
10
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
11
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
12
+ t[p[i]] = s[p[i]];
13
+ }
14
+ return t;
15
+ };
16
+ import { assert } from "@fluidframework/common-utils";
5
17
  import { TelemetryLogger } from "./logger";
6
18
  /**
7
19
  * The MockLogger records events sent to it, and then can walk back over those events
@@ -22,19 +34,20 @@ export class MockLogger extends TelemetryLogger {
22
34
  * Search events logged since the last time matchEvents was called, looking for the given expected
23
35
  * events in order.
24
36
  * @param expectedEvents - events in order that are expected to appear in the recorded log.
37
+ * @param inlineDetailsProp - true if the "details" property in the actual event should be extracted and inlined.
25
38
  * These event objects may be subsets of the logged events.
26
39
  * Note: category is omitted from the type because it's usually uninteresting and tedious to type.
27
40
  */
28
- matchEvents(expectedEvents) {
29
- const matchedExpectedEventCount = this.getMatchedEventsCount(expectedEvents);
41
+ matchEvents(expectedEvents, inlineDetailsProp = false) {
42
+ const matchedExpectedEventCount = this.getMatchedEventsCount(expectedEvents, inlineDetailsProp);
30
43
  // How many expected events were left over? Hopefully none.
31
44
  const unmatchedExpectedEventCount = expectedEvents.length - matchedExpectedEventCount;
32
45
  return unmatchedExpectedEventCount === 0;
33
46
  }
34
47
  /** Asserts that matchEvents is true, and prints the actual/expected output if not */
35
- assertMatch(expectedEvents, message) {
48
+ assertMatch(expectedEvents, message, inlineDetailsProp = false) {
36
49
  const actualEvents = this.events;
37
- if (!this.matchEvents(expectedEvents)) {
50
+ if (!this.matchEvents(expectedEvents, inlineDetailsProp)) {
38
51
  throw new Error(`${message}
39
52
  expected:
40
53
  ${JSON.stringify(expectedEvents)}
@@ -47,18 +60,19 @@ ${JSON.stringify(actualEvents)}`);
47
60
  * Search events logged since the last time matchEvents was called, looking for any of the given
48
61
  * expected events.
49
62
  * @param expectedEvents - events that are expected to appear in the recorded log.
63
+ * @param inlineDetailsProp - true if the "details" property in the actual event should be extracted and inlined.
50
64
  * These event objects may be subsets of the logged events.
51
65
  * Note: category is omitted from the type because it's usually uninteresting and tedious to type.
52
66
  * @returns if any of the expected events is found.
53
67
  */
54
- matchAnyEvent(expectedEvents) {
55
- const matchedExpectedEventCount = this.getMatchedEventsCount(expectedEvents);
68
+ matchAnyEvent(expectedEvents, inlineDetailsProp = false) {
69
+ const matchedExpectedEventCount = this.getMatchedEventsCount(expectedEvents, inlineDetailsProp);
56
70
  return matchedExpectedEventCount > 0;
57
71
  }
58
72
  /** Asserts that matchAnyEvent is true, and prints the actual/expected output if not */
59
- assertMatchAny(expectedEvents, message) {
73
+ assertMatchAny(expectedEvents, message, inlineDetailsProp = false) {
60
74
  const actualEvents = this.events;
61
- if (!this.matchAnyEvent(expectedEvents)) {
75
+ if (!this.matchAnyEvent(expectedEvents, inlineDetailsProp)) {
62
76
  throw new Error(`${message}
63
77
  expected:
64
78
  ${JSON.stringify(expectedEvents)}
@@ -71,16 +85,18 @@ ${JSON.stringify(actualEvents)}`);
71
85
  * Search events logged since the last time matchEvents was called, looking only for the given expected
72
86
  * events in order.
73
87
  * @param expectedEvents - events in order that are expected to be the only events in the recorded log.
88
+ * @param inlineDetailsProp - true if the "details" property in the actual event should be extracted and inlined.
74
89
  * These event objects may be subsets of the logged events.
75
90
  * Note: category is omitted from the type because it's usually uninteresting and tedious to type.
76
91
  */
77
- matchEventStrict(expectedEvents) {
78
- return expectedEvents.length === this.events.length && this.matchEvents(expectedEvents);
92
+ matchEventStrict(expectedEvents, inlineDetailsProp = false) {
93
+ return (expectedEvents.length === this.events.length &&
94
+ this.matchEvents(expectedEvents, inlineDetailsProp));
79
95
  }
80
96
  /** Asserts that matchEvents is true, and prints the actual/expected output if not */
81
- assertMatchStrict(expectedEvents, message) {
97
+ assertMatchStrict(expectedEvents, message, inlineDetailsProp = false) {
82
98
  const actualEvents = this.events;
83
- if (!this.matchEventStrict(expectedEvents)) {
99
+ if (!this.matchEventStrict(expectedEvents, inlineDetailsProp)) {
84
100
  throw new Error(`${message}
85
101
  expected:
86
102
  ${JSON.stringify(expectedEvents)}
@@ -90,9 +106,9 @@ ${JSON.stringify(actualEvents)}`);
90
106
  }
91
107
  }
92
108
  /** Asserts that matchAnyEvent is false for the given events, and prints the actual/expected output if not */
93
- assertMatchNone(disallowedEvents, message) {
109
+ assertMatchNone(disallowedEvents, message, inlineDetailsProp = false) {
94
110
  const actualEvents = this.events;
95
- if (this.matchAnyEvent(disallowedEvents)) {
111
+ if (this.matchAnyEvent(disallowedEvents, inlineDetailsProp)) {
96
112
  throw new Error(`${message}
97
113
  disallowed events:
98
114
  ${JSON.stringify(disallowedEvents)}
@@ -101,11 +117,11 @@ actual:
101
117
  ${JSON.stringify(actualEvents)}`);
102
118
  }
103
119
  }
104
- getMatchedEventsCount(expectedEvents) {
120
+ getMatchedEventsCount(expectedEvents, inlineDetailsProp) {
105
121
  let iExpectedEvent = 0;
106
122
  this.events.forEach((event) => {
107
123
  if (iExpectedEvent < expectedEvents.length &&
108
- MockLogger.eventsMatch(event, expectedEvents[iExpectedEvent])) {
124
+ MockLogger.eventsMatch(event, expectedEvents[iExpectedEvent], inlineDetailsProp)) {
109
125
  // We found the next expected event; increment
110
126
  ++iExpectedEvent;
111
127
  }
@@ -118,9 +134,19 @@ ${JSON.stringify(actualEvents)}`);
118
134
  /**
119
135
  * Ensure the expected event is a strict subset of the actual event
120
136
  */
121
- static eventsMatch(actual, expected) {
122
- const masked = Object.assign(Object.assign({}, actual), expected);
123
- return JSON.stringify(masked) === JSON.stringify(actual);
137
+ static eventsMatch(actual, expected, inlineDetailsProp) {
138
+ const { details } = actual, actualForMatching = __rest(actual, ["details"]);
139
+ let detailsExpanded = { details };
140
+ // "details" is used in a lot of telemetry logs to group a bunch of properties together and stringify them.
141
+ // Some of the properties in the expected event may be inside "details". So, if inlineDetailsProp is true,
142
+ // extract the properties from "details" in the actual event and inline them in the actual event.
143
+ if (inlineDetailsProp && details !== undefined) {
144
+ assert(typeof details === "string", 0x6c9 /* Details should a JSON stringified string if inlineDetailsProp is true */);
145
+ detailsExpanded = JSON.parse(details);
146
+ }
147
+ const actualExpanded = Object.assign(Object.assign({}, actualForMatching), detailsExpanded);
148
+ const masked = Object.assign(Object.assign({}, actualExpanded), expected);
149
+ return JSON.stringify(masked) === JSON.stringify(actualExpanded);
124
150
  }
125
151
  }
126
152
  //# sourceMappingURL=mockLogger.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mockLogger.js","sourceRoot":"","sources":["../src/mockLogger.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLogger, ITelemetryBaseEvent } from \"@fluidframework/common-definitions\";\nimport { TelemetryLogger } from \"./logger\";\n\n/**\n * The MockLogger records events sent to it, and then can walk back over those events\n * searching for a set of expected events to match against the logged events.\n */\nexport class MockLogger extends TelemetryLogger implements ITelemetryLogger {\n\tevents: ITelemetryBaseEvent[] = [];\n\n\tconstructor() {\n\t\tsuper();\n\t}\n\n\tclear() {\n\t\tthis.events = [];\n\t}\n\n\tsend(event: ITelemetryBaseEvent): void {\n\t\tthis.events.push(event);\n\t}\n\n\t/**\n\t * Search events logged since the last time matchEvents was called, looking for the given expected\n\t * events in order.\n\t * @param expectedEvents - events in order that are expected to appear in the recorded log.\n\t * These event objects may be subsets of the logged events.\n\t * Note: category is omitted from the type because it's usually uninteresting and tedious to type.\n\t */\n\tmatchEvents(expectedEvents: Omit<ITelemetryBaseEvent, \"category\">[]): boolean {\n\t\tconst matchedExpectedEventCount = this.getMatchedEventsCount(expectedEvents);\n\t\t// How many expected events were left over? Hopefully none.\n\t\tconst unmatchedExpectedEventCount = expectedEvents.length - matchedExpectedEventCount;\n\t\treturn unmatchedExpectedEventCount === 0;\n\t}\n\n\t/** Asserts that matchEvents is true, and prints the actual/expected output if not */\n\tassertMatch(expectedEvents: Omit<ITelemetryBaseEvent, \"category\">[], message?: string) {\n\t\tconst actualEvents = this.events;\n\t\tif (!this.matchEvents(expectedEvents)) {\n\t\t\tthrow new Error(`${message}\nexpected:\n${JSON.stringify(expectedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\t/**\n\t * Search events logged since the last time matchEvents was called, looking for any of the given\n\t * expected events.\n\t * @param expectedEvents - events that are expected to appear in the recorded log.\n\t * These event objects may be subsets of the logged events.\n\t * Note: category is omitted from the type because it's usually uninteresting and tedious to type.\n\t * @returns if any of the expected events is found.\n\t */\n\tmatchAnyEvent(expectedEvents: Omit<ITelemetryBaseEvent, \"category\">[]): boolean {\n\t\tconst matchedExpectedEventCount = this.getMatchedEventsCount(expectedEvents);\n\t\treturn matchedExpectedEventCount > 0;\n\t}\n\n\t/** Asserts that matchAnyEvent is true, and prints the actual/expected output if not */\n\tassertMatchAny(expectedEvents: Omit<ITelemetryBaseEvent, \"category\">[], message?: string) {\n\t\tconst actualEvents = this.events;\n\t\tif (!this.matchAnyEvent(expectedEvents)) {\n\t\t\tthrow new Error(`${message}\nexpected:\n${JSON.stringify(expectedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\t/**\n\t * Search events logged since the last time matchEvents was called, looking only for the given expected\n\t * events in order.\n\t * @param expectedEvents - events in order that are expected to be the only events in the recorded log.\n\t * These event objects may be subsets of the logged events.\n\t * Note: category is omitted from the type because it's usually uninteresting and tedious to type.\n\t */\n\tmatchEventStrict(expectedEvents: Omit<ITelemetryBaseEvent, \"category\">[]): boolean {\n\t\treturn expectedEvents.length === this.events.length && this.matchEvents(expectedEvents);\n\t}\n\n\t/** Asserts that matchEvents is true, and prints the actual/expected output if not */\n\tassertMatchStrict(expectedEvents: Omit<ITelemetryBaseEvent, \"category\">[], message?: string) {\n\t\tconst actualEvents = this.events;\n\t\tif (!this.matchEventStrict(expectedEvents)) {\n\t\t\tthrow new Error(`${message}\nexpected:\n${JSON.stringify(expectedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\t/** Asserts that matchAnyEvent is false for the given events, and prints the actual/expected output if not */\n\tassertMatchNone(disallowedEvents: Omit<ITelemetryBaseEvent, \"category\">[], message?: string) {\n\t\tconst actualEvents = this.events;\n\t\tif (this.matchAnyEvent(disallowedEvents)) {\n\t\t\tthrow new Error(`${message}\ndisallowed events:\n${JSON.stringify(disallowedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\tprivate getMatchedEventsCount(expectedEvents: Omit<ITelemetryBaseEvent, \"category\">[]): number {\n\t\tlet iExpectedEvent = 0;\n\t\tthis.events.forEach((event) => {\n\t\t\tif (\n\t\t\t\tiExpectedEvent < expectedEvents.length &&\n\t\t\t\tMockLogger.eventsMatch(event, expectedEvents[iExpectedEvent])\n\t\t\t) {\n\t\t\t\t// We found the next expected event; increment\n\t\t\t\t++iExpectedEvent;\n\t\t\t}\n\t\t});\n\n\t\t// Remove the events so far; next call will just compare subsequent events from here\n\t\tthis.events = [];\n\n\t\t// Return the count of matched events.\n\t\treturn iExpectedEvent;\n\t}\n\n\t/**\n\t * Ensure the expected event is a strict subset of the actual event\n\t */\n\tprivate static eventsMatch(\n\t\tactual: ITelemetryBaseEvent,\n\t\texpected: Omit<ITelemetryBaseEvent, \"category\">,\n\t): boolean {\n\t\tconst masked = { ...actual, ...expected };\n\t\treturn JSON.stringify(masked) === JSON.stringify(actual);\n\t}\n}\n"]}
1
+ {"version":3,"file":"mockLogger.js","sourceRoot":"","sources":["../src/mockLogger.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryLogger, ITelemetryBaseEvent } from \"@fluidframework/common-definitions\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { TelemetryLogger } from \"./logger\";\n\n/**\n * The MockLogger records events sent to it, and then can walk back over those events\n * searching for a set of expected events to match against the logged events.\n */\nexport class MockLogger extends TelemetryLogger implements ITelemetryLogger {\n\tevents: ITelemetryBaseEvent[] = [];\n\n\tconstructor() {\n\t\tsuper();\n\t}\n\n\tclear() {\n\t\tthis.events = [];\n\t}\n\n\tsend(event: ITelemetryBaseEvent): void {\n\t\tthis.events.push(event);\n\t}\n\n\t/**\n\t * Search events logged since the last time matchEvents was called, looking for the given expected\n\t * events in order.\n\t * @param expectedEvents - events in order that are expected to appear in the recorded log.\n\t * @param inlineDetailsProp - true if the \"details\" property in the actual event should be extracted and inlined.\n\t * These event objects may be subsets of the logged events.\n\t * Note: category is omitted from the type because it's usually uninteresting and tedious to type.\n\t */\n\tmatchEvents(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tinlineDetailsProp: boolean = false,\n\t): boolean {\n\t\tconst matchedExpectedEventCount = this.getMatchedEventsCount(\n\t\t\texpectedEvents,\n\t\t\tinlineDetailsProp,\n\t\t);\n\t\t// How many expected events were left over? Hopefully none.\n\t\tconst unmatchedExpectedEventCount = expectedEvents.length - matchedExpectedEventCount;\n\t\treturn unmatchedExpectedEventCount === 0;\n\t}\n\n\t/** Asserts that matchEvents is true, and prints the actual/expected output if not */\n\tassertMatch(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tmessage?: string,\n\t\tinlineDetailsProp: boolean = false,\n\t) {\n\t\tconst actualEvents = this.events;\n\t\tif (!this.matchEvents(expectedEvents, inlineDetailsProp)) {\n\t\t\tthrow new Error(`${message}\nexpected:\n${JSON.stringify(expectedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\t/**\n\t * Search events logged since the last time matchEvents was called, looking for any of the given\n\t * expected events.\n\t * @param expectedEvents - events that are expected to appear in the recorded log.\n\t * @param inlineDetailsProp - true if the \"details\" property in the actual event should be extracted and inlined.\n\t * These event objects may be subsets of the logged events.\n\t * Note: category is omitted from the type because it's usually uninteresting and tedious to type.\n\t * @returns if any of the expected events is found.\n\t */\n\tmatchAnyEvent(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tinlineDetailsProp: boolean = false,\n\t): boolean {\n\t\tconst matchedExpectedEventCount = this.getMatchedEventsCount(\n\t\t\texpectedEvents,\n\t\t\tinlineDetailsProp,\n\t\t);\n\t\treturn matchedExpectedEventCount > 0;\n\t}\n\n\t/** Asserts that matchAnyEvent is true, and prints the actual/expected output if not */\n\tassertMatchAny(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tmessage?: string,\n\t\tinlineDetailsProp: boolean = false,\n\t) {\n\t\tconst actualEvents = this.events;\n\t\tif (!this.matchAnyEvent(expectedEvents, inlineDetailsProp)) {\n\t\t\tthrow new Error(`${message}\nexpected:\n${JSON.stringify(expectedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\t/**\n\t * Search events logged since the last time matchEvents was called, looking only for the given expected\n\t * events in order.\n\t * @param expectedEvents - events in order that are expected to be the only events in the recorded log.\n\t * @param inlineDetailsProp - true if the \"details\" property in the actual event should be extracted and inlined.\n\t * These event objects may be subsets of the logged events.\n\t * Note: category is omitted from the type because it's usually uninteresting and tedious to type.\n\t */\n\tmatchEventStrict(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tinlineDetailsProp: boolean = false,\n\t): boolean {\n\t\treturn (\n\t\t\texpectedEvents.length === this.events.length &&\n\t\t\tthis.matchEvents(expectedEvents, inlineDetailsProp)\n\t\t);\n\t}\n\n\t/** Asserts that matchEvents is true, and prints the actual/expected output if not */\n\tassertMatchStrict(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tmessage?: string,\n\t\tinlineDetailsProp: boolean = false,\n\t) {\n\t\tconst actualEvents = this.events;\n\t\tif (!this.matchEventStrict(expectedEvents, inlineDetailsProp)) {\n\t\t\tthrow new Error(`${message}\nexpected:\n${JSON.stringify(expectedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\t/** Asserts that matchAnyEvent is false for the given events, and prints the actual/expected output if not */\n\tassertMatchNone(\n\t\tdisallowedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tmessage?: string,\n\t\tinlineDetailsProp: boolean = false,\n\t) {\n\t\tconst actualEvents = this.events;\n\t\tif (this.matchAnyEvent(disallowedEvents, inlineDetailsProp)) {\n\t\t\tthrow new Error(`${message}\ndisallowed events:\n${JSON.stringify(disallowedEvents)}\n\nactual:\n${JSON.stringify(actualEvents)}`);\n\t\t}\n\t}\n\n\tprivate getMatchedEventsCount(\n\t\texpectedEvents: Omit<ITelemetryBaseEvent, \"category\">[],\n\t\tinlineDetailsProp: boolean,\n\t): number {\n\t\tlet iExpectedEvent = 0;\n\t\tthis.events.forEach((event) => {\n\t\t\tif (\n\t\t\t\tiExpectedEvent < expectedEvents.length &&\n\t\t\t\tMockLogger.eventsMatch(event, expectedEvents[iExpectedEvent], inlineDetailsProp)\n\t\t\t) {\n\t\t\t\t// We found the next expected event; increment\n\t\t\t\t++iExpectedEvent;\n\t\t\t}\n\t\t});\n\n\t\t// Remove the events so far; next call will just compare subsequent events from here\n\t\tthis.events = [];\n\n\t\t// Return the count of matched events.\n\t\treturn iExpectedEvent;\n\t}\n\n\t/**\n\t * Ensure the expected event is a strict subset of the actual event\n\t */\n\tprivate static eventsMatch(\n\t\tactual: ITelemetryBaseEvent,\n\t\texpected: Omit<ITelemetryBaseEvent, \"category\">,\n\t\tinlineDetailsProp: boolean,\n\t): boolean {\n\t\tconst { details, ...actualForMatching } = actual;\n\t\tlet detailsExpanded = { details };\n\t\t// \"details\" is used in a lot of telemetry logs to group a bunch of properties together and stringify them.\n\t\t// Some of the properties in the expected event may be inside \"details\". So, if inlineDetailsProp is true,\n\t\t// extract the properties from \"details\" in the actual event and inline them in the actual event.\n\t\tif (inlineDetailsProp && details !== undefined) {\n\t\t\tassert(\n\t\t\t\ttypeof details === \"string\",\n\t\t\t\t0x6c9 /* Details should a JSON stringified string if inlineDetailsProp is true */,\n\t\t\t);\n\t\t\tdetailsExpanded = JSON.parse(details);\n\t\t}\n\t\tconst actualExpanded: ITelemetryBaseEvent = { ...actualForMatching, ...detailsExpanded };\n\t\tconst masked = { ...actualExpanded, ...expected };\n\t\treturn JSON.stringify(masked) === JSON.stringify(actualExpanded);\n\t}\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/telemetry-utils",
3
- "version": "2.0.0-internal.4.2.1",
3
+ "version": "2.0.0-internal.4.4.0",
4
4
  "description": "Collection of telemetry relates utilities for Fluid",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -50,7 +50,7 @@
50
50
  "@fluidframework/build-common": "^1.1.0",
51
51
  "@fluidframework/build-tools": "^0.17.0",
52
52
  "@fluidframework/eslint-config-fluid": "^2.0.0",
53
- "@fluidframework/mocha-test-setup": ">=2.0.0-internal.4.2.1 <2.0.0-internal.4.3.0",
53
+ "@fluidframework/mocha-test-setup": ">=2.0.0-internal.4.4.0 <2.0.0-internal.4.5.0",
54
54
  "@fluidframework/telemetry-utils-previous": "npm:@fluidframework/telemetry-utils@2.0.0-internal.4.1.0",
55
55
  "@microsoft/api-extractor": "^7.34.4",
56
56
  "@types/debug": "^4.1.5",
@@ -76,14 +76,13 @@
76
76
  "broken": {}
77
77
  },
78
78
  "scripts": {
79
- "build": "npm run build:genver && concurrently npm:build:compile npm:lint && npm run build:docs",
79
+ "build": "concurrently npm:build:compile npm:lint && npm run build:docs",
80
80
  "build:commonjs": "npm run tsc && npm run typetests:gen && npm run build:test",
81
81
  "build:compile": "concurrently npm:build:commonjs npm:build:esnext",
82
82
  "build:docs": "api-extractor run --local --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/doc-models/* ../../../_api-extractor-temp/",
83
83
  "build:esnext": "tsc --project ./tsconfig.esnext.json",
84
84
  "build:full": "npm run build",
85
85
  "build:full:compile": "npm run build:compile",
86
- "build:genver": "gen-version",
87
86
  "build:test": "tsc --project ./src/test/tsconfig.json",
88
87
  "bump-version": "npm version minor --no-push --no-git-tag-version && npm run build:genver",
89
88
  "ci:build:docs": "api-extractor run --typescript-compiler-folder ../../../node_modules/typescript && copyfiles -u 1 ./_api-extractor-temp/* ../../../_api-extractor-temp/",
package/src/mockLogger.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  import { ITelemetryLogger, ITelemetryBaseEvent } from "@fluidframework/common-definitions";
7
+ import { assert } from "@fluidframework/common-utils";
7
8
  import { TelemetryLogger } from "./logger";
8
9
 
9
10
  /**
@@ -29,20 +30,31 @@ export class MockLogger extends TelemetryLogger implements ITelemetryLogger {
29
30
  * Search events logged since the last time matchEvents was called, looking for the given expected
30
31
  * events in order.
31
32
  * @param expectedEvents - events in order that are expected to appear in the recorded log.
33
+ * @param inlineDetailsProp - true if the "details" property in the actual event should be extracted and inlined.
32
34
  * These event objects may be subsets of the logged events.
33
35
  * Note: category is omitted from the type because it's usually uninteresting and tedious to type.
34
36
  */
35
- matchEvents(expectedEvents: Omit<ITelemetryBaseEvent, "category">[]): boolean {
36
- const matchedExpectedEventCount = this.getMatchedEventsCount(expectedEvents);
37
+ matchEvents(
38
+ expectedEvents: Omit<ITelemetryBaseEvent, "category">[],
39
+ inlineDetailsProp: boolean = false,
40
+ ): boolean {
41
+ const matchedExpectedEventCount = this.getMatchedEventsCount(
42
+ expectedEvents,
43
+ inlineDetailsProp,
44
+ );
37
45
  // How many expected events were left over? Hopefully none.
38
46
  const unmatchedExpectedEventCount = expectedEvents.length - matchedExpectedEventCount;
39
47
  return unmatchedExpectedEventCount === 0;
40
48
  }
41
49
 
42
50
  /** Asserts that matchEvents is true, and prints the actual/expected output if not */
43
- assertMatch(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string) {
51
+ assertMatch(
52
+ expectedEvents: Omit<ITelemetryBaseEvent, "category">[],
53
+ message?: string,
54
+ inlineDetailsProp: boolean = false,
55
+ ) {
44
56
  const actualEvents = this.events;
45
- if (!this.matchEvents(expectedEvents)) {
57
+ if (!this.matchEvents(expectedEvents, inlineDetailsProp)) {
46
58
  throw new Error(`${message}
47
59
  expected:
48
60
  ${JSON.stringify(expectedEvents)}
@@ -56,19 +68,30 @@ ${JSON.stringify(actualEvents)}`);
56
68
  * Search events logged since the last time matchEvents was called, looking for any of the given
57
69
  * expected events.
58
70
  * @param expectedEvents - events that are expected to appear in the recorded log.
71
+ * @param inlineDetailsProp - true if the "details" property in the actual event should be extracted and inlined.
59
72
  * These event objects may be subsets of the logged events.
60
73
  * Note: category is omitted from the type because it's usually uninteresting and tedious to type.
61
74
  * @returns if any of the expected events is found.
62
75
  */
63
- matchAnyEvent(expectedEvents: Omit<ITelemetryBaseEvent, "category">[]): boolean {
64
- const matchedExpectedEventCount = this.getMatchedEventsCount(expectedEvents);
76
+ matchAnyEvent(
77
+ expectedEvents: Omit<ITelemetryBaseEvent, "category">[],
78
+ inlineDetailsProp: boolean = false,
79
+ ): boolean {
80
+ const matchedExpectedEventCount = this.getMatchedEventsCount(
81
+ expectedEvents,
82
+ inlineDetailsProp,
83
+ );
65
84
  return matchedExpectedEventCount > 0;
66
85
  }
67
86
 
68
87
  /** Asserts that matchAnyEvent is true, and prints the actual/expected output if not */
69
- assertMatchAny(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string) {
88
+ assertMatchAny(
89
+ expectedEvents: Omit<ITelemetryBaseEvent, "category">[],
90
+ message?: string,
91
+ inlineDetailsProp: boolean = false,
92
+ ) {
70
93
  const actualEvents = this.events;
71
- if (!this.matchAnyEvent(expectedEvents)) {
94
+ if (!this.matchAnyEvent(expectedEvents, inlineDetailsProp)) {
72
95
  throw new Error(`${message}
73
96
  expected:
74
97
  ${JSON.stringify(expectedEvents)}
@@ -82,17 +105,28 @@ ${JSON.stringify(actualEvents)}`);
82
105
  * Search events logged since the last time matchEvents was called, looking only for the given expected
83
106
  * events in order.
84
107
  * @param expectedEvents - events in order that are expected to be the only events in the recorded log.
108
+ * @param inlineDetailsProp - true if the "details" property in the actual event should be extracted and inlined.
85
109
  * These event objects may be subsets of the logged events.
86
110
  * Note: category is omitted from the type because it's usually uninteresting and tedious to type.
87
111
  */
88
- matchEventStrict(expectedEvents: Omit<ITelemetryBaseEvent, "category">[]): boolean {
89
- return expectedEvents.length === this.events.length && this.matchEvents(expectedEvents);
112
+ matchEventStrict(
113
+ expectedEvents: Omit<ITelemetryBaseEvent, "category">[],
114
+ inlineDetailsProp: boolean = false,
115
+ ): boolean {
116
+ return (
117
+ expectedEvents.length === this.events.length &&
118
+ this.matchEvents(expectedEvents, inlineDetailsProp)
119
+ );
90
120
  }
91
121
 
92
122
  /** Asserts that matchEvents is true, and prints the actual/expected output if not */
93
- assertMatchStrict(expectedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string) {
123
+ assertMatchStrict(
124
+ expectedEvents: Omit<ITelemetryBaseEvent, "category">[],
125
+ message?: string,
126
+ inlineDetailsProp: boolean = false,
127
+ ) {
94
128
  const actualEvents = this.events;
95
- if (!this.matchEventStrict(expectedEvents)) {
129
+ if (!this.matchEventStrict(expectedEvents, inlineDetailsProp)) {
96
130
  throw new Error(`${message}
97
131
  expected:
98
132
  ${JSON.stringify(expectedEvents)}
@@ -103,9 +137,13 @@ ${JSON.stringify(actualEvents)}`);
103
137
  }
104
138
 
105
139
  /** Asserts that matchAnyEvent is false for the given events, and prints the actual/expected output if not */
106
- assertMatchNone(disallowedEvents: Omit<ITelemetryBaseEvent, "category">[], message?: string) {
140
+ assertMatchNone(
141
+ disallowedEvents: Omit<ITelemetryBaseEvent, "category">[],
142
+ message?: string,
143
+ inlineDetailsProp: boolean = false,
144
+ ) {
107
145
  const actualEvents = this.events;
108
- if (this.matchAnyEvent(disallowedEvents)) {
146
+ if (this.matchAnyEvent(disallowedEvents, inlineDetailsProp)) {
109
147
  throw new Error(`${message}
110
148
  disallowed events:
111
149
  ${JSON.stringify(disallowedEvents)}
@@ -115,12 +153,15 @@ ${JSON.stringify(actualEvents)}`);
115
153
  }
116
154
  }
117
155
 
118
- private getMatchedEventsCount(expectedEvents: Omit<ITelemetryBaseEvent, "category">[]): number {
156
+ private getMatchedEventsCount(
157
+ expectedEvents: Omit<ITelemetryBaseEvent, "category">[],
158
+ inlineDetailsProp: boolean,
159
+ ): number {
119
160
  let iExpectedEvent = 0;
120
161
  this.events.forEach((event) => {
121
162
  if (
122
163
  iExpectedEvent < expectedEvents.length &&
123
- MockLogger.eventsMatch(event, expectedEvents[iExpectedEvent])
164
+ MockLogger.eventsMatch(event, expectedEvents[iExpectedEvent], inlineDetailsProp)
124
165
  ) {
125
166
  // We found the next expected event; increment
126
167
  ++iExpectedEvent;
@@ -140,8 +181,22 @@ ${JSON.stringify(actualEvents)}`);
140
181
  private static eventsMatch(
141
182
  actual: ITelemetryBaseEvent,
142
183
  expected: Omit<ITelemetryBaseEvent, "category">,
184
+ inlineDetailsProp: boolean,
143
185
  ): boolean {
144
- const masked = { ...actual, ...expected };
145
- return JSON.stringify(masked) === JSON.stringify(actual);
186
+ const { details, ...actualForMatching } = actual;
187
+ let detailsExpanded = { details };
188
+ // "details" is used in a lot of telemetry logs to group a bunch of properties together and stringify them.
189
+ // Some of the properties in the expected event may be inside "details". So, if inlineDetailsProp is true,
190
+ // extract the properties from "details" in the actual event and inline them in the actual event.
191
+ if (inlineDetailsProp && details !== undefined) {
192
+ assert(
193
+ typeof details === "string",
194
+ 0x6c9 /* Details should a JSON stringified string if inlineDetailsProp is true */,
195
+ );
196
+ detailsExpanded = JSON.parse(details);
197
+ }
198
+ const actualExpanded: ITelemetryBaseEvent = { ...actualForMatching, ...detailsExpanded };
199
+ const masked = { ...actualExpanded, ...expected };
200
+ return JSON.stringify(masked) === JSON.stringify(actualExpanded);
146
201
  }
147
202
  }
@@ -1,9 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- *
5
- * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
- */
7
- export declare const pkgName = "@fluidframework/telemetry-utils";
8
- export declare const pkgVersion = "2.0.0-internal.4.2.1";
9
- //# sourceMappingURL=packageVersion.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,oCAAoC,CAAC;AACzD,eAAO,MAAM,UAAU,yBAAyB,CAAC"}
@@ -1,12 +0,0 @@
1
- "use strict";
2
- /*!
3
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
4
- * Licensed under the MIT License.
5
- *
6
- * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
7
- */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.pkgVersion = exports.pkgName = void 0;
10
- exports.pkgName = "@fluidframework/telemetry-utils";
11
- exports.pkgVersion = "2.0.0-internal.4.2.1";
12
- //# sourceMappingURL=packageVersion.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,iCAAiC,CAAC;AAC5C,QAAA,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/telemetry-utils\";\nexport const pkgVersion = \"2.0.0-internal.4.2.1\";\n"]}
@@ -1,9 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- *
5
- * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
- */
7
- export declare const pkgName = "@fluidframework/telemetry-utils";
8
- export declare const pkgVersion = "2.0.0-internal.4.2.1";
9
- //# sourceMappingURL=packageVersion.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"packageVersion.d.ts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,oCAAoC,CAAC;AACzD,eAAO,MAAM,UAAU,yBAAyB,CAAC"}
@@ -1,9 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- *
5
- * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
- */
7
- export const pkgName = "@fluidframework/telemetry-utils";
8
- export const pkgVersion = "2.0.0-internal.4.2.1";
9
- //# sourceMappingURL=packageVersion.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,iCAAiC,CAAC;AACzD,MAAM,CAAC,MAAM,UAAU,GAAG,sBAAsB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/telemetry-utils\";\nexport const pkgVersion = \"2.0.0-internal.4.2.1\";\n"]}
@@ -1,9 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- *
5
- * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
6
- */
7
-
8
- export const pkgName = "@fluidframework/telemetry-utils";
9
- export const pkgVersion = "2.0.0-internal.4.2.1";