diff --git a/src/components/NcAppNavigationCaption/NcAppNavigationCaption.vue b/src/components/NcAppNavigationCaption/NcAppNavigationCaption.vue index 505e53d410..c7d6164f1b 100644 --- a/src/components/NcAppNavigationCaption/NcAppNavigationCaption.vue +++ b/src/components/NcAppNavigationCaption/NcAppNavigationCaption.vue @@ -148,6 +148,14 @@ export default { default: false, }, + /** + * If `isHeading` is set, this defines the heading level that should be used + */ + headingLevel: { + type: Number, + default: 2, + }, + /** * Any [NcActions](#/Components/NcActions?id=ncactions-1) prop */ @@ -161,7 +169,9 @@ export default { return this.isHeading ? 'div' : 'li' }, captionTag() { - return this.isHeading ? 'h2' : 'span' + // Limit to at least h2 as h1 is considered invalid and reserved + const headingLevel = Math.max(2, this.headingLevel) + return this.isHeading ? `h${headingLevel}` : 'span' }, // Check if the actions slot is populated hasActions() { diff --git a/tests/unit/components/NcAppNavigation/NcAppNavigationCaption.spec.ts b/tests/unit/components/NcAppNavigation/NcAppNavigationCaption.spec.ts new file mode 100644 index 0000000000..b15151a216 --- /dev/null +++ b/tests/unit/components/NcAppNavigation/NcAppNavigationCaption.spec.ts @@ -0,0 +1,74 @@ +import { describe, expect } from '@jest/globals' +import { shallowMount } from '@vue/test-utils' +import NcAppNavigationCaption from '../../../../src/components/NcAppNavigationCaption/NcAppNavigationCaption.vue' + +describe('NcAppNavigationCaption.vue', () => { + test('attributes are passed to actions', async () => { + const wrapper = shallowMount(NcAppNavigationCaption, { + propsData: { + name: 'The name', + }, + attrs: { + forceMenu: 'true', + }, + slots: { + actions: [ + 'Button 1', + 'Button 2', + ], + }, + }) + + expect(wrapper.findComponent({ name: 'NcActions' }).attributes('forcemenu')).toBe('true') + }) + + test('component is a list entry by default', async () => { + const wrapper = shallowMount(NcAppNavigationCaption, { + propsData: { + name: 'The name', + }, + }) + + expect(wrapper.element.tagName).toBe('LI') + expect(wrapper.find('h2').exists()).toBe(false) + expect(wrapper.find('span').exists()).toBe(true) + }) + + test('component tags are adjusted when used as heading', async () => { + const wrapper = shallowMount(NcAppNavigationCaption, { + propsData: { + name: 'The name', + isHeading: true, + }, + }) + + expect(wrapper.element.tagName).toBe('DIV') + expect(wrapper.find('h2').exists()).toBe(true) + }) + + test('can set the heading level', async () => { + const wrapper = shallowMount(NcAppNavigationCaption, { + propsData: { + name: 'The name', + isHeading: true, + headingLevel: 3, + }, + }) + + expect(wrapper.contains('h3')).toBe(true) + expect(wrapper.contains('h2')).toBe(false) + }) + + test('does not set the heading level to h1', async () => { + const wrapper = shallowMount(NcAppNavigationCaption, { + propsData: { + name: 'The name', + isHeading: true, + headingLevel: 1, + }, + }) + + expect(wrapper.contains('h2')).toBe(true) + expect(wrapper.contains('h1')).toBe(false) + }) +})