import { ApproxStructure, Assertions, GeneralSteps, Logger, Step, type StructAssert } from '@ephox/agar'; import { UnitTest } from '@ephox/bedrock-client'; import { SelectorFind, type SugarElement } from '@ephox/sugar'; import * as Behaviour from 'ephox/alloy/api/behaviour/Behaviour'; import { Tabstopping } from 'ephox/alloy/api/behaviour/Tabstopping'; import * as GuiFactory from 'ephox/alloy/api/component/GuiFactory'; import * as AlloyTriggers from 'ephox/alloy/api/events/AlloyTriggers'; import { Container } from 'ephox/alloy/api/ui/Container'; import { Tabbar } from 'ephox/alloy/api/ui/Tabbar'; import { TabSection } from 'ephox/alloy/api/ui/TabSection'; import * as GuiSetup from 'ephox/alloy/test/GuiSetup'; UnitTest.asynctest('TabSection Test', (success, failure) => { GuiSetup.setup((_store, _doc, _body) => { let counterA = 0; let counterB = 0; return GuiFactory.build( TabSection.sketch({ dom: { tag: 'div' }, components: [ TabSection.parts.tabbar({ dom: { tag: 'div' }, components: [ Tabbar.parts.tabs({ }) ], markers: { tabClass: 'test-tab-button', selectedClass: 'selected-test-tab-button' }, tabbarBehaviours: Behaviour.derive([ Tabstopping.config({ }) ]) }), TabSection.parts.tabview({ dom: { tag: 'div', classes: [ 'test-tabview' ] } }) ], tabs: [ { uid: 'alpha-tab', value: 'alpha', dom: { tag: 'button', innerHtml: 'A' }, view: () => { counterA++; return [ Container.sketch({ dom: { innerHtml: 'This is the view for "A' + counterA + '"' }, components: [ ] }) ]; } }, { uid: 'beta-tab', value: 'beta', dom: { tag: 'button', innerHtml: 'B' }, view: () => { counterB++; return [ Container.sketch({ dom: { innerHtml: 'This is the view for "B' + counterB + '"' }, components: [ ] }) ]; } } ] }) ); }, (doc, _body, _gui, component, _store) => { const alpha = component.getSystem().getByUid('alpha-tab').getOrDie(); const beta = component.getSystem().getByUid('beta-tab').getOrDie(); const tview = component.getSystem().getByDom( SelectorFind.descendant(component.element, '.test-tabview').getOrDie('Could not find tabview') ).getOrDie(); const sAssertTabSelection = (label: string, expected: boolean, element: SugarElement) => Assertions.sAssertStructure(label + ' (asserting structure)', ApproxStructure.build((s, str, arr) => s.element('button', { attrs: { 'aria-selected': expected ? str.is('true') : str.is('false') }, classes: [ (expected ? arr.has : arr.not)('selected-test-tab-button') ] })), element); const sAssertTabView = (label: string, expected: ApproxStructure.Builder) => Assertions.sAssertStructure(label + ' (asserting structure)', ApproxStructure.build((s, str, arr) => s.element('div', { children: expected(s, str, arr) })), tview.element); return [ GuiSetup.mAddStyles(doc, [ '.selected-test-tab-button { background: #cadbee; }' ]), Assertions.sAssertStructure('Checking initial tab section', ApproxStructure.build((s, str, arr) => s.element('div', { children: [ s.element('div', { attrs: { 'data-alloy-tabstop': str.is('true'), 'role': str.is('tablist') }, children: [ s.element('button', { html: str.is('A'), attrs: { 'data-alloy-id': str.none(), 'aria-selected': str.is('true') }, classes: [ arr.has('test-tab-button') ] }), s.element('button', { html: str.is('B'), attrs: { 'data-alloy-id': str.none(), 'aria-selected': str.is('false') }, classes: [ arr.has('test-tab-button') ] }) ] }), s.element('div', { classes: [ arr.has('test-tabview') ] }) ] })), component.element), Logger.t( 'Execute alpha, check tabs and tabview', GeneralSteps.sequence([ Step.sync(() => { AlloyTriggers.emitExecute(alpha); }), sAssertTabSelection('Check Alpha', true, alpha.element), sAssertTabSelection('Check Beta', false, beta.element), sAssertTabView('Check TabView', (s, str, _arr) => [ s.element('div', { html: str.is('This is the view for "A1"') }) ]) ]) ), Logger.t( 'Execute beta, check tabs and tabview', GeneralSteps.sequence([ Step.sync(() => { AlloyTriggers.emitExecute(beta); }), sAssertTabSelection('Check Alpha', false, alpha.element), sAssertTabSelection('Check Beta', true, beta.element), sAssertTabView('Check TabView', (s, str, _arr) => [ s.element('div', { html: str.is('This is the view for "B1"') }) ]) ]) ), Logger.t( 'Execute alpha again, check tabs and tabview. Should be v2', GeneralSteps.sequence([ Step.sync(() => { AlloyTriggers.emitExecute(alpha); }), sAssertTabSelection('Check Alpha', true, alpha.element), sAssertTabSelection('Check Beta', false, beta.element), sAssertTabView('Check TabView', (s, str, _arr) => [ s.element('div', { html: str.is('This is the view for "A2"') }) ]) ]) ), Logger.t( 'Execute alpha again x 2, check tabs and tabview. Should stay v2', GeneralSteps.sequence([ Step.sync(() => { AlloyTriggers.emitExecute(alpha); }), sAssertTabSelection('Check Alpha', true, alpha.element), sAssertTabSelection('Check Beta', false, beta.element), sAssertTabView('Check TabView', (s, str, _arr) => [ s.element('div', { html: str.is('This is the view for "A2"') }) ]) ]) ), Logger.t( 'Execute alpha again x 3 (via API), check tabs and tabview. Should still stay v2', GeneralSteps.sequence([ Step.sync(() => { TabSection.showTab(component, 'alpha'); }), sAssertTabSelection('Check Alpha', true, alpha.element), sAssertTabSelection('Check Beta', false, beta.element), sAssertTabView('Check TabView', (s, str, _arr) => [ s.element('div', { html: str.is('This is the view for "A2"') }) ]) ]) ), Logger.t( 'Execute alpha again x 4 (via API), check tabs and tabview. Should still stay v2', GeneralSteps.sequence([ Step.sync(() => { TabSection.showTab(component, 'alpha'); }), sAssertTabSelection('Check Alpha', true, alpha.element), sAssertTabSelection('Check Beta', false, beta.element), sAssertTabView('Check TabView', (s, str, _arr) => [ s.element('div', { html: str.is('This is the view for "A2"') }) ]) ]) ), Logger.t( 'Execute beta (via API), check tabs and tabview. Should still stay v2', GeneralSteps.sequence([ Step.sync(() => { TabSection.showTab(component, 'beta'); }), sAssertTabSelection('Check Alpha', false, alpha.element), sAssertTabSelection('Check Beta', true, beta.element), sAssertTabView('Check TabView', (s, str, _arr) => [ s.element('div', { html: str.is('This is the view for "B2"') }) ]) ]) ), GuiSetup.mRemoveStyles ]; }, success, failure); });