import { RouterTestingModule } from '@angular/router/testing' ; import { IonIcon } from '@ionic/angular' ; import { createHostFactory , SpectatorHost } from '@ngneat/spectator' ; import { MockComponent , MockComponents } from 'ng-mocks' ; import { DesignTokenHelper } from '@kirbydesign/core' ; import { FitHeadingDirective } from '../../directives/fit-heading/fit-heading.directive' ; import { TestHelper } from '../../testing/test-helper' ; import { WindowRef } from '../../types/window-ref' ; import { CardComponent } from '../card/card.component' ; import { DropdownComponent } from '../dropdown/dropdown.component' ; import { EmptyStateComponent } from '../empty-state/empty-state.component' ; import { IconComponent } from '../icon/icon.component' ; import { ItemComponent } from '../item/item.component' ; import { PageActionsComponent , PageActionsDirective , PageComponent , PageContentComponent , PageTitleDirective , PageToolbarTitleDirective , } from '../page/page.component' ; import { ButtonComponent } from './button.component' ; const getColor = DesignTokenHelper . getColor ; const size = DesignTokenHelper . size ; const fontSize = DesignTokenHelper . fontSize ; const fatFingerSize = DesignTokenHelper . fatFingerSize ( ) ; describe ( 'ButtonComponent in Kirby Page' , ( ) => { let spectator ; const createHost = createHostFactory ( { component : PageComponent , imports : [ TestHelper . ionicModuleForTest , RouterTestingModule ] , declarations : [ ButtonComponent , PageContentComponent , PageActionsComponent , PageActionsDirective , PageTitleDirective , PageToolbarTitleDirective , FitHeadingDirective , ] , providers : [ { provide : WindowRef , useValue : < WindowRef > { nativeWindow : window } , } , ] , } ) ; beforeEach ( ( ) => { spectator = createHost < PageComponent > ( `<kirby-page>
        <ng-template kirbyPageTitle>
          <h1>Test Title</h1>
          <button kirby-button class="normal-button">Test</button>
        </ng-template>
        <ng-template kirbyPageToolbarTitle>
          Test Title
        </ng-template>
        <kirby-page-actions *kirbyPageActions>
          <button kirby-button class="text">Test Action</button>
          <button kirby-button class="icon-only">Icon</button>
        </kirby-page-actions>
        <kirby-page-content>
          <p class="my-content">Custom Content...</kirby-page-content>
        </kirby-page>` ) ; } ) ; it ( 'should create page wrapper' , ( ) => { expect ( spectator ) . toBeTruthy ( ) ; } ) ; describe ( 'inside Toolbar' , ( ) => { let ionToolbar ; let actionButtonInHeader ; let actionButtonInHeaderIconOnly ; beforeEach ( ( ) => { ionToolbar = spectator . queryHost ( 'ion-toolbar' ) ; actionButtonInHeader = spectator . queryHost ( 'ion-toolbar kirby-page-actions button[kirby-button].text' ) ; actionButtonInHeaderIconOnly = spectator . queryHost ( 'ion-toolbar kirby-page-actions button[kirby-button].icon-only' ) ; } ) ; it ( 'should render action button' , ( ) => { expect ( actionButtonInHeader ) . toBeTruthy ( ) ; } ) ; it ( 'should render without background-color' , async ( ) => { await TestHelper . whenReady ( ionToolbar ) ; expect ( actionButtonInHeader ) . toHaveComputedStyle ( { 'background-color' : 'transparent' } ) ; } ) ; it ( 'should render with correct color' , async ( ) => { await TestHelper . whenReady ( ionToolbar ) ; expect ( actionButtonInHeader ) . toHaveComputedStyle ( { color : getColor ( 'black' ) , } ) ; } ) ; it ( 'should render with transparent border' , async ( ) => { await TestHelper . whenReady ( ionToolbar ) ; expect ( actionButtonInHeader ) . toHaveComputedStyle ( { 'border-width' : '1px' , 'border-style' : 'solid' , 'border-color' : 'transparent' , } ) ; } ) ; it ( 'should render with correct size' , ( ) => { expect ( actionButtonInHeader ) . toHaveComputedStyle ( { width : 'auto' , height : fatFingerSize , } ) ; expect ( actionButtonInHeaderIconOnly ) . toHaveComputedStyle ( { width : fatFingerSize , height : fatFingerSize , } ) ; } ) ; } ) ; describe ( 'inside Page Actions' , ( ) => { let ionContent ; let actionButtonInPage ; beforeEach ( ( ) => { ionContent = spectator . queryHost ( 'ion-content' ) ; actionButtonInPage = spectator . queryHost ( '.page-title kirby-page-actions button[kirby-button]' ) ; } ) ; it ( 'should render action button' , ( ) => { expect ( actionButtonInPage ) . toBeTruthy ( ) ; } ) ; it ( 'should render with correct background-color' , async ( ) => { await TestHelper . whenReady ( ionContent ) ; expect ( actionButtonInPage ) . toHaveComputedStyle ( { 'background-color' : getColor ( 'white' ) , } ) ; } ) ; it ( 'should render with correct color' , async ( ) => { await TestHelper . whenReady ( ionContent ) ; expect ( actionButtonInPage ) . toHaveComputedStyle ( { color : getColor ( 'white' , 'contrast' ) , } ) ; } ) ; it ( 'should render with transparent border' , async ( ) => { await TestHelper . whenReady ( ionContent ) ; expect ( actionButtonInPage ) . toHaveComputedStyle ( { 'border-width' : '1px' , 'border-style' : 'solid' , 'border-color' : 'transparent' , } ) ; } ) ; } ) ; describe ( 'inside Page Title' , ( ) => { let ionContent ; let normalButtonInPage ; beforeEach ( ( ) => { ionContent = spectator . queryHost ( 'ion-content' ) ; normalButtonInPage = spectator . queryHost ( '.page-title button[kirby-button].normal-button' ) ; } ) ; it ( 'should render normal button' , ( ) => { expect ( normalButtonInPage ) . toBeTruthy ( ) ; } ) ; it ( 'should render with correct background-color' , async ( ) => { await TestHelper . whenReady ( ionContent ) ; expect ( normalButtonInPage ) . toHaveComputedStyle ( { 'background-color' : getColor ( 'primary' ) , } ) ; } ) ; it ( 'should render with transparent border' , async ( ) => { await TestHelper . whenReady ( ionContent ) ; expect ( normalButtonInPage ) . toHaveComputedStyle ( { 'border-width' : '1px' , 'border-style' : 'solid' , 'border-color' : 'transparent' , } ) ; } ) ; it ( 'should render with correct color' , async ( ) => { await TestHelper . whenReady ( ionContent ) ; expect ( normalButtonInPage ) . toHaveComputedStyle ( { color : getColor ( 'primary' , 'contrast' ) , } ) ; } ) ; } ) ; } ) ; describe ( 'ButtonComponent in kirby empty state' , ( ) => { let spectator ; let actionButtonInEmptyState ; const createHost = createHostFactory ( { component : EmptyStateComponent , imports : [ TestHelper . ionicModuleForTest , RouterTestingModule ] , declarations : [ ButtonComponent , IconComponent ] , } ) ; beforeEach ( ( ) => { spectator = createHost < PageComponent > ( `
      <kirby-empty-state
        title="No items"
        subtitle="You don't have any items. Call support to add some items to your account."
      >
        <button kirby-button>Call support</button>
      </kirby-empty-state>` ) ; actionButtonInEmptyState = spectator . queryHost ( '.content button[kirby-button]' ) ; } ) ; it ( 'should render with correct font-size' , ( ) => { expect ( actionButtonInEmptyState ) . toHaveComputedStyle ( { 'font-size' : fontSize ( 'n' ) , } ) ; } ) ; it ( 'should render with correct height' , ( ) => { expect ( actionButtonInEmptyState ) . toHaveComputedStyle ( { height : size ( 'xxl' ) } ) ; } ) ; it ( 'should render with correct min-width' , ( ) => { expect ( actionButtonInEmptyState ) . toHaveComputedStyle ( { 'min-width' : '220px' } ) ; } ) ; } ) ; describe ( 'ButtonComponent in Kirby dropdown' , ( ) => { let spectator ; const createHost = createHostFactory ( { component : DropdownComponent , declarations : [ ButtonComponent , MockComponents ( CardComponent , ItemComponent , IconComponent ) ] , } ) ; it ( 'should render with space between text and icon' , ( ) => { spectator = createHost < DropdownComponent > ( `<kirby-dropdown>
      </kirby-dropdown>` ) ; let button = spectator . queryHost ( 'button[kirby-button]' ) ; expect ( button ) . toHaveComputedStyle ( { 'justify-content' : 'space-between' } ) ; } ) ; } ) ; describe ( 'ButtonComponent configured with icon only' , ( ) => { let spectator ; let element ; const createHost = createHostFactory ( { component : ButtonComponent , declarations : [ MockComponent ( IconComponent ) ] , } ) ; const attentionLevels = [ '1' , '2' , '3' , '4' ] ; type AttentionLevel = '1' | '2' | '3' | '4' ; const iconButtonSizeDefault = size ( 'xl' ) ; it ( 'should render with correct width and height' , ( ) => { spectator = createHost ( `<button kirby-button>
        <kirby-icon name="edit">
      </kirby-icon></button>` ) ; element = spectator . element as HTMLButtonElement ; expect ( element ) . toHaveComputedStyle ( { width : iconButtonSizeDefault , height : iconButtonSizeDefault , } ) ; } ) ; describe ( 'and configured with attentionlevel' , ( ) => { beforeEach ( ( ) => { spectator = createHost ( `<button kirby-button >
          <kirby-icon name="edit">
        </kirby-icon></button>` ) ; element = spectator . element as HTMLButtonElement ; } ) ; attentionLevels . forEach ( ( attentionLevel ) => { it ( 'should render with correct width and height for attentionlevel = ' + attentionLevel , ( ) => { spectator . component . attentionLevel = attentionLevel ; spectator . detectChanges ( ) ; expect ( element ) . toHaveComputedStyle ( { width : iconButtonSizeDefault , height : iconButtonSizeDefault , } ) ; } ) ; } ) ; } ) ; describe ( 'and initialized with size = SM' , ( ) => { const iconButtonSizeSM = size ( 'l' ) ; beforeEach ( ( ) => { spectator = createHost ( `<button kirby-button size="sm">
          <kirby-icon name="edit">
        </kirby-icon></button>` ) ; element = spectator . element as HTMLButtonElement ; } ) ; it ( 'should render with correct width and height' , ( ) => { expect ( element ) . toHaveComputedStyle ( { width : iconButtonSizeSM , height : iconButtonSizeSM } ) ; } ) ; describe ( 'and configured with attentionlevel' , ( ) => { attentionLevels . forEach ( ( attentionLevel ) => { it ( 'should render with correct width and height for attentionlevel = ' + attentionLevel , ( ) => { spectator . component . attentionLevel = attentionLevel ; spectator . detectChanges ( ) ; expect ( element ) . toHaveComputedStyle ( { width : iconButtonSizeSM , height : iconButtonSizeSM , } ) ; } ) ; } ) ; } ) ; } ) ; describe ( 'and initialized with size = MD' , ( ) => { const iconButtonSizeMD = size ( 'xl' ) ; beforeEach ( ( ) => { spectator = createHost ( `<button kirby-button size="md">
          <kirby-icon name="edit">
        </kirby-icon></button>` ) ; element = spectator . element as HTMLButtonElement ; } ) ; it ( 'should render with correct width and height' , ( ) => { expect ( element ) . toHaveComputedStyle ( { width : iconButtonSizeMD , height : iconButtonSizeMD } ) ; } ) ; describe ( 'and configured with attentionlevel' , ( ) => { attentionLevels . forEach ( ( attentionLevel ) => { it ( 'should render with correct width and height for attentionlevel = ' + attentionLevel , ( ) => { spectator . component . attentionLevel = attentionLevel ; spectator . detectChanges ( ) ; expect ( element ) . toHaveComputedStyle ( { width : iconButtonSizeMD , height : iconButtonSizeMD , } ) ; } ) ; } ) ; } ) ; } ) ; describe ( 'and initialized with size = LG' , ( ) => { const iconButtonSizeLG = size ( 'xxl' ) ; beforeEach ( ( ) => { spectator = createHost ( `<button kirby-button size="lg">
          <kirby-icon name="edit">
        </kirby-icon></button>` ) ; element = spectator . element as HTMLButtonElement ; } ) ; it ( 'should render with correct width and height' , ( ) => { expect ( element ) . toHaveComputedStyle ( { width : iconButtonSizeLG , height : iconButtonSizeLG } ) ; } ) ; describe ( 'and configured with attentionlevel' , ( ) => { attentionLevels . forEach ( ( attentionLevel ) => { it ( 'should render with correct width and height for attentionlevel = ' + attentionLevel , ( ) => { spectator . component . attentionLevel = attentionLevel ; spectator . detectChanges ( ) ; expect ( element ) . toHaveComputedStyle ( { width : iconButtonSizeLG , height : iconButtonSizeLG , } ) ; } ) ; } ) ; } ) ; } ) ; } ) ; describe ( 'ButtonComponent configured with text and icon' , ( ) => { let kirbyIcon ; let spectator ; let element ; const createHost = createHostFactory ( { component : ButtonComponent , declarations : [ IconComponent , MockComponent ( IonIcon ) ] , } ) ; it ( 'should render with correct icon font-size' , ( ) => { spectator = createHost ( `<button kirby-button>
        <span>Text</span>
        <kirby-icon name="arrow-down"></kirby-icon>
      </button>` ) ; element = spectator . element as HTMLButtonElement ; kirbyIcon = element . getElementsByTagName ( 'kirby-icon' ) [ 0 ] ; expect ( kirbyIcon ) . toHaveComputedStyle ( { 'font-size' : size ( 'm' ) } ) ; } ) ; describe ( 'when icon left' , ( ) => { beforeEach ( ( ) => { spectator = createHost ( `<button kirby-button>
          <kirby-icon name="arrow-down"></kirby-icon>
          <span>Icon Left, Text Right</span>
        </button>` ) ; element = spectator . element as HTMLButtonElement ; kirbyIcon = element . getElementsByTagName ( 'kirby-icon' ) [ 0 ] ; } ) ; it ( 'should render with correct padding' , ( ) => { expect ( element ) . toHaveComputedStyle ( { 'padding-left' : size ( 'xs' ) , 'padding-right' : size ( 's' ) , } ) ; } ) ; it ( 'should render with correct icon margin' , ( ) => { expect ( kirbyIcon ) . toHaveComputedStyle ( { 'margin-left' : '0px' , 'margin-right' : size ( 'xxs' ) , } ) ; } ) ; } ) ; describe ( 'when icon right' , ( ) => { beforeEach ( ( ) => { spectator = createHost ( `<button kirby-button>
          <span>Text Left, Icon Right</span>
          <kirby-icon name="arrow-down"></kirby-icon>
        </button>` ) ; element = spectator . element as HTMLButtonElement ; kirbyIcon = element . getElementsByTagName ( 'kirby-icon' ) [ 0 ] ; } ) ; it ( 'should render with correct padding' , ( ) => { expect ( element ) . toHaveComputedStyle ( { 'padding-left' : size ( 's' ) , 'padding-right' : size ( 'xs' ) , } ) ; } ) ; it ( 'should render with correct icon margin' , ( ) => { expect ( kirbyIcon ) . toHaveComputedStyle ( { 'margin-left' : size ( 'xxs' ) , 'margin-right' : '0px' , } ) ; } ) ; } ) ; describe ( 'and initialized with size = SM' , ( ) => { beforeEach ( ( ) => { spectator = createHost ( `<button kirby-button size="sm">
          <span>Text</span>
          <kirby-icon name="arrow-down"></kirby-icon>
        </button>` ) ; element = spectator . element as HTMLButtonElement ; kirbyIcon = element . getElementsByTagName ( 'kirby-icon' ) [ 0 ] ; } ) ; it ( 'should render with correct icon font-size' , ( ) => { expect ( kirbyIcon ) . toHaveComputedStyle ( { 'font-size' : size ( 's' ) } ) ; } ) ; it ( 'should render with correct min-width' , ( ) => { expect ( element ) . toHaveComputedStyle ( { 'min-width' : '88px' } ) ; } ) ; } ) ; describe ( 'and initialized with size = MD' , ( ) => { beforeEach ( ( ) => { spectator = createHost ( `<button kirby-button size="md">
          <span>Text</span>
          <kirby-icon name="arrow-down"></kirby-icon>
        </button>` ) ; element = spectator . element as HTMLButtonElement ; kirbyIcon = element . getElementsByTagName ( 'kirby-icon' ) [ 0 ] ; } ) ; it ( 'should render with correct icon font-size' , ( ) => { expect ( kirbyIcon ) . toHaveComputedStyle ( { 'font-size' : size ( 'm' ) } ) ; } ) ; it ( 'should render with correct min-width' , ( ) => { expect ( element ) . toHaveComputedStyle ( { 'min-width' : '88px' } ) ; } ) ; } ) ; describe ( 'and initialized with size = LG' , ( ) => { beforeEach ( ( ) => { spectator = createHost ( `<button kirby-button size="lg">
          <span>Text</span>
          <kirby-icon name="arrow-down"></kirby-icon>
        </button>` ) ; element = spectator . element as HTMLButtonElement ; kirbyIcon = element . getElementsByTagName ( 'kirby-icon' ) [ 0 ] ; } ) ; it ( 'should render with correct icon font-size' , ( ) => { expect ( kirbyIcon ) . toHaveComputedStyle ( { 'font-size' : size ( 'm' ) } ) ; } ) ; it ( 'should render with correct min-width' , ( ) => { expect ( element ) . toHaveComputedStyle ( { 'min-width' : '220px' } ) ; } ) ; } ) ; } ) ; describe ( 'ButtonComponent configured with text and icon using an ngIf directive' , ( ) => { let spectator ; let element ; const createHost = createHostFactory ( { component : ButtonComponent , declarations : [ MockComponent ( IconComponent ) ] , } ) ; it ( 'should not have the icon-only class, if kirby-icon is inserted before text' , ( ) => { spectator = createHost ( '<button kirby-button><kirby-icon name="close" *ngIf="true"></kirby-icon>Test</button>' ) ; element = spectator . element as HTMLButtonElement ; expect ( element ) . not . toHaveClass ( 'icon-only' ) ; } ) ; it ( 'should not have the icon-only class, if kirby-icon is inserted after text' , ( ) => { spectator = createHost ( '<button kirby-button>Test<kirby-icon name="close" *ngIf="true"></kirby-icon></button>' ) ; element = spectator . element as HTMLButtonElement ; expect ( element ) . not . toHaveClass ( 'icon-only' ) ; } ) ; } ) ;