Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,375 @@
import { mount } from '@vue/test-utils';
import { createStore } from 'vuex';
import ImageDetails from '../ImageDetails.vue';

// Define constants locally to avoid import issues
const RESOURCE = {
IMAGE: "sbombastic.rancher.io.image"
};

describe('ImageDetails', () => {
let store: any;
let wrapper: any;

const mockImageData = {
metadata: { name: 'test-image' },
spec: {
repository: 'test-repo',
registry: 'test-registry',
scanResult: {
critical: 5,
high: 10,
medium: 15,
low: 8,
none: 2
}
}
};

beforeEach(() => {
store = createStore({
modules: {
cluster: {
namespaced: true,
getters: {
'all': () => (type: string) => {
if (type === RESOURCE.IMAGE) return [mockImageData];
return [];
}
},
actions: {
'findAll': jest.fn()
}
}
}
});

wrapper = mount(ImageDetails, {
global: {
plugins: [store],
mocks: {
$route: {
params: {
cluster: 'test-cluster',
id: 'test-image'
}
},
$router: {
push: jest.fn()
},
$t: (key: string) => key,
$store: store
},
stubs: {
RouterLink: {
template: '<a><slot /></a>',
props: ['to']
},
BadgeState: {
template: '<span class="badge-state"><slot /></span>',
props: ['color', 'label']
},
SortableTable: {
template: '<div class="sortable-table"><slot name="header-left" /><slot name="search" /></div>',
props: ['rows', 'headers', 'hasAdvancedFiltering', 'namespaced', 'rowActions', 'search']
},
ScoreBadge: {
template: '<span class="score-badge"><slot /></span>',
props: ['score', 'scoreType']
},
BarChart: {
template: '<div class="bar-chart"></div>',
props: ['chartData', 'description', 'colorPrefix']
},
Checkbox: {
template: '<input type="checkbox" class="checkbox" />',
props: ['value', 'label']
}
}
}
});
});

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

describe('Component Initialization', () => {
it('should render the component', () => {
expect(wrapper.exists()).toBe(true);
});

it('should display the correct title with image name', () => {
const title = wrapper.find('.title');
expect(title.exists()).toBe(true);
expect(title.text()).toContain('test-image');
});

it('should display the severity badge', () => {
const severityBadge = wrapper.find('.severity-badge');
expect(severityBadge.exists()).toBe(true);
});

it('should display the download report button', () => {
const downloadButton = wrapper.find('.btn.role-primary');
expect(downloadButton.exists()).toBe(true);
expect(downloadButton.text()).toContain('imageScanner.images.downloadReport');
});
});

describe('Image Information Section', () => {
it('should display image details in info grid', () => {
const infoGrid = wrapper.find('.info-grid');
expect(infoGrid.exists()).toBe(true);
});

it('should show basic image properties', () => {
const infoItems = wrapper.findAll('.info-item');
expect(infoItems.length).toBeGreaterThan(0);
});

it('should toggle show all properties when clicked', async () => {
const showPropertiesLink = wrapper.find('.show-properties-link a');
expect(showPropertiesLink.exists()).toBe(true);

await showPropertiesLink.trigger('click');
expect(wrapper.vm.showAllProperties).toBe(true);

await showPropertiesLink.trigger('click');
expect(wrapper.vm.showAllProperties).toBe(false);
});

it('should show additional properties when showAllProperties is true', async () => {
wrapper.vm.showAllProperties = true;
await wrapper.vm.$nextTick();

// These should be visible when showAllProperties is true
expect(wrapper.vm.showAllProperties).toBe(true);

// Check that additional properties are rendered
const infoItems = wrapper.findAll('.info-item');
expect(infoItems.length).toBeGreaterThan(10); // Should have more items when expanded
});
});

describe('Summary Section', () => {
it('should render vulnerabilities section', () => {
const vulnerabilitiesSection = wrapper.find('.vulnerabilities-section');
expect(vulnerabilitiesSection.exists()).toBe(true);
});

it('should render severity section with BarChart', () => {
const severitySection = wrapper.find('.severity-section');
expect(severitySection.exists()).toBe(true);

const barChart = wrapper.find('.bar-chart');
expect(barChart.exists()).toBe(true);
});

it('should display most severe vulnerabilities', () => {
const vulnerabilitiesList = wrapper.find('.vulnerabilities-list');
expect(vulnerabilitiesList.exists()).toBe(true);
});
});

describe('Vulnerability Table', () => {
it('should render SortableTable component', () => {
const sortableTable = wrapper.find('.sortable-table');
expect(sortableTable.exists()).toBe(true);
});

it('should display download custom report button', () => {
const downloadCustomButton = wrapper.find('.table-header-actions .btn.role-primary');
expect(downloadCustomButton.exists()).toBe(true);
expect(downloadCustomButton.text()).toContain('imageScanner.images.buttons.downloadCustomReport');
});

it('should show selected count when vulnerabilities are selected', async () => {
wrapper.vm.selectedVulnerabilities = ['CVE-2017-5337', 'CVE-2018-1000007'];
await wrapper.vm.$nextTick();

const selectedCount = wrapper.find('.selected-count');
expect(selectedCount.exists()).toBe(true);
expect(selectedCount.text()).toContain('2');
});
});

describe('Computed Properties', () => {
it('should calculate total vulnerabilities correctly', () => {
wrapper.vm.severityDistribution = {
critical: 5,
high: 10,
medium: 15,
low: 8,
none: 2
};

expect(wrapper.vm.totalVulnerabilities).toBe(40);
});

it('should determine overall severity correctly', () => {
wrapper.vm.severityDistribution = {
critical: 5,
high: 0,
medium: 0,
low: 0,
none: 0
};

expect(wrapper.vm.overallSeverity).toBe('critical');
});

it('should return none when no vulnerabilities', () => {
wrapper.vm.severityDistribution = {
critical: 0,
high: 0,
medium: 0,
low: 0,
none: 0
};

expect(wrapper.vm.overallSeverity).toBe('none');
});

it('should calculate severity distribution with percentages', () => {
wrapper.vm.severityDistribution = {
critical: 10,
high: 20,
medium: 0,
low: 0,
none: 0
};

const distribution = wrapper.vm.severityDistributionWithPercentages;
expect(distribution.critical.percentage).toBe('33.3');
expect(distribution.high.percentage).toBe('66.7');
});

it('should filter vulnerabilities by CVE search', () => {
wrapper.vm.filters.cveSearch = 'CVE-2017';
const filtered = wrapper.vm.filteredVulnerabilities;
expect(filtered.every(v => v.cveId.includes('CVE-2017'))).toBe(true);
});

it('should filter vulnerabilities by score', () => {
wrapper.vm.filters.score = '9.0';
const filtered = wrapper.vm.filteredVulnerabilities;
expect(filtered.every(v => {
const score = parseFloat(v.score.split(' ')[0]);
return score >= 9.0;
})).toBe(true);
});

it('should filter vulnerabilities by package search', () => {
wrapper.vm.filters.packageSearch = 'tomcat';
const filtered = wrapper.vm.filteredVulnerabilities;
expect(filtered.every(v => v.package.toLowerCase().includes('tomcat'))).toBe(true);
});

it('should filter vulnerabilities by fix availability', () => {
wrapper.vm.filters.fixAvailable = 'available';
const filtered = wrapper.vm.filteredVulnerabilities;
expect(filtered.every(v => v.fixAvailable === true)).toBe(true);
});

it('should filter vulnerabilities by severity', () => {
wrapper.vm.filters.severity = 'critical';
const filtered = wrapper.vm.filteredVulnerabilities;
expect(filtered.every(v => v.severity === 'critical')).toBe(true);
});

it('should filter vulnerabilities by exploitability', () => {
wrapper.vm.filters.exploitability = 'affected';
const filtered = wrapper.vm.filteredVulnerabilities;
expect(filtered.every(v => v.exploitability === 'affected')).toBe(true);
});
});

describe('Methods', () => {
it('should return correct severity color', () => {
expect(wrapper.vm.getSeverityColor('critical')).toBe('critical-severity');
expect(wrapper.vm.getSeverityColor('high')).toBe('bg-error');
expect(wrapper.vm.getSeverityColor('medium')).toBe('bg-warning');
expect(wrapper.vm.getSeverityColor('low')).toBe('bg-warning');
expect(wrapper.vm.getSeverityColor('none')).toBe('bg-info');
});

it('should return correct severity bar color', () => {
expect(wrapper.vm.getSeverityBarColor('critical')).toBe('#850917');
expect(wrapper.vm.getSeverityBarColor('high')).toBe('#DE2136');
expect(wrapper.vm.getSeverityBarColor('medium')).toBe('#FF8533');
expect(wrapper.vm.getSeverityBarColor('low')).toBe('#FDD835');
expect(wrapper.vm.getSeverityBarColor('none')).toBe('#E0E0E0');
});

it('should handle selection change', () => {
const selected = ['CVE-2017-5337', 'CVE-2018-1000007'];
wrapper.vm.onSelectionChange(selected);
expect(wrapper.vm.selectedVulnerabilities).toEqual(selected);
});

it('should handle download full report', () => {
const consoleSpy = jest.spyOn(console, 'log').mockImplementation();
wrapper.vm.downloadFullReport();
expect(consoleSpy).toHaveBeenCalledWith('Downloading full report for:', wrapper.vm.imageName);
consoleSpy.mockRestore();
});

it('should handle download custom report', () => {
const consoleSpy = jest.spyOn(console, 'log').mockImplementation();
wrapper.vm.downloadCustomReport();
expect(consoleSpy).toHaveBeenCalledWith('Downloading custom report with filters:', wrapper.vm.filters);
consoleSpy.mockRestore();
});

it('should calculate most severe vulnerabilities correctly', () => {
// Ensure vulnerability details are loaded first
wrapper.vm.vulnerabilityDetails = wrapper.vm.getMockVulnerabilityDetails();
wrapper.vm.calculateMostSevereVulnerabilities();
expect(wrapper.vm.mostSevereVulnerabilities).toHaveLength(5);

// Should be sorted by score descending
const scores = wrapper.vm.mostSevereVulnerabilities.map(v => parseFloat(v.score.split(' ')[0]));
for (let i = 1; i < scores.length; i++) {
expect(scores[i-1]).toBeGreaterThanOrEqual(scores[i]);
}
});
});

describe('Component Data', () => {
it('should have correct initial data properties', () => {
expect(wrapper.vm.PRODUCT_NAME).toBeDefined();
expect(wrapper.vm.RESOURCE).toBeDefined();
expect(wrapper.vm.PAGE).toBeDefined();
expect(wrapper.vm.VULNERABILITY_DETAILS_TABLE).toBeDefined();
expect(wrapper.vm.showAllProperties).toBe(false);
expect(wrapper.vm.selectedVulnerabilities).toEqual([]);
});

it('should have correct filter defaults', () => {
expect(wrapper.vm.filters.cveSearch).toBe('');
expect(wrapper.vm.filters.score).toBe('');
expect(wrapper.vm.filters.packageSearch).toBe('');
expect(wrapper.vm.filters.fixAvailable).toBe('any');
expect(wrapper.vm.filters.severity).toBe('any');
expect(wrapper.vm.filters.exploitability).toBe('any');
});
});

describe('Mock Data', () => {
it('should generate mock vulnerability details', () => {
const mockData = wrapper.vm.getMockVulnerabilityDetails();
expect(Array.isArray(mockData)).toBe(true);
expect(mockData.length).toBeGreaterThan(0);

// Check structure of first vulnerability
const firstVuln = mockData[0];
expect(firstVuln).toHaveProperty('cveId');
expect(firstVuln).toHaveProperty('score');
expect(firstVuln).toHaveProperty('package');
expect(firstVuln).toHaveProperty('fixAvailable');
expect(firstVuln).toHaveProperty('severity');
expect(firstVuln).toHaveProperty('exploitability');
});
});
});
Loading