-
-
Notifications
You must be signed in to change notification settings - Fork 9.9k
Expand file tree
/
Copy pathevent-log-checker.ts
More file actions
157 lines (131 loc) · 5.14 KB
/
event-log-checker.ts
File metadata and controls
157 lines (131 loc) · 5.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import assert from 'assert';
import picocolors from 'picocolors';
import versions from '../code/core/src/common/versions';
import { oneWayHash } from '../code/core/src/telemetry/one-way-hash';
import { allTemplates } from '../code/lib/cli-storybook/src/sandbox-templates';
import { esMain } from './utils/esmain';
const PORT = process.env.PORT || 6007;
type EventType = 'build' | 'test-run';
type EventDefinition = {
noBoot?: boolean;
};
const eventTypeDefinitions: Record<EventType, EventDefinition> = {
build: {},
'test-run': { noBoot: true },
};
async function run() {
const [eventType, templateName] = process.argv.slice(2);
let testMessage = '';
// very simple jest-like test fn for better error readability
const test = (message: string, fn: () => void) => {
testMessage = message;
fn();
};
try {
if (!eventType || !templateName) {
throw new Error(
`Need eventType and templateName; call with ./event-log-checker <eventType> <templateName>`
);
}
const definition = eventTypeDefinitions[eventType as EventType];
if (!definition) {
throw new Error(`Unexpected eventType '${eventType}'`);
}
const template = allTemplates[templateName as keyof typeof allTemplates];
if (!template) {
throw new Error(`Unexpected template '${templateName}'`);
}
const events: any = await (await fetch(`http://localhost:${PORT}/event-log`)).json();
const eventsWithoutMocks = events.filter((e: any) => e.eventType !== 'mocking');
if (definition.noBoot) {
test('Should log 1 event', () => {
assert.equal(
eventsWithoutMocks.length,
1,
`Expected 1 event but received ${
eventsWithoutMocks.length
} instead. The following events were logged: ${JSON.stringify(events)}`
);
});
} else {
// two or three events are logged, depending on whether the template has a `vitest-integration` task
test('Should log 2 or 3 events', () => {
assert.ok(
eventsWithoutMocks.length === 2 || eventsWithoutMocks.length === 3,
`Expected 2 or 3 events but received ${
eventsWithoutMocks.length
} instead. The following events were logged: ${JSON.stringify(eventsWithoutMocks)}`
);
});
}
if (eventsWithoutMocks.length === 0) {
throw new Error('No events were logged');
}
const [bootEvent, mainEvent] = definition.noBoot
? [null, eventsWithoutMocks[0]]
: eventsWithoutMocks;
const storybookVersion = versions.storybook;
if (bootEvent) {
test('boot event should have cliVersion and storybookVersion in context', () => {
assert.equal(bootEvent.context.cliVersion, storybookVersion);
assert.equal(bootEvent.context.storybookVersion, storybookVersion);
});
}
test(`main event should have storybookVersion in context`, () => {
assert.equal(mainEvent.context.storybookVersion, storybookVersion);
});
test(`main event should have storybookVersion in metadata`, () => {
assert.equal(mainEvent.metadata.storybookVersion, storybookVersion);
});
if (bootEvent) {
test(`Should log a boot event with a payload of type ${eventType}`, () => {
assert.equal(bootEvent.eventType, 'boot');
assert.equal(bootEvent.payload?.eventType, eventType);
});
}
test(`main event should be ${eventType} and contain correct id and session id`, () => {
assert.equal(mainEvent.eventType, eventType);
assert.ok(typeof mainEvent.eventId === 'string');
assert.ok(typeof mainEvent.sessionId === 'string');
if (bootEvent) {
assert.notEqual(mainEvent.eventId, bootEvent.eventId);
assert.equal(mainEvent.sessionId, bootEvent.sessionId);
}
});
test(`main event should contain anonymousId properly hashed`, () => {
const templateDir = `sandbox/${templateName.replace('/', '-')}`;
const unhashedId = `github.com/storybookjs/storybook.git${templateDir}`;
assert.equal(mainEvent.context.anonymousId, oneWayHash(unhashedId));
});
// Not sure if it's worth testing this as we are not providing this value in CI.
// For now the code is commented out so we can discuss later.
// test(`main event should contain a userSince value`, () => {
// assert.ok(typeof mainEvent.metadata.userSince === 'number');
// });
const {
expected: { renderer, builder, framework },
} = template;
test(`main event should contain correct packages from template's "expected" field`, () => {
assert.equal(mainEvent.metadata.renderer, renderer);
assert.equal(mainEvent.metadata.builder, builder);
assert.equal(mainEvent.metadata.framework.name, framework);
});
} catch (err) {
if (err instanceof assert.AssertionError) {
console.log(`Assertions failed for ${picocolors.bold(templateName)}\n`);
console.log(picocolors.bold(picocolors.red(`✕ ${testMessage}:`)));
console.log(err);
process.exit(1);
}
throw err;
}
}
export {};
if (esMain(import.meta.url)) {
run()
.then(() => process.exit(0))
.catch((err) => {
console.log(err);
process.exit(1);
});
}