import { newSpecPage } from '@stencil/core/testing';
import { BsToast } from '../bs-toast';
import { faker } from '@faker-js/faker';
import { queryByText } from '@testing-library/dom';
describe('bs-toast', () => {
  describe('Test rendering', () => {
    let title;
    let message;
    let toastId;
    beforeEach(() => {
      title = faker.random.word();
      message = faker.random.words(5);
      toastId = faker.random.alphaNumeric(20);
    });
    it('renders', async () => {
      const page = await newSpecPage({
        components: [BsToast],
        html: `
          <bs-toast toast-id="${toastId}" toast-title="${title}" content="${message}" />
        `
      });
      const component = page.root.shadowRoot.querySelector('.bs-toast');
      expect(queryByText(component, title));
      expect(queryByText(component, message));
    });
    it('renders content when sent in as slot as well', async () => {
      const page = await newSpecPage({
        components: [BsToast],
        html: `
          <bs-toast toast-id="${toastId}" toast-title="${title}">${message}</bs-toast>
        `
      });
      const component = page.root.shadowRoot.querySelector('.bs-toast');
      expect(queryByText(component, title));
      expect(queryByText(component, message));
    });
    // data shown = true
    it('renders data-shown when given', async () => {
      // Setting duration = 0 to prevent dismissal timer
      const page = await newSpecPage({
        components: [BsToast],
        html: `
          <bs-toast
            toast-id="${toastId}"
            toast-title="${title}"
            shown
            duration="0"
            content="${message}"
          />`
      });
      const component = page.root.shadowRoot.querySelector('.bs-toast');
      expect(component.getAttribute('data-shown')).toBe('');
    });
    // data dismissed = undefined
    it('renders data-dismiss undefined when not shown initially', async () => {
      const page = await newSpecPage({
        components: [BsToast],
        html: `
          <bs-toast
            toast-id="${toastId}"
            toast-title="${title}"
            content="${message}"
            shown="false"
          />`
      });
      const component = page.root.shadowRoot.querySelector('.bs-toast');
      expect(component.getAttribute('data-dismissed')).toBeNull();
    });
    // data dismissed = true
    it('renders data-dismissed when switching to not shown', async () => {
      // Setting duration = 0 to prevent dismissal timer
      const page = await newSpecPage({
        components: [BsToast],
        html: `
          <bs-toast
            toast-id="${toastId}"
            toast-title="${title}"
            shown
            duration="0"
            content="${message}"
          />`
      });
      // Flip to not shown
      page.root.shown = undefined;
      await page.waitForChanges();
      const component = page.root.shadowRoot.querySelector('.bs-toast');
      expect(component.getAttribute('data-dismissed')).toBe('');
    });
    // data-variant = undefined
    it('renders with undefined data-variant', async () => {
      const page = await newSpecPage({
        components: [BsToast],
        html: `
          <bs-toast
            toast-id="${toastId}"
            toast-title="${title}"
            content="${message}"
          />`
      });
      const component = page.root.shadowRoot.querySelector('.bs-toast');
      expect(component.getAttribute('data-variant')).toBeNull();
    });
    // data-variant = warning
    it('renders with "warning" data-variant', async () => {
      const page = await newSpecPage({
        components: [BsToast],
        html: `
          <bs-toast
            toast-id="${toastId}"
            toast-title="${title}"
            variant="warning"
            content="${message}"
          />`
      });
      const component = page.root.shadowRoot.querySelector('.bs-toast');
      expect(component.getAttribute('data-variant')).toBe('warning');
    });
    // data-variant = positive
    it('renders with "positive" data-variant', async () => {
      const page = await newSpecPage({
        components: [BsToast],
        html: `
          <bs-toast
            toast-id="${toastId}"
            toast-title="${title}"
            variant="positive"
            content="${message}"
          />`
      });
      const component = page.root.shadowRoot.querySelector('.bs-toast');
      expect(component.getAttribute('data-variant')).toBe('positive');
    });
    // data-variant = negative
    it('renders with "negative" data-variant', async () => {
      const page = await newSpecPage({
        components: [BsToast],
        html: `
          <bs-toast
            toast-id="${toastId}"
            toast-title="${title}"
            variant="negative"
            content="${message}"
          />`
      });
      const component = page.root.shadowRoot.querySelector('.bs-toast');
      expect(component.getAttribute('data-variant')).toBe('negative');
    });
    // data-stacked = undefined
    it('renders data-stacked undefined when not given', async () => {
      const page = await newSpecPage({
        components: [BsToast],
        html: `
          <bs-toast
            toast-id="${toastId}"
            toast-title="${title}"
            content="${message}"
          />`
      });
      const component = page.root.shadowRoot.querySelector('.bs-toast');
      expect(component.getAttribute('data-stacked')).toBeNull;
    });
    // data-stacked = true
    it('renders data-stacked when given', async () => {
      const page = await newSpecPage({
        components: [BsToast],
        html: `
          <bs-toast
            toast-id="${toastId}"
            toast-title="${title}"
            stacked
            content=${message}
          />`
      });
      const component = page.root.shadowRoot.querySelector('.bs-toast');
      expect(component.getAttribute('data-stacked')).toBe('');
    });
  });
  describe('Test component class logic', () => {
    let comp;
    beforeEach(() => {
      comp = new BsToast();
    });
    describe('onShownChange()', () => {
      it('should set isShown to true / isDismissed to false when showing', () => {
        comp.onShownChange(true, false);
        expect(comp.isShown).toBe(true);
        expect(comp.isDismissed).toBe(false);
      });
      it('should set isShown to true / isDismissed to true when dismissing', () => {
        comp.onShownChange(false, true);
        expect(comp.isShown).toBe(false);
        expect(comp.isDismissed).toBe(true);
      });
      it('should set isShown to false / isDismissed to false when not showing and never shown', () => {
        comp.onShownChange(false, undefined);
        expect(comp.isShown).toBe(false);
        expect(comp.isDismissed).toBe(false);
      });
    });
    describe('handleDismiss()', () => {
      // Fake-out the timer system for these tests so it's more predictable
      beforeEach(() => jest.useFakeTimers());
      // Clean up timers in the system
      afterEach(() => jest.clearAllTimers());
      it('should set internal state and emit dismissed event', done => {
        const toastId = faker.random.alphaNumeric(20);
        const mockEmitter = {
          emit: (detail) => {
            expect(detail).toContain(toastId);
            expect(comp.isShown).toBe(false);
            expect(comp.isDismissed).toBe(true);
            done();
            return null;
          }
        };
        comp.toastId = toastId;
        comp.dismiss = mockEmitter;
        comp.handleDismiss();
        jest.advanceTimersByTime(200);
      });
      it('should clear dismissal timeout if present', () => {
        // Just capturing event to prevent unnecessary unit test logging
        comp.dismiss = { emit: jest.fn() };
        comp.timer = setTimeout(() => null, 10000);
        comp.handleDismiss();
        expect(comp.timer).toBeUndefined();
      });
    });
    describe('componentDidRender()', () => {
      // Fake-out the timer system for these tests so it's more predictable
      beforeEach(() => jest.useFakeTimers());
      // Clean up timers in the system
      afterEach(() => jest.clearAllTimers());
      // shown / duration > 0
      it('should set dismiss timer when showing and given a duration', () => {
        comp.isShown = true;
        comp.duration = 10000;
        comp.componentDidRender();
        expect(comp.timer).not.toBeUndefined();
      });
      // shown / duration <= 0
      it('should not set dismiss timer when showing and no duration', () => {
        comp.isShown = true;
        comp.duration = 0;
        comp.componentDidRender();
        expect(comp.timer).toBeUndefined();
      });
      // !shown / duration > 0
      it('should not set dismiss timer when not showing', () => {
        comp.isShown = false;
        comp.duration = 10000;
        comp.componentDidRender();
        expect(comp.timer).toBeUndefined();
      });
    });
    describe('getIcon()', () => {
      // warning
      it('should return a warning icon when warning variant', () => {
        comp.variant = 'warning';
        expect(JSON.stringify(comp.getIcon())).toContain('bs-icon-warning');
      });
      // positive
      it('should return a positive icon when positive variant', () => {
        comp.variant = 'positive';
        expect(JSON.stringify(comp.getIcon())).toContain('bs-icon-thumbs-up-stroke');
      });
      // negative
      it('should return negative icon when negative variant', () => {
        comp.variant = 'negative';
        expect(JSON.stringify(comp.getIcon())).toContain('bs-icon-warning');
      });
      // base
      it('should return base icon when no variant given', () => {
        comp.variant = undefined;
        expect(JSON.stringify(comp.getIcon())).toContain('bs-icon-circle-exclamation');
      });
    });
    describe('handleButtonClick()', () => {
      // dismiss clicked
      it('should dismiss when action is the dismiss action', () => {
        const mockDismiss = jest.fn();
        comp.handleDismiss = mockDismiss;
        comp.dismissAction = 'Dismiss';
        comp.handleButtonClick('Dismiss');
        expect(mockDismiss).toHaveBeenCalled();
      });
      // action clicked - event emitted
      it('should fire action event when not the dismiss action', done => {
        const toastId = faker.random.alphaNumeric(20);
        const action = faker.random.word();
        const mockEmitter = {
          emit: (detail) => {
            expect(detail).toContain(toastId);
            expect(detail).toContain(action);
            done();
            return null;
          }
        };
        comp.toastId = toastId;
        comp.actionclick = mockEmitter;
        comp.handleButtonClick(action);
      });
    });
    describe('getButton()', () => {
      // no action, no button
      it('should return no button if no action is given', () => {
        expect(comp.getButton(undefined, undefined)).toBeUndefined();
      });
      // primary
      it('should return a primary button when that type is given', () => {
        const action = faker.random.word();
        const button = JSON.stringify(comp.getButton(action, 'primary'));
        expect(button).toContain('bs-button');
        expect(button).not.toContain('ghost-btn');
        expect(button).not.toContain('text-btn');
        expect(button).toContain(action);
        expect(button).not.toContain('bs-icon-small-caret-right');
      });
      // ghost
      it('should return a ghost button when that type is given', () => {
        const action = faker.random.word();
        const button = JSON.stringify(comp.getButton(action, 'ghost'));
        expect(button).toContain('bs-button');
        expect(button).toContain('ghost-btn');
        expect(button).not.toContain('text-btn');
        expect(button).toContain(action);
        expect(button).not.toContain('bs-icon-small-caret-right');
      });
      // text
      it('should return a text button when that type is given', () => {
        const action = faker.random.word();
        const button = JSON.stringify(comp.getButton(action, 'text'));
        expect(button).toContain('bs-button');
        expect(button).not.toContain('ghost-btn');
        expect(button).toContain('text-btn');
        expect(button).toContain(action);
        expect(button).not.toContain('bs-icon-small-caret-right');
      });
    });
  });
});
//# sourceMappingURL=bs-toast.spec.js.map
