Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
7b7f636
feat(banner): add banner component
RivaIvanova Apr 26, 2024
e6ddf93
Merge branch 'master' into rivanova/feat-banner-1174
RivaIvanova Apr 26, 2024
14b9397
refactor(banner): address lint
RivaIvanova Apr 26, 2024
7af5e1c
Merge branch 'master' of https://github.com/IgniteUI/igniteui-webcomp…
RivaIvanova May 8, 2024
6a76296
Merge branch 'master' into rivanova/feat-banner-1174
RivaIvanova May 14, 2024
d689e47
Merge branch 'master' into rivanova/feat-banner-1174
simeonoff May 16, 2024
ed015fc
Merge branch 'master' into rivanova/feat-banner-1174
simeonoff May 20, 2024
c101905
Merge branch 'master' into rivanova/feat-banner-1174
May 27, 2024
fdcaed0
Banner - add themes styling (#1217)
desig9stein May 30, 2024
d5d5c1f
Merge branch 'master' into rivanova/feat-banner-1174
simeonoff May 30, 2024
21cd39f
Merge branch 'master' into rivanova/feat-banner-1174
RivaIvanova Jun 3, 2024
9cf0072
chore(banner): add css parts to component description
RivaIvanova Jun 3, 2024
8ff00b2
Merge branch 'master' into rivanova/feat-banner-1174
rkaraivanov Jun 5, 2024
f7365ef
refactor(banner): update paddings and theming
simeonoff Jun 6, 2024
7f3674d
lint(banner): fix errors
simeonoff Jun 6, 2024
eac2ec2
Merge branch 'master' into rivanova/feat-banner-1174
simeonoff Jun 7, 2024
319eb70
refactor(banner): address comments
RivaIvanova Jun 10, 2024
00d8ce4
fix(banner): make sure that the users can change the icon color throu…
desig9stein Jun 10, 2024
553d9c7
refactor(banner): emit igcClosed when animation completes
RivaIvanova Jun 10, 2024
ce694e6
Merge branch 'rivanova/feat-banner-1174' of https://github.com/Ignite…
RivaIvanova Jun 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Added
- Banner component [#1174](https://github.com/IgniteUI/igniteui-webcomponents/issues/1174)
### Fixed
- Input, Textarea - passing `undefined` to **value** sets the underlying input value to undefined [#1206](https://github.com/IgniteUI/igniteui-webcomponents/issues/1206)

Expand Down
289 changes: 289 additions & 0 deletions src/components/banner/banner.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
import {
elementUpdated,
expect,
fixture,
html,
nextFrame,
} from '@open-wc/testing';
import { spy } from 'sinon';

import { defineComponents } from '../common/definitions/defineComponents.js';
import { finishAnimationsFor } from '../common/utils.spec.js';
import IgcBannerComponent from './banner.js';

describe('Banner', () => {
before(() => {
defineComponents(IgcBannerComponent);
});

const createDefaultBanner = () => html`
<igc-banner> You are currently offline. </igc-banner>
`;

const createSlottedBanner = () => html`
<igc-banner>
<igc-icon slot="prefix"></igc-icon>
Build <strong>123</strong> completed!
<div slot="actions">
<igc-button>OK 1</igc-button>
<igc-button>View log</igc-button>
</div>
</igc-banner>
`;

let banner: IgcBannerComponent;

beforeEach(async () => {
banner = await fixture<IgcBannerComponent>(createDefaultBanner());
});

const DIFF_OPTIONS = {
ignoreTags: ['igc-button'],
ignoreAttributes: ['inert'],
};

const BUTTON_DIFF_OPTIONS = ['variant', 'size', 'style'];

async function clickHideComplete() {
finishAnimationsFor(banner.shadowRoot!);
await elementUpdated(banner);
await nextFrame();
await nextFrame();
}

describe('Initialization Tests', () => {
it('passes the a11y audit', async () => {
await expect(banner).to.be.accessible();
await expect(banner).shadowDom.to.be.accessible();
});

it('is correctly initialized with its default component state', () => {
expect(banner.open).to.be.false;
expect(banner.dir).to.be.empty;
});

it('should render a default action button', () => {
const button = banner.shadowRoot!.querySelector('igc-button');

expect(button).not.to.be.null;
expect(button).dom.to.equal(`<igc-button type="button">OK</igc-button>`, {
ignoreAttributes: BUTTON_DIFF_OPTIONS,
});
});

it('is correctly rendered both in shown/hidden states', async () => {
expect(banner.open).to.be.false;

expect(banner).dom.to.equal(
'<igc-banner>You are currently offline.</igc-banner>'
);
expect(banner).shadowDom.to.equal(
`<div part="base" inert>
<div part="spacer">
<div part="message">
<div part="illustration">
<slot name="prefix"></slot>
</div>
<div part="content">
<slot></slot>
</div>
</div>
<div part="actions">
<slot name="actions">
<igc-button type="button">OK</igc-button>
</slot>
</div>
</div>
</div>`,
{
ignoreAttributes: BUTTON_DIFF_OPTIONS,
}
);

await banner.show();

expect(banner).dom.to.equal(
'<igc-banner open>You are currently offline.</igc-banner>'
);
expect(banner).shadowDom.to.equal(
`<div part="base">
<div part="spacer">
<div part="message">
<div part="illustration">
<slot name="prefix"></slot>
</div>
<div part="content">
<slot></slot>
</div>
</div>
<div part="actions">
<slot name="actions">
<igc-button type="button">OK</igc-button>
</slot>
</div>
</div>
</div>`,
{
ignoreAttributes: BUTTON_DIFF_OPTIONS,
}
);
});

it('should correctly render slotted content', async () => {
banner = await fixture<IgcBannerComponent>(createSlottedBanner());

const prefix = banner.querySelector('igc-icon');
const actions = banner.querySelector('div');

expect(prefix).not.to.be.null;
expect(actions).not.to.be.null;

expect(actions?.children[0]).dom.to.equal(
'<igc-button>OK 1</igc-button>',
{
ignoreAttributes: [...BUTTON_DIFF_OPTIONS, 'type'],
}
);

expect(actions?.children[1]).dom.to.equal(
'<igc-button>View log</igc-button>',
{
ignoreAttributes: [...BUTTON_DIFF_OPTIONS, 'type'],
}
);
});
});

describe('Methods` Tests', () => {
it('calls `show` and `hide` methods successfully', async () => {
expect(banner.open).to.be.false;

await banner.show();

expect(banner.open).to.be.true;
expect(banner).dom.to.equal(
'<igc-banner open>You are currently offline.</igc-banner>',
DIFF_OPTIONS
);

await banner.hide();

expect(banner.open).to.be.false;
expect(banner).dom.to.equal(
'<igc-banner>You are currently offline.</igc-banner>',
DIFF_OPTIONS
);
});

it('calls `toggle` method successfully', async () => {
expect(banner.open).to.be.false;

await banner.toggle();

expect(banner.open).to.be.true;
expect(banner).dom.to.equal(
'<igc-banner open>You are currently offline.</igc-banner>',
DIFF_OPTIONS
);

await banner.toggle();

expect(banner.open).to.be.false;
expect(banner).dom.to.equal(
'<igc-banner>You are currently offline.</igc-banner>',
DIFF_OPTIONS
);
});

it('`show`, `hide`, `toggle` methods return proper values', async () => {
expect(banner.open).to.be.false;

// hide banner when already hidden
let animation = await banner.hide();
expect(animation).to.be.false;

// show banner when hidden
animation = await banner.show();
expect(animation).to.be.true;
expect(banner.open).to.be.true;

// show banner when already shown
animation = await banner.show();
expect(animation).to.be.false;

// hide banner when shown
animation = await banner.hide();
expect(animation).to.be.true;
expect(banner.open).to.be.false;

// hide -> show
animation = await banner.toggle();
expect(animation).to.be.true;
expect(banner.open).to.be.true;

// show -> hide
animation = await banner.toggle();
expect(animation).to.be.true;
expect(banner.open).to.be.false;
});
});

describe('Action Tests', () => {
it('should close the banner when clicking the default button', async () => {
expect(banner.open).to.be.false;

await banner.show();

expect(banner.open).to.be.true;

const button = banner.shadowRoot!.querySelector('igc-button');

button?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
await clickHideComplete();

expect(banner.open).to.be.false;
});

it('should emit correct event sequence for the default action button', async () => {
const eventSpy = spy(banner, 'emitEvent');

expect(banner.open).to.be.false;

await banner.show();

expect(banner.open).to.be.true;

const button = banner.shadowRoot!.querySelector('igc-button');
button?.dispatchEvent(new MouseEvent('click', { bubbles: true }));

expect(eventSpy.callCount).to.equal(1);
expect(eventSpy).calledWith('igcClosing', { cancelable: true });

eventSpy.resetHistory();
await clickHideComplete();

expect(eventSpy).calledWith('igcClosed');
expect(banner.open).to.be.false;
});

it('can cancel `igcClosing` event', async () => {
const eventSpy = spy(banner, 'emitEvent');
const button = banner.shadowRoot!.querySelector('igc-button');

banner.addEventListener('igcClosing', (event) => {
event.preventDefault();
});

await banner.show();

expect(banner.open).to.be.true;

button?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
await clickHideComplete();

expect(eventSpy).calledWith('igcClosing');
expect(eventSpy).not.calledWith('igcClosed');
expect(banner.open).to.be.true;
});
});
});
Loading