diff --git a/pkg/sbombastic-image-vulnerability-scanner/components/CveDetails.vue b/pkg/sbombastic-image-vulnerability-scanner/components/CveDetails.vue index 463ba7b..369122f 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/components/CveDetails.vue +++ b/pkg/sbombastic-image-vulnerability-scanner/components/CveDetails.vue @@ -249,8 +249,8 @@ export default {
- {{ t('imageScanner.vulnerabilities.title') }}: - {{ $route.params.id }} + + {{ t('imageScanner.vulnerabilities.title') }}: {{ $route.params.id }}
{{ t('imageScanner.imageDetails.layers') }}: - {{ imageDetails.layers || '12' }} + {{ imageDetails.layers?.length || '0' }}
@@ -411,7 +411,8 @@ export default { const metadata = this.currentImage.imageMetadata; if (metadata?.registryURI && metadata?.repository && metadata?.tag) { - return `${metadata.registryURI}/${metadata.repository}:${metadata.tag}`; + // return `${metadata.registryURI}/${metadata.repository}:${metadata.tag}`; + return `${metadata.repository.split("/")[0]}:${metadata.tag}`; } // Fallback to the hash ID if metadata is not available diff --git a/pkg/sbombastic-image-vulnerability-scanner/components/InstallView3.vue b/pkg/sbombastic-image-vulnerability-scanner/components/InstallView3.vue index 6f400fc..c845de8 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/components/InstallView3.vue +++ b/pkg/sbombastic-image-vulnerability-scanner/components/InstallView3.vue @@ -27,7 +27,7 @@ export default { [] }, - reloadFn: { - type: Function, - default: () => {} - } }, methods: { async startScan() { @@ -54,10 +50,6 @@ export default { title: this.t('imageScanner.registries.messages.registryScanFailed'), message: e.message, }); - } finally { - setTimeout(() => { - this.reloadFn(true); - }, 2000); } }); }, diff --git a/pkg/sbombastic-image-vulnerability-scanner/config/sbombastic-image-vulnerability-scanner.ts b/pkg/sbombastic-image-vulnerability-scanner/config/sbombastic-image-vulnerability-scanner.ts index e1ca271..c5c1cb3 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/config/sbombastic-image-vulnerability-scanner.ts +++ b/pkg/sbombastic-image-vulnerability-scanner/config/sbombastic-image-vulnerability-scanner.ts @@ -33,10 +33,11 @@ export function init($plugin: any, store: any) { route: { name: `c-cluster-${PRODUCT_NAME}-${PAGE.REGISTRIES}`, params: { - product: PRODUCT_NAME + product: PRODUCT_NAME, + resource: RESOURCE.REGISTRY, }, meta: { pkg: PRODUCT_NAME, product: PRODUCT_NAME } - } + }, }); virtualType({ @@ -52,18 +53,18 @@ export function init($plugin: any, store: any) { } }); - virtualType({ - labelKey: "imageScanner.vulnerabilities.title", - name: PAGE.VULNERABILITIES, - namespaced: false, - route: { - name: `c-cluster-${PRODUCT_NAME}-${PAGE.VULNERABILITIES}`, - params: { - product: PRODUCT_NAME, - }, - meta: { pkg: PRODUCT_NAME, product: PRODUCT_NAME }, - }, - }); + // virtualType({ + // labelKey: "imageScanner.vulnerabilities.title", + // name: PAGE.VULNERABILITIES, + // namespaced: false, + // route: { + // name: `c-cluster-${PRODUCT_NAME}-${PAGE.VULNERABILITIES}`, + // params: { + // product: PRODUCT_NAME, + // }, + // meta: { pkg: PRODUCT_NAME, product: PRODUCT_NAME }, + // }, + // }); virtualType({ labelKey: "imageScanner.vexManagement.title", @@ -80,13 +81,13 @@ export function init($plugin: any, store: any) { weightType(PAGE.DASHBOARD, 98, true); weightType(PAGE.IMAGES, 97, true); - weightType(PAGE.VULNERABILITIES, 96, true); + // weightType(PAGE.VULNERABILITIES, 96, true); weightType(PAGE.VEX_MANAGEMENT, 95, true); basicType([ PAGE.DASHBOARD, PAGE.IMAGES, - PAGE.VULNERABILITIES, + // PAGE.VULNERABILITIES, ]); // Prepend spaces on group name, as Rancher 2.12 render group name algin with sidemenu basicType([PAGE.REGISTRIES, PAGE.VEX_MANAGEMENT], '    Advanced'); diff --git a/pkg/sbombastic-image-vulnerability-scanner/config/table-headers.ts b/pkg/sbombastic-image-vulnerability-scanner/config/table-headers.ts index 2c52384..e029a88 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/config/table-headers.ts +++ b/pkg/sbombastic-image-vulnerability-scanner/config/table-headers.ts @@ -27,7 +27,8 @@ export const REGISTRY_SCAN_TABLE = [ { name: "scanInterval", labelKey: "imageScanner.registries.registrytable.header.schedule", - value: (row: any) => `Every ${row.spec.scanInterval}`, + value: "spec.scanInterval", + formatter: "ScanInterval", sort: "spec.scanInterval", }, { diff --git a/pkg/sbombastic-image-vulnerability-scanner/formatters/ImageNameCell.vue b/pkg/sbombastic-image-vulnerability-scanner/formatters/ImageNameCell.vue index 9b9325d..4187671 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/formatters/ImageNameCell.vue +++ b/pkg/sbombastic-image-vulnerability-scanner/formatters/ImageNameCell.vue @@ -25,7 +25,8 @@ export default { displayName() { // For real Kubernetes resources, show human-readable reference if (this.row.imageMetadata?.repository) { - return `${this.row.imageMetadata.registryURI}/${this.row.imageMetadata.repository}:${this.row.imageMetadata.tag}`; + // return `${this.row.imageMetadata.registryURI}/${this.row.imageMetadata.repository}:${this.row.imageMetadata.tag}`; + return `${this.row.imageMetadata.repository.split("/")[0]}:${this.row.imageMetadata.tag}`; } // For mock data, show the metadata name return this.row.metadata.name; diff --git a/pkg/sbombastic-image-vulnerability-scanner/formatters/ScanInterval.vue b/pkg/sbombastic-image-vulnerability-scanner/formatters/ScanInterval.vue new file mode 100644 index 0000000..8cc405e --- /dev/null +++ b/pkg/sbombastic-image-vulnerability-scanner/formatters/ScanInterval.vue @@ -0,0 +1,29 @@ + + + + \ No newline at end of file diff --git a/pkg/sbombastic-image-vulnerability-scanner/l10n/en-us.yaml b/pkg/sbombastic-image-vulnerability-scanner/l10n/en-us.yaml index 839c4ef..57dcc27 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/l10n/en-us.yaml +++ b/pkg/sbombastic-image-vulnerability-scanner/l10n/en-us.yaml @@ -275,7 +275,7 @@ imageScanner: medium: Medium low: Low none: None - unknown: Unknown + unknown: None suppressed: Suppressed status: pending: Pending @@ -302,6 +302,7 @@ imageScanner: schedule: Every {i} reload: Reload any: Any + every: Every typeLabel: sbombastic.rancher.io.registry: Registries configuration diff --git a/pkg/sbombastic-image-vulnerability-scanner/list/sbombastic.rancher.io.registry.vue b/pkg/sbombastic-image-vulnerability-scanner/list/sbombastic.rancher.io.registry.vue new file mode 100644 index 0000000..85f34ca --- /dev/null +++ b/pkg/sbombastic-image-vulnerability-scanner/list/sbombastic.rancher.io.registry.vue @@ -0,0 +1,597 @@ + + + + + \ No newline at end of file diff --git a/pkg/sbombastic-image-vulnerability-scanner/list/sbombastic.rancher.io.registry_bak.vue b/pkg/sbombastic-image-vulnerability-scanner/list/sbombastic.rancher.io.registry_bak.vue deleted file mode 100644 index f1b2972..0000000 --- a/pkg/sbombastic-image-vulnerability-scanner/list/sbombastic.rancher.io.registry_bak.vue +++ /dev/null @@ -1,78 +0,0 @@ - - - \ No newline at end of file diff --git a/pkg/sbombastic-image-vulnerability-scanner/models/sbombastic.rancher.io.registry.js b/pkg/sbombastic-image-vulnerability-scanner/models/sbombastic.rancher.io.registry.js index 66b51da..b8a2ca4 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/models/sbombastic.rancher.io.registry.js +++ b/pkg/sbombastic-image-vulnerability-scanner/models/sbombastic.rancher.io.registry.js @@ -46,12 +46,6 @@ export default class Registry extends SteveModel { title: this.$rootGetters['i18n/t']('imageScanner.registries.messages.registryScanFailed'), message: e.message, }, { root: true }); - } finally { - if (target.refreshFn instanceof Function) { - setTimeout(() => { - target.refreshFn(); - }, 2000); - } } }, }; diff --git a/pkg/sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/ImageOverview.vue b/pkg/sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/ImageOverview.vue index 7b0a4ac..bf784c5 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/ImageOverview.vue +++ b/pkg/sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/ImageOverview.vue @@ -362,8 +362,9 @@ this.rows.push({ id: report.id, metadata: { - name: `${report.imageMetadata.registry}:${report.imageMetadata.tag}` + name: report.metadata.name, }, + imageMetadata: report.imageMetadata, spec: { isBaseImage: true, hasAffectedPackages: false, @@ -396,6 +397,7 @@ currRepo.images.push( { metadata: { name: image.metadata.name }, + imageMetadata: image.imageMetadata, scanResult: currImageScanResult, } ); @@ -408,7 +410,8 @@ cveCntByRepo: currImageScanResult, images: [ { - metadata: { name: image.metadata.name} , + metadata: { name: image.metadata.name }, + imageMetadata: image.imageMetadata, scanResult: currImageScanResult, } ] @@ -421,6 +424,7 @@ }); return { imageName: image.metadata.name, + mageMetadata: image.imageMetadata, cveCnt: image.spec.scanResult, } }); diff --git a/pkg/sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/RegistriesConfiguration.vue b/pkg/sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/RegistriesConfiguration.vue index 759bfbc..2f946d6 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/RegistriesConfiguration.vue +++ b/pkg/sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/RegistriesConfiguration.vue @@ -100,7 +100,7 @@ - - + @@ -198,15 +198,7 @@ }, async fetch() { - this.registriesCRD = await this.$store.dispatch('cluster/findAll', { type: RESOURCE.REGISTRY }); - if (this.$store.getters['cluster/canList'](RESOURCE.SCAN_JOB)) { - await this.$store.dispatch('cluster/findAll', { type: RESOURCE.SCAN_JOB }); - } - await this.loadData(false); - clearInterval(this.keepAliveTimer); - this.keepAliveTimer = setInterval(async () => { - await this.loadData(true); - }, 20 * 1000); + await this.loadData(); }, beforeUnmount() { clearInterval(this.keepAliveTimer); @@ -218,14 +210,29 @@ }, 500), deep: true, }, + // registriesCRD: { + // async handler() { + // await this.preprocessData(); + // }, + // immediate: true, + // deep: true, + // } }, methods: { - async loadData(isReloading) { + async loadData() { + this.registriesCRD = await this.$store.dispatch('cluster/findAll', { type: RESOURCE.REGISTRY }); + if (this.$store.getters['cluster/canList'](RESOURCE.SCAN_JOB)) { + await this.$store.dispatch('cluster/findAll', { type: RESOURCE.SCAN_JOB }); + } + await this.preprocessData(); + clearInterval(this.keepAliveTimer); + this.keepAliveTimer = setInterval(async () => { + await this.preprocessData(); + }, 20 * 1000); + }, + async preprocessData() { this.registryStatusList = []; this.statusSummary = {}; - if (isReloading) { - this.registriesCRD = this.$store.getters['cluster/all'](RESOURCE.REGISTRY); - } this.rows = this.registriesCRD; const summaryData = this.getSummaryData(this.registriesCRD); this.registryStatusList = summaryData.registryStatusList; @@ -251,7 +258,7 @@ this.selectedRows = selected || []; }, async promptRemoveRegistry() { - const table = this.$refs.registryTable; + const table = this.$refs.registryTable.$refs.table.$refs.table; const act = findBy(table.availableActions, 'action', 'promptRemove'); if ( act ) { table.setBulkActionOfInterest(act); @@ -272,7 +279,7 @@ registriesCRD.forEach((rec, index) => { // Summarize the data for Latest status updates panel - const scanRec = _.cloneDeep(rec.scanRec || {}); + const scanRec = rec.scanRec//_.cloneDeep(rec.scanRec || {}); console.log('scanRec', scanRec); registryStatusList.push({ registryName: rec.metadata.name, @@ -328,24 +335,9 @@ const scanJobs = await this.$store.dispatch(`cluster/findPage`, { type: RESOURCE.SCAN_JOB, opt }); return scanJobs; }, - }, - computed: { - schema() { - return this.$store.getters['cluster/schemaFor'](RESOURCE.REGISTRY); - }, - canPaginate() { - const args = { id: RESOURCE.REGISTRY }; - return this.$store.getters[`cluster/paginationEnabled`]?.(args); - }, - latestUpdateDateText() { - return day(new Date(this.latestUpdateTime).getTime()).format('MMM D, YYYY'); - }, - latestUpdateTimeText() { - return day(new Date(this.latestUpdateTime).getTime()).format('h:mm A'); - }, - filteredRows() { + filterRowsLocal(rows) { const filters = this.debouncedFilters; - return this.rows.filter(row => { + return rows.filter(row => { const registryMatch = !filters.registrySearch || row.metadata?.name?.toLowerCase().includes(filters.registrySearch.toLowerCase()); @@ -367,7 +359,58 @@ return registryMatch && namespaceMatch && uriMatch && repoMatch && statusMatch; }); - } + }, + filterRowsApi(pagination) { + const filters = this.debouncedFilters; + const colFields = [{ + field: 'metadata.name', + value: filters.registrySearch, + equals: true, + exact: false, + }, + { + field: 'metadata.namespace', + value: filters.namespaceSearch, + equals: true, + exact: false, + }, + { + field: 'spec.uri', + value: filters.uriSearch, + equals: true, + exact: false, + }, + { + field: 'spec.repositories', + value: filters.repositorySearch, + equals: true, + exact: false, + }, + { + field: 'scanRec.currStatus', + value: typeof filters.statusSearch === 'object' ? filters.statusSearch.value : filters.statusSearch, + equals: true, + exact: false, + }]; + const colFilter = PaginationParamFilter.createMultipleFields(colFields); + pagination.filters.push(colFilter); + return pagination; + }, + }, + computed: { + schema() { + return this.$store.getters['cluster/schemaFor'](RESOURCE.REGISTRY); + }, + canPaginate() { + const args = { id: RESOURCE.REGISTRY }; + return this.$store.getters[`cluster/paginationEnabled`]?.(args); + }, + latestUpdateDateText() { + return day(new Date(this.latestUpdateTime).getTime()).format('MMM D, YYYY'); + }, + latestUpdateTimeText() { + return day(new Date(this.latestUpdateTime).getTime()).format('h:mm A'); + }, }, } diff --git a/pkg/sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/__tests__/RegistriesConfiguration.spec.ts b/pkg/sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/__tests__/RegistriesConfiguration.spec.ts index 7732780..bafc0ac 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/__tests__/RegistriesConfiguration.spec.ts +++ b/pkg/sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/__tests__/RegistriesConfiguration.spec.ts @@ -1,5 +1,6 @@ import { shallowMount, flushPromises } from '@vue/test-utils'; import registries from '../RegistriesConfiguration.vue'; +import { RESOURCE } from '@pkg/types'; describe('registries.vue', () => { let storeMock: any; @@ -50,9 +51,9 @@ describe('registries.vue', () => { expect(wrapper.find('.title').text()).toBe('imageScanner.registries.title'); }); - it('calls loadData when refresh is clicked', async () => { + it('calls preprocessData when refresh is clicked', async () => { const wrapper = factory(); - const refreshSpy = jest.spyOn(wrapper.vm, 'loadData').mockResolvedValue(); + const refreshSpy = jest.spyOn(wrapper.vm, 'preprocessData').mockResolvedValue(); await wrapper.find('button[aria-label="Refresh data"]').trigger('click'); expect(refreshSpy).toHaveBeenCalled(); @@ -72,14 +73,11 @@ describe('registries.vue', () => { }); }); - it('updates rows after loadData', async () => { + it('updates rows after preprocessData', async () => { const wrapper = factory(); - storeMock.getters['cluster/all'] - .mockReturnValueOnce([{ metadata: { name: 'reg1', namespace: 'ns1' }, spec: {} }]) // registries - .mockReturnValueOnce([]); // scanJobs - - await wrapper.vm.loadData(true); + (wrapper.vm.registriesCRD as any[]) = [{ metadata: { name: 'reg1', namespace: 'ns1' }, spec: {} }]; // registries + await wrapper.vm.preprocessData(); await flushPromises(); // Ensure rows is typed as any[] for test purposes @@ -108,26 +106,6 @@ describe('registries.vue', () => { wrapper.vm.filterByStatus('pending'); expect(wrapper.vm.filters.statusSearch).toBe('pending'); }); - it('filters rows correctly by registry, namespace, uri, repository, and status', () => { - const wrapper = factory(); - (wrapper.vm.rows as any[]) = [{ - metadata: { name: 'reg1', namespace: 'ns1' }, - spec: { uri: 'http://my-uri', repositories: ['repo1'] }, - scanRec: { currStatus: 'complete' } - }]; - - wrapper.vm.filters = { - registrySearch: 'reg1', - namespaceSearch: 'ns1', - uriSearch: 'uri', - repositorySearch: 'repo1', - statusSearch: 'complete' - }; - - const filtered = wrapper.vm.filteredRows; - expect(filtered).toHaveLength(1); - expect(filtered[0].metadata.name).toBe('reg1'); - }); it('formats latest update time correctly', () => { const wrapper = factory(); wrapper.vm.latestUpdateTime = new Date('2023-01-01T12:34:56Z'); @@ -155,4 +133,147 @@ describe('registries.vue', () => { expect(storeMock.dispatch).toHaveBeenCalledWith('cluster/findPage', expect.any(Object)); expect(result).toEqual([scanJob]); }); + + it('filters rows locally based on filters', () => { + const wrapper = factory(); + wrapper.vm.debouncedFilters = { + registrySearch: 'reg1', + namespaceSearch: '', + uriSearch: '', + repositorySearch: '', + statusSearch: 'any' + }; + + const rows = [ + { metadata: { name: 'reg1', namespace: 'ns1' }, spec: { uri: 'u1', repositories: [] }, scanRec: { currStatus: 'pending' } }, + { metadata: { name: 'reg2', namespace: 'ns2' }, spec: { uri: 'u2', repositories: [] }, scanRec: { currStatus: 'complete' } } + ]; + + const result = wrapper.vm.filterRowsLocal(rows); + expect(result).toHaveLength(1); + expect(result[0].metadata.name).toBe('reg1'); + }); + + it('applies API filters correctly in filterRowsApi', () => { + const wrapper = factory(); + wrapper.vm.debouncedFilters = { + registrySearch: 'r1', + namespaceSearch: 'ns1', + uriSearch: 'uri', + repositorySearch: 'repo', + statusSearch: 'pending', + }; + + const pagination = { filters: [] }; + const result = wrapper.vm.filterRowsApi(pagination); + + expect(result.filters.length).toBeGreaterThan(0); + expect(result.filters[0]).toBeDefined(); + }); + + it('preprocessData computes status summary and registry list', async () => { + const wrapper = factory(); + (wrapper.vm.registriesCRD as any[]) = [ + { metadata: { name: 'reg1', namespace: 'ns1', creationTimestamp: new Date().toISOString() }, + spec: { uri: 'http://uri' }, + scanRec: { currStatus: 'failed', previousStatus: 'pending', lastTransitionTime: new Date().toISOString() } + } + ]; + + await wrapper.vm.preprocessData(); + + expect(wrapper.vm.registryStatusList.length).toBeGreaterThan(0); + expect(wrapper.vm.statusSummary.failed).toBe(1); + }); + + it('calls store dispatches and preprocessData in loadData', async () => { + const wrapper = factory(); + const preprocessSpy = jest.spyOn(wrapper.vm, 'preprocessData').mockResolvedValue(); + + storeMock.dispatch.mockResolvedValueOnce([{ id: 'reg1' }]); // for REGISTRY + storeMock.dispatch.mockResolvedValueOnce([{ id: 'scanJob1' }]); // for SCAN_JOB + + await wrapper.vm.loadData(); + + expect(storeMock.dispatch).toHaveBeenCalledWith('cluster/findAll', { type: 'sbombastic.rancher.io.registry' }); + expect(storeMock.dispatch).toHaveBeenCalledWith('cluster/findAll', { type: 'sbombastic.rancher.io.scanjob' }); + expect(preprocessSpy).toHaveBeenCalled(); + }); + + it('skips SCAN_JOB fetch if canList returns false', async () => { + storeMock.getters['cluster/canList'] = jest.fn().mockReturnValue(false); + const wrapper = factory(); + const preprocessSpy = jest.spyOn(wrapper.vm, 'preprocessData').mockResolvedValue(); + + storeMock.dispatch.mockResolvedValueOnce([{ id: 'reg1' }]); // only registry + + await wrapper.vm.loadData(); + + expect(storeMock.dispatch).toHaveBeenCalledTimes(1); // only REGISTRY + expect(preprocessSpy).toHaveBeenCalled(); + }); + + it('clears keepAliveTimer on beforeUnmount', () => { + const wrapper = factory(); + const clearSpy = jest.spyOn(global, 'clearInterval'); + + wrapper.vm.keepAliveTimer = setInterval(() => {}, 1000); + if (wrapper.vm.$options.beforeUnmount && wrapper.vm.$options.beforeUnmount[0]) { + wrapper.vm.$options.beforeUnmount[0].call(wrapper.vm); + } + }); + + it('updates selectedRows when onSelectionChange is called', () => { + const wrapper = factory(); + wrapper.vm.onSelectionChange([{ id: 'row1' }]); + expect(wrapper.vm.selectedRows).toEqual([{ id: 'row1' }]); + }); + + it('matches by name and namespace in filterRowsLocal', () => { + const wrapper = factory(); + wrapper.vm.debouncedFilters = { + registrySearch: 'reg1', + namespaceSearch: 'ns1', + uriSearch: '', + repositorySearch: '', + statusSearch: 'any' + }; + + const rows = [ + { metadata: { name: 'reg1', namespace: 'ns1' }, spec: { uri: '', repositories: [] }, scanRec: {} }, + { metadata: { name: 'reg2', namespace: 'ns2' }, spec: { uri: '', repositories: [] }, scanRec: {} } + ]; + + const result = wrapper.vm.filterRowsLocal(rows); + expect(result).toHaveLength(1); + expect(result[0].metadata.namespace).toBe('ns1'); + }); + + it('uses statusSearch.value if statusSearch is an object', () => { + const wrapper = factory(); + wrapper.vm.debouncedFilters = { + registrySearch: '', + namespaceSearch: '', + uriSearch: '', + repositorySearch: '', + statusSearch: { value: 'pending' }, + }; + + const pagination = { filters: [] }; + const result = wrapper.vm.filterRowsApi(pagination); + + // stringify and search for the filter field/value + const serialized = JSON.stringify(result.filters); + expect(serialized).toContain('"field":"scanRec.currStatus"'); + expect(serialized).toContain('"value":"pending"'); + }); + + it('returns canPaginate from store getter', () => { + storeMock.getters['cluster/paginationEnabled'] = jest.fn().mockReturnValue(true); + const wrapper = factory(); + + expect(wrapper.vm.canPaginate).toBe(true); + expect(storeMock.getters['cluster/paginationEnabled']).toHaveBeenCalledWith({ id: 'sbombastic.rancher.io.registry' }); + }); + }); \ No newline at end of file diff --git a/pkg/sbombastic-image-vulnerability-scanner/routes/sbombastic-image-vulnerability-scanner-routes.ts b/pkg/sbombastic-image-vulnerability-scanner/routes/sbombastic-image-vulnerability-scanner-routes.ts index deff783..c26ef63 100644 --- a/pkg/sbombastic-image-vulnerability-scanner/routes/sbombastic-image-vulnerability-scanner-routes.ts +++ b/pkg/sbombastic-image-vulnerability-scanner/routes/sbombastic-image-vulnerability-scanner-routes.ts @@ -30,11 +30,11 @@ const routes = [ path: `/c/:cluster/${PRODUCT_NAME}/${PAGE.IMAGES}/:id`, component: ImageDetails, }, - { - name: `c-cluster-${PRODUCT_NAME}-${PAGE.VULNERABILITIES}`, - path: `/c/:cluster/${PRODUCT_NAME}/${PAGE.VULNERABILITIES}`, - component: Vulnerabilities, - }, + // { + // name: `c-cluster-${PRODUCT_NAME}-${PAGE.VULNERABILITIES}`, + // path: `/c/:cluster/${PRODUCT_NAME}/${PAGE.VULNERABILITIES}`, + // component: Vulnerabilities, + // }, { name: `c-cluster-${PRODUCT_NAME}-${PAGE.REGISTRIES}`, path: `/c/:cluster/${PRODUCT_NAME}/${PAGE.REGISTRIES}`,