diff --git a/packages/vue/src/components.ts b/packages/vue/src/components.ts index c88b7189c009..654611d701cf 100644 --- a/packages/vue/src/components.ts +++ b/packages/vue/src/components.ts @@ -30,6 +30,11 @@ export const formatComponentName = (vm?: ViewModel, includeFile?: boolean): stri return ROOT_COMPONENT_NAME; } + // https://github.com/getsentry/sentry-javascript/issues/5204 $options can be undefined + if (!vm.$options) { + return ANONYMOUS_COMPONENT_NAME; + } + const options = vm.$options; let name = options.name || options._componentTag; diff --git a/packages/vue/test/components.test.ts b/packages/vue/test/components.test.ts index 6df0a950455d..2d0928fcf617 100644 --- a/packages/vue/test/components.test.ts +++ b/packages/vue/test/components.test.ts @@ -1,26 +1,120 @@ import { formatComponentName } from '../src/components'; -it('properly format component names', () => { - const vm: any = { - $options: {}, - }; - vm.$root = vm; - expect(formatComponentName(vm)).toBe(''); - - vm.$root = null; - vm.$options.name = 'hello-there'; - expect(formatComponentName(vm)).toBe(''); - - vm.$options.name = null; - vm.$options._componentTag = 'foo-bar-1'; - expect(formatComponentName(vm)).toBe(''); - - vm.$options._componentTag = null; - vm.$options.__file = '/foo/bar/baz/SomeThing.vue'; - expect(formatComponentName(vm)).toBe(` at ${vm.$options.__file}`); - expect(formatComponentName(vm, false)).toBe(''); - - vm.$options.__file = 'C:\\foo\\bar\\baz\\windows_file.vue'; - expect(formatComponentName(vm)).toBe(` at ${vm.$options.__file}`); - expect(formatComponentName(vm, false)).toBe(''); +describe('formatComponentName', () => { + describe('when the vm is not defined', () => { + it('returns the anonymous component name', () => { + // arrange + const vm = undefined; + + // act + const formattedName = formatComponentName(vm); + + // assert + expect(formattedName).toEqual(''); + }); + }); + + describe('when the vm is defined', () => { + let vm: any = undefined; + + beforeEach(() => { + vm = {}; + }); + + describe('and when the $options is not defined', () => { + it('returns the anonymous component name', () => { + // arrange + vm.$options = undefined; + + // act + const formattedName = formatComponentName(vm); + + // assert + expect(formattedName).toEqual(''); + }); + }); + + describe('when the $options is defined', () => { + beforeEach(() => { + vm = { $options: {} }; + }); + + describe('when the vm is the $root', () => { + it('returns the root component name', () => { + // arrange + vm.$root = vm; + + // act + const formattedName = formatComponentName(vm); + + // assert + expect(formattedName).toEqual(''); + }); + }); + + describe('when the $options have a name', () => { + it('returns the name', () => { + // arrange + vm.$options.name = 'hello-there'; + + // act + const formattedName = formatComponentName(vm); + + // assert + expect(formattedName).toEqual(''); + }); + }); + + describe('when the options have a _componentTag', () => { + it('returns the _componentTag', () => { + // arrange + vm.$options._componentTag = 'foo-bar-1'; + + // act + const formattedName = formatComponentName(vm); + + // assert + expect(formattedName).toEqual(''); + }); + }); + + describe('when the options have a __file', () => { + describe('and we do not wish to include the filename', () => { + it.each([ + ['unix', '/foo/bar/baz/SomeThing.vue', ''], + ['unix', '/foo/bar/baz/SomeThing.ts', ''], + ['windows', 'C:\\foo\\bar\\baz\\windows_file.vue', ''], + ['windows', 'C:\\foo\\bar\\baz\\windows_file.ts', ''], + ])('returns the filename (%s)', (_, filePath, expected) => { + // arrange + vm.$options.__file = filePath; + + // act + const formattedName = formatComponentName(vm, false); + + // assert + expect(formattedName).toEqual(expected); + }); + }); + + describe('and we wish to include the filename', () => { + it.each([ + ['unix', '/foo/bar/baz/SomeThing.vue', ''], + ['unix', '/foo/bar/baz/SomeThing.ts', ''], + ['windows', 'C:\\foo\\bar\\baz\\windows_file.vue', ''], + ['windows', 'C:\\foo\\bar\\baz\\windows_file.ts', ''], + ])('returns the filename (%s)', (_, filePath, expected) => { + // arrange + vm.$options.__file = filePath; + + // act + const formattedName = formatComponentName(vm); + + // assert + expect(formattedName).toEqual(`${expected} at ${filePath}`); + }); + }); + }); + }); + }); });