Skip to content

Commit 3c69550

Browse files
author
Sébastien Henau
committed
tests: add flareVue and error boundary tests
1 parent c44c06c commit 3c69550

File tree

2 files changed

+67
-4
lines changed

2 files changed

+67
-4
lines changed

packages/vue/tests/FlareErrorBoundary.test.ts

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,20 @@ const ThrowingComponent = defineComponent({
2525
},
2626
});
2727

28+
const ThrowingComponentWithProps = defineComponent({
29+
name: 'ThrowingComponentWithProps',
30+
props: {
31+
userId: { type: Number, required: true },
32+
name: { type: String, required: true },
33+
},
34+
setup() {
35+
throw testError;
36+
},
37+
render() {
38+
return h('div', 'should not render');
39+
},
40+
});
41+
2842
describe('FlareErrorBoundary', () => {
2943
let consoleWarnSpy: ReturnType<typeof vi.spyOn>;
3044

@@ -62,7 +76,7 @@ describe('FlareErrorBoundary', () => {
6276
expect(mockReport.mock.calls[0][0]).toBe(testError);
6377
});
6478

65-
test('passes vue context with info, componentName, componentHierarchy, and componentHierarchyFrames', async () => {
79+
test('passes vue context with info, componentName, componentProps, componentHierarchy, and componentHierarchyFrames', async () => {
6680
mount(FlareErrorBoundary, {
6781
slots: {
6882
default: () => h(ThrowingComponent),
@@ -75,6 +89,7 @@ describe('FlareErrorBoundary', () => {
7589
const context = mockReport.mock.calls[0][1];
7690
expect(context.vue.info).toEqual(expect.any(String));
7791
expect(context.vue.componentName).toBe('ThrowingComponent');
92+
expect(context.vue.componentProps).toBeDefined();
7893
expect(context.vue.componentHierarchy).toBeInstanceOf(Array);
7994
expect(context.vue.componentHierarchy).toContain('ThrowingComponent');
8095
expect(context.vue.componentHierarchyFrames).toBeInstanceOf(Array);
@@ -83,6 +98,38 @@ describe('FlareErrorBoundary', () => {
8398
expect(context.vue.componentHierarchyFrames[0]).toHaveProperty('props');
8499
});
85100

101+
test('captures componentProps from the erroring component', async () => {
102+
mount(FlareErrorBoundary, {
103+
slots: {
104+
default: () => h(ThrowingComponentWithProps, { userId: 42, name: 'Alice' }),
105+
fallback: () => h('div', 'Error'),
106+
},
107+
});
108+
109+
await nextTick();
110+
111+
const context = mockReport.mock.calls[0][1];
112+
expect(context.vue.componentProps).toEqual({ userId: 42, name: 'Alice' });
113+
});
114+
115+
test('fallback slot receives componentProps', async () => {
116+
let receivedProps: Record<string, unknown> | null = null;
117+
118+
mount(FlareErrorBoundary, {
119+
slots: {
120+
default: () => h(ThrowingComponentWithProps, { userId: 42, name: 'Alice' }),
121+
fallback: (props: { componentProps: Record<string, unknown> | null }) => {
122+
receivedProps = props.componentProps;
123+
return h('div', 'Error');
124+
},
125+
},
126+
});
127+
128+
await nextTick();
129+
130+
expect(receivedProps).toEqual({ userId: 42, name: 'Alice' });
131+
});
132+
86133
test('passes instance and info as extra solution parameters', async () => {
87134
mount(FlareErrorBoundary, {
88135
slots: {

packages/vue/tests/flareVue.test.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,27 +80,42 @@ describe('flareVue', () => {
8080
expect(reportedError.message).toBe('string error');
8181
});
8282

83-
test('passes vue context with info, componentName, componentHierarchy, and componentHierarchyFrames', () => {
83+
test('passes vue context with info, componentName, componentProps, componentHierarchy, and componentHierarchyFrames', () => {
8484
const app = createMockApp();
8585
(flareVue as Function)(app);
8686

8787
const grandparent = createMockInstance('App');
8888
const parent = createMockInstance('Layout', grandparent);
89-
const instance = createMockInstance('Button', parent);
89+
const instance = createMockInstance('Button', parent, { variant: 'primary' });
9090

9191
callHandler(app, new Error('test'), instance, 'setup function');
9292

9393
const context = mockReport.mock.calls[0][1];
9494
expect(context.vue.info).toBe('setup function');
9595
expect(context.vue.componentName).toBe('Button');
96+
expect(context.vue.componentProps).toEqual({ variant: 'primary' });
9697
expect(context.vue.componentHierarchy).toEqual(['Button', 'Layout', 'App']);
9798
expect(context.vue.componentHierarchyFrames).toEqual([
98-
{ component: 'Button', file: null, props: {} },
99+
{ component: 'Button', file: null, props: { variant: 'primary' } },
99100
{ component: 'Layout', file: null, props: {} },
100101
{ component: 'App', file: null, props: {} },
101102
]);
102103
});
103104

105+
test('componentProps is a shallow copy of instance props', () => {
106+
const app = createMockApp();
107+
(flareVue as Function)(app);
108+
109+
const originalProps = { userId: 42 };
110+
const instance = createMockInstance('UserCard', null, originalProps);
111+
112+
callHandler(app, new Error('test'), instance, 'setup function');
113+
114+
const context = mockReport.mock.calls[0][1];
115+
expect(context.vue.componentProps).toEqual({ userId: 42 });
116+
expect(context.vue.componentProps).not.toBe(originalProps);
117+
});
118+
104119
test('passes instance and info as extra solution parameters', () => {
105120
const app = createMockApp();
106121
(flareVue as Function)(app);
@@ -187,6 +202,7 @@ describe('flareVue', () => {
187202

188203
const context = mockReport.mock.calls[0][1];
189204
expect(context.vue.componentName).toBe('AnonymousComponent');
205+
expect(context.vue.componentProps).toBeNull();
190206
expect(context.vue.componentHierarchy).toEqual([]);
191207
expect(context.vue.componentHierarchyFrames).toEqual([]);
192208
});

0 commit comments

Comments
 (0)