import { nextTick } from 'vue';
import { shallowMount } from '@vue/test-utils';
import VulnerabilityListGraphql from 'ee/security_dashboard/components/shared/vulnerability_report/vulnerability_list_graphql.vue';
import VulnerabilityReport from 'ee/security_dashboard/components/shared/vulnerability_report/vulnerability_report.vue';
import VulnerabilityCounts from 'ee/security_dashboard/components/shared/vulnerability_report/vulnerability_counts.vue';
import VulnerabilityFilters from 'ee/security_dashboard/components/shared/vulnerability_report/vulnerability_filters.vue';
import projectVulnerabilitiesQuery from 'ee/security_dashboard/graphql/queries/project_vulnerabilities.query.graphql';
import { DASHBOARD_TYPES } from 'ee/security_dashboard/store/constants';
import {
  FIELD_PRESETS,
  FIELDS,
  FILTER_PRESETS,
  REPORT_TAB,
  REPORT_TYPE_PRESETS,
} from 'ee/security_dashboard/components/shared/vulnerability_report/constants';

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

  const createWrapper = ({
    type = REPORT_TAB.DEVELOPMENT,
    showProjectFilter = false,
    canAdminVulnerability = false,
    dashboardType = DASHBOARD_TYPES.GROUP,
  } = {}) => {
    wrapper = shallowMount(VulnerabilityReport, {
      propsData: {
        type,
        query: projectVulnerabilitiesQuery,
        showProjectFilter,
      },
      provide: {
        dashboardType,
        canAdminVulnerability,
      },
    });
  };

  const findVulnerabilityCounts = () => wrapper.findComponent(VulnerabilityCounts);
  const findVulnerabilityFilters = () => wrapper.findComponent(VulnerabilityFilters);
  const findVulnerabilityListGraphql = () => wrapper.findComponent(VulnerabilityListGraphql);

  afterEach(() => {
    wrapper.destroy();
  });

  describe('vulnerability filters component', () => {
    it('will pass data from filters-changed event to the counts and list components', async () => {
      createWrapper();
      const data = { a: 1 };
      findVulnerabilityFilters().vm.$emit('filters-changed', data);
      await nextTick();

      expect(findVulnerabilityCounts().props('filters')).toBe(data);
      expect(findVulnerabilityListGraphql().props('filters')).toBe(data);
    });

    it('will filter by everything except cluster image scanning results for the development report', async () => {
      createWrapper({ type: REPORT_TAB.DEVELOPMENT });
      findVulnerabilityFilters().vm.$emit('filters-changed', {});
      await nextTick();

      expect(findVulnerabilityListGraphql().props('filters').reportType).toBe(
        REPORT_TYPE_PRESETS.DEVELOPMENT,
      );
    });

    it('will filter by cluster image scanning results for the operational report', async () => {
      createWrapper({ type: REPORT_TAB.OPERATIONAL });
      findVulnerabilityFilters().vm.$emit('filters-changed', {});
      await nextTick();

      expect(findVulnerabilityListGraphql().props('filters').reportType).toBe(
        REPORT_TYPE_PRESETS.OPERATIONAL,
      );
    });

    it.each`
      dashboardType               | type                      | expectedFilters
      ${DASHBOARD_TYPES.GROUP}    | ${REPORT_TAB.DEVELOPMENT} | ${FILTER_PRESETS.DEVELOPMENT}
      ${DASHBOARD_TYPES.INSTANCE} | ${REPORT_TAB.OPERATIONAL} | ${FILTER_PRESETS.OPERATIONAL}
      ${DASHBOARD_TYPES.PROJECT}  | ${REPORT_TAB.DEVELOPMENT} | ${FILTER_PRESETS.DEVELOPMENT_PROJECT}
    `(
      'shows the expected filter for the $type $dashboardType report',
      ({ dashboardType, type, expectedFilters }) => {
        createWrapper({ dashboardType, type });

        expect(findVulnerabilityFilters().props('filters')).toEqual(expectedFilters);
      },
    );
  });

  describe('vulnerability list GraphQL component', () => {
    it('gets passed the query prop', () => {
      createWrapper();

      expect(findVulnerabilityListGraphql().props('query')).toBe(projectVulnerabilitiesQuery);
    });

    it.each`
      type                      | expectedFields
      ${REPORT_TAB.DEVELOPMENT} | ${FIELD_PRESETS.DEVELOPMENT}
      ${REPORT_TAB.OPERATIONAL} | ${FIELD_PRESETS.OPERATIONAL}
    `('gets passed the expected fields prop for the $type report', ({ type, expectedFields }) => {
      createWrapper({ type });

      expect(findVulnerabilityListGraphql().props('fields')).toEqual(expectedFields);
    });

    it('gets passed the checkbox field if the user can admin vulnerability', () => {
      createWrapper({ canAdminVulnerability: true });

      expect(findVulnerabilityListGraphql().props('fields')).toContainEqual(FIELDS.CHECKBOX);
    });

    it.each([true, false])(
      'gets passed the expected value for the should show project namespace prop',
      (showProjectFilter) => {
        createWrapper({ showProjectFilter });

        expect(findVulnerabilityListGraphql().props('showProjectNamespace')).toBe(
          showProjectFilter,
        );
      },
    );
  });
});
