import { ApproxStructure, Assertions, GeneralSteps, Keyboard, Keys, Log, Mouse, Step } from '@ephox/agar'; import { UnitTest } from '@ephox/bedrock-client'; import { Arr, Fun, Future, Result } from '@ephox/katamari'; import { SelectorExists } 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 type { SketchSpec } from 'ephox/alloy/api/component/SpecTypes'; import { Button } from 'ephox/alloy/api/ui/Button'; import { FloatingToolbarButton } from 'ephox/alloy/api/ui/FloatingToolbarButton'; import * as Layout from 'ephox/alloy/positioning/layout/Layout'; import * as GuiSetup from 'ephox/alloy/test/GuiSetup'; import * as Sinks from 'ephox/alloy/test/Sinks'; import * as TestPartialToolbarGroup from 'ephox/alloy/test/toolbar/TestPartialToolbarGroup'; UnitTest.asynctest('FloatingToolbarButtonTest', (success, failure) => { const sinkComp = Sinks.relativeSink(); const makeButton = (itemSpec: { text: string }): SketchSpec => Button.sketch({ dom: { tag: 'button', innerHtml: itemSpec.text }, buttonBehaviours: Behaviour.derive([ Tabstopping.config({ }) ]) }); GuiSetup.setup((store, _doc, _body) => GuiFactory.build( FloatingToolbarButton.sketch({ layouts: { onRtl: () => [ ], onLtr: () => [ Layout.southeast, Layout.northeast ] }, lazySink: Fun.constant(Result.value(sinkComp)), fetch: () => Future.nu((resolve) => { const groups = TestPartialToolbarGroup.createGroups([ { items: Arr.map([{ text: 'A' }, { text: 'B' }], makeButton) }, { items: Arr.map([{ text: 'C' }, { text: 'D' }], makeButton) } ]); resolve(groups); }), markers: { toggledClass: 'test-button-toggle' }, parts: { button: { dom: { tag: 'button', classes: [ 'more-button' ], innerHtml: '+' } }, toolbar: { dom: { tag: 'div', classes: [ 'test-toolbar' ] } } }, onToggled: (_comp, state) => store.adder('onToggled:' + state)() }) ), (doc, _body, gui, component, store) => { gui.add(sinkComp); const sAssertButtonStructure = (active: boolean) => GeneralSteps.sequence([ Assertions.sAssertStructure( `Floating toolbar button should ${active ? 'have' : 'not have'} toggle class`, ApproxStructure.build((s, str, arr) => s.element('button', { classes: active ? [ arr.has('test-button-toggle') ] : [], children: [ s.text(str.is('+')) ] })), component.element ) ]); const sAssertFloatingToolbarToggleState = (expected: boolean) => Step.sync(() => { Assertions.assertEq('Expected floating toolbar toggle state to be ' + expected, expected, FloatingToolbarButton.isOpen(component)); }); const sToggleFloatingToolbar = () => Step.sync(() => { FloatingToolbarButton.toggle(component); }); const sAssertFloatingToolbarOpened = () => GeneralSteps.sequence([ Assertions.sAssertStructure( 'Assert floating toolbar structure', ApproxStructure.build((s, str, arr) => s.element('div', { children: [ s.element('div', { attrs: { id: str.contains('aria-controls') }, children: [ s.element('div', { classes: [ arr.has('test-toolbar') ], children: [ ApproxStructure.build((s, str, arr) => s.element('div', { classes: [ arr.has('test-toolbar-group') ], children: [ s.element('button', { html: str.is('A') }), s.element('button', { html: str.is('B') }) ] })), ApproxStructure.build((s, str, arr) => s.element('div', { classes: [ arr.has('test-toolbar-group') ], children: [ s.element('button', { html: str.is('C') }), s.element('button', { html: str.is('D') }) ] })) ] }) ] }) ] })), sinkComp.element ), sAssertFloatingToolbarToggleState(true) ]); const sAssertFloatingToolbarClosed = () => Step.sync(() => { Assertions.assertEq('Floating toolbar should not exist', false, SelectorExists.descendant(sinkComp.element, 'test-toolbar')); sAssertFloatingToolbarToggleState(false); }); return [ GuiSetup.mAddStyles(doc, [ '.test-toolbar { display: flex; }' ]), store.sAssertEq('Assert initial store state', [ ]), Log.stepsAsStep('', 'Assert initial structure', [ sAssertButtonStructure(false), sAssertFloatingToolbarClosed() ]), Log.stepsAsStep('', 'Clicking on button should open floating toolbar', [ Mouse.sClickOn(gui.element, 'button'), sAssertButtonStructure(true), sAssertFloatingToolbarOpened() ]), store.sAssertEq('Assert store contains toggled state', [ 'onToggled:true' ]), Log.stepsAsStep('', 'Escape should close floating toolbar', [ Keyboard.sKeyup(doc, Keys.escape(), { }), sAssertFloatingToolbarClosed() ]), store.sAssertEq('Assert store contains 2 toggled state', [ 'onToggled:true', 'onToggled:false' ]), Log.stepsAsStep('TINY-6032', 'Using the API to toggle the floating toolbar should work', [ sToggleFloatingToolbar(), sAssertButtonStructure(true), sAssertFloatingToolbarOpened(), sToggleFloatingToolbar(), sAssertFloatingToolbarClosed() ]), GuiSetup.mRemoveStyles ]; }, success, failure); });