Skip to content

Commit 0d07854

Browse files
authored
fix(vue): accounts for undefined options when formatting component name (#5254)
When formatting the component name, options can be undefined. When it is, we return the `ANONYMOUS_COMPONENT_NAME` early.
1 parent 0457289 commit 0d07854

File tree

2 files changed

+122
-23
lines changed

2 files changed

+122
-23
lines changed

packages/vue/src/components.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ export const formatComponentName = (vm?: ViewModel, includeFile?: boolean): stri
3030
return ROOT_COMPONENT_NAME;
3131
}
3232

33+
// https://github.com/getsentry/sentry-javascript/issues/5204 $options can be undefined
34+
if (!vm.$options) {
35+
return ANONYMOUS_COMPONENT_NAME;
36+
}
37+
3338
const options = vm.$options;
3439

3540
let name = options.name || options._componentTag;

packages/vue/test/components.test.ts

Lines changed: 117 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,120 @@
11
import { formatComponentName } from '../src/components';
22

3-
it('properly format component names', () => {
4-
const vm: any = {
5-
$options: {},
6-
};
7-
vm.$root = vm;
8-
expect(formatComponentName(vm)).toBe('<Root>');
9-
10-
vm.$root = null;
11-
vm.$options.name = 'hello-there';
12-
expect(formatComponentName(vm)).toBe('<HelloThere>');
13-
14-
vm.$options.name = null;
15-
vm.$options._componentTag = 'foo-bar-1';
16-
expect(formatComponentName(vm)).toBe('<FooBar1>');
17-
18-
vm.$options._componentTag = null;
19-
vm.$options.__file = '/foo/bar/baz/SomeThing.vue';
20-
expect(formatComponentName(vm)).toBe(`<SomeThing> at ${vm.$options.__file}`);
21-
expect(formatComponentName(vm, false)).toBe('<SomeThing>');
22-
23-
vm.$options.__file = 'C:\\foo\\bar\\baz\\windows_file.vue';
24-
expect(formatComponentName(vm)).toBe(`<WindowsFile> at ${vm.$options.__file}`);
25-
expect(formatComponentName(vm, false)).toBe('<WindowsFile>');
3+
describe('formatComponentName', () => {
4+
describe('when the vm is not defined', () => {
5+
it('returns the anonymous component name', () => {
6+
// arrange
7+
const vm = undefined;
8+
9+
// act
10+
const formattedName = formatComponentName(vm);
11+
12+
// assert
13+
expect(formattedName).toEqual('<Anonymous>');
14+
});
15+
});
16+
17+
describe('when the vm is defined', () => {
18+
let vm: any = undefined;
19+
20+
beforeEach(() => {
21+
vm = {};
22+
});
23+
24+
describe('and when the $options is not defined', () => {
25+
it('returns the anonymous component name', () => {
26+
// arrange
27+
vm.$options = undefined;
28+
29+
// act
30+
const formattedName = formatComponentName(vm);
31+
32+
// assert
33+
expect(formattedName).toEqual('<Anonymous>');
34+
});
35+
});
36+
37+
describe('when the $options is defined', () => {
38+
beforeEach(() => {
39+
vm = { $options: {} };
40+
});
41+
42+
describe('when the vm is the $root', () => {
43+
it('returns the root component name', () => {
44+
// arrange
45+
vm.$root = vm;
46+
47+
// act
48+
const formattedName = formatComponentName(vm);
49+
50+
// assert
51+
expect(formattedName).toEqual('<Root>');
52+
});
53+
});
54+
55+
describe('when the $options have a name', () => {
56+
it('returns the name', () => {
57+
// arrange
58+
vm.$options.name = 'hello-there';
59+
60+
// act
61+
const formattedName = formatComponentName(vm);
62+
63+
// assert
64+
expect(formattedName).toEqual('<HelloThere>');
65+
});
66+
});
67+
68+
describe('when the options have a _componentTag', () => {
69+
it('returns the _componentTag', () => {
70+
// arrange
71+
vm.$options._componentTag = 'foo-bar-1';
72+
73+
// act
74+
const formattedName = formatComponentName(vm);
75+
76+
// assert
77+
expect(formattedName).toEqual('<FooBar1>');
78+
});
79+
});
80+
81+
describe('when the options have a __file', () => {
82+
describe('and we do not wish to include the filename', () => {
83+
it.each([
84+
['unix', '/foo/bar/baz/SomeThing.vue', '<SomeThing>'],
85+
['unix', '/foo/bar/baz/SomeThing.ts', '<Anonymous>'],
86+
['windows', 'C:\\foo\\bar\\baz\\windows_file.vue', '<WindowsFile>'],
87+
['windows', 'C:\\foo\\bar\\baz\\windows_file.ts', '<Anonymous>'],
88+
])('returns the filename (%s)', (_, filePath, expected) => {
89+
// arrange
90+
vm.$options.__file = filePath;
91+
92+
// act
93+
const formattedName = formatComponentName(vm, false);
94+
95+
// assert
96+
expect(formattedName).toEqual(expected);
97+
});
98+
});
99+
100+
describe('and we wish to include the filename', () => {
101+
it.each([
102+
['unix', '/foo/bar/baz/SomeThing.vue', '<SomeThing>'],
103+
['unix', '/foo/bar/baz/SomeThing.ts', '<Anonymous>'],
104+
['windows', 'C:\\foo\\bar\\baz\\windows_file.vue', '<WindowsFile>'],
105+
['windows', 'C:\\foo\\bar\\baz\\windows_file.ts', '<Anonymous>'],
106+
])('returns the filename (%s)', (_, filePath, expected) => {
107+
// arrange
108+
vm.$options.__file = filePath;
109+
110+
// act
111+
const formattedName = formatComponentName(vm);
112+
113+
// assert
114+
expect(formattedName).toEqual(`${expected} at ${filePath}`);
115+
});
116+
});
117+
});
118+
});
119+
});
26120
});

0 commit comments

Comments
 (0)