import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import Footer from 'ee/vulnerabilities/components/footer.vue';
import Header from 'ee/vulnerabilities/components/header.vue';
import Main from 'ee/vulnerabilities/components/vulnerability.vue';
import Details from 'ee/vulnerabilities/components/vulnerability_details.vue';

const mockAxios = new AxiosMockAdapter();

describe('Vulnerability', () => {
  let wrapper;

  const vulnerability = {
    id: 1,
    created_at: new Date().toISOString(),
    report_type: 'sast',
    state: 'detected',
    create_mr_url: '/create_mr_url',
    new_issue_url: '/new_issue_url',
    project_fingerprint: 'abc123',
    pipeline: {
      id: 2,
      created_at: new Date().toISOString(),
      url: 'pipeline_url',
      sourceBranch: 'main',
    },
    description: 'description',
    identifiers: 'identifiers',
    links: 'links',
    location: 'location',
    name: 'name',
    project: {
      full_path: '/project_full_path',
      full_name: 'Test Project',
    },
    discussions_url: '/discussion_url',
    notes_url: '/notes_url',
    can_modify_related_issues: false,
    related_issues_help_path: '/help_path',
    merge_request_feedback: null,
    issue_feedback: null,
    remediation: null,
  };

  const createWrapper = () => {
    wrapper = shallowMount(Main, {
      propsData: {
        vulnerability,
      },
    });
  };

  afterEach(() => {
    wrapper.destroy();
    wrapper = null;
    mockAxios.reset();
  });

  beforeEach(createWrapper);

  const findHeader = () => wrapper.find(Header);
  const findDetails = () => wrapper.find(Details);
  const findFooter = () => wrapper.find(Footer);

  describe('default behavior', () => {
    it('consists of header, details, and footer', () => {
      expect(findHeader().exists()).toBe(true);
      expect(findDetails().exists()).toBe(true);
      expect(findFooter().exists()).toBe(true);
    });

    it('passes the correct properties to the children', () => {
      expect(findHeader().props('initialVulnerability')).toBe(vulnerability);
      expect(findDetails().props('vulnerability')).toBe(vulnerability);
      expect(findFooter().props('vulnerability')).toBe(vulnerability);
    });
  });

  describe('vulnerability state change event', () => {
    let fetchDiscussions;
    let refreshVulnerability;

    beforeEach(() => {
      fetchDiscussions = jest.fn();
      refreshVulnerability = jest.fn();

      findHeader().vm.refreshVulnerability = refreshVulnerability;
      findFooter().vm.fetchDiscussions = fetchDiscussions;
    });

    it('updates the footer notes when the vulnerbility state was changed', () => {
      findHeader().vm.$emit('vulnerability-state-change');

      expect(fetchDiscussions).toHaveBeenCalledTimes(1);
      expect(refreshVulnerability).not.toHaveBeenCalled();
    });

    it('updates the header when the footer received a state-change note', () => {
      findFooter().vm.$emit('vulnerability-state-change');

      expect(fetchDiscussions).not.toHaveBeenCalled();
      expect(refreshVulnerability).toHaveBeenCalledTimes(1);
    });
  });
});
