import React from 'react'; import { vi } from 'vitest'; import { Heading, HeadingLevelProvider, Paragraph } from '@shoptet/ui-core-web'; import { render } from '../../../vitest/render'; describe('core Heading level context', () => { it('renders

with no provider (context base 0 + level 1)', () => { const { container } = render(Title); expect(container.querySelector('h1')).not.toBeNull(); }); it('respects the local level prop without a provider', () => { const { container } = render(Title); expect(container.querySelector('h3')).not.toBeNull(); }); it('adds provider offset to the base so a default Heading renders h2 (base 1 + level 1)', () => { const { container } = render( Title ); expect(container.querySelector('h2')).not.toBeNull(); expect(container.querySelector('h1')).toBeNull(); }); it('accumulates nested provider offsets (outer base + inner offset + local level)', () => { const { container } = render( Title ); expect(container.querySelector('h6')).not.toBeNull(); expect(container.querySelector('h2')).toBeNull(); }); it('adds the local level to the inherited base (base 1 + level 2 = h3)', () => { const { container } = render( Title ); expect(container.querySelector('h3')).not.toBeNull(); }); it('emits

when the computed level exceeds 6', () => { const { container } = render( Title ); const heading = container.querySelector('h6'); expect(heading).not.toBeNull(); expect(heading?.getAttribute('role')).toBeNull(); expect(heading?.getAttribute('aria-level')).toBe('7'); }); it('warns when the computed level exceeds 9 and caps the exposed aria-level at 9', () => { const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); try { const { container } = render( Title ); const heading = container.querySelector('h6'); expect(heading).not.toBeNull(); expect(heading?.getAttribute('aria-level')).toBe('9'); expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('Computed level 10 exceeds 9')); } finally { warnSpy.mockRestore(); } }); it('owns role/aria-level at render time while forwarding other aria attributes', () => { // Consumers may pass HTML attributes, but Heading overwrites role/aria-level when it needs // explicit heading semantics. A native heading carries neither attribute; other aria-* forward. const { container } = render(Title); const h1 = container.querySelector('h1'); expect(h1).not.toBeNull(); expect(h1?.getAttribute('role')).toBeNull(); expect(h1?.getAttribute('aria-level')).toBeNull(); expect(h1?.getAttribute('aria-label')).toBe('label'); }); it('forwards arbitrary attributes and resolves className from state', () => { const { container } = render( `level-${state.level}`}> Title ); const h1 = container.querySelector('h1'); expect(h1?.getAttribute('id')).toBe('anchor'); expect(h1?.className).toBe('level-1'); }); }); describe('core Paragraph block-nesting degrade', () => { it('renders a

at the top level', () => { const { container } = render(Text); expect(container.querySelector('p')).not.toBeNull(); }); it('degrades a nested Paragraph to an inline ', () => { const { container } = render( outer inner ); const outer = container.querySelector('p'); expect(outer).not.toBeNull(); expect(outer?.querySelector('p')).toBeNull(); expect(outer?.querySelector('span')).not.toBeNull(); expect(outer?.querySelector('span')?.textContent).toBe('inner'); }); }); describe('core block-in-block nesting across Heading and Paragraph', () => { it('degrades a Heading inside a Paragraph to a plain (no in the

)', () => { const { container } = render( text Sub ); const outer = container.querySelector('p'); expect(outer).not.toBeNull(); expect(outer?.querySelector('h1')).toBeNull(); const inner = outer?.querySelector('span'); expect(inner).not.toBeNull(); expect(inner?.hasAttribute('role')).toBe(false); expect(inner?.hasAttribute('aria-level')).toBe(false); expect(inner?.textContent).toBe('Sub'); }); it('degrades a Paragraph inside a Heading to an inline (no

in the heading)', () => { const { container } = render( Title body ); const outer = container.querySelector('h1'); expect(outer).not.toBeNull(); expect(outer?.querySelector('p')).toBeNull(); const inner = outer?.querySelector('span'); expect(inner).not.toBeNull(); expect(inner?.hasAttribute('role')).toBe(false); expect(inner?.textContent).toBe('body'); }); it('degrades a Heading inside a Heading to a plain (no nested )', () => { const { container } = render( Title Sub ); const outer = container.querySelector('h1'); expect(outer).not.toBeNull(); expect(outer?.querySelector('h2')).toBeNull(); const inner = outer?.querySelector('span'); expect(inner).not.toBeNull(); expect(inner?.hasAttribute('role')).toBe(false); expect(inner?.hasAttribute('aria-level')).toBe(false); }); });