Skip to content

Commit

Permalink
tests(front): cover ClustersView
Browse files Browse the repository at this point in the history
Add unit tests to cover ClustersView and ClustersListItem component.
  • Loading branch information
rezib committed Jan 13, 2025
1 parent d4b6b6c commit 6da46b0
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 0 deletions.
102 changes: 102 additions & 0 deletions frontend/tests/components/clusters/ClustersListItem.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { describe, test, expect, beforeEach, vi } from 'vitest'
import { flushPromises, shallowMount } from '@vue/test-utils'
import ClusterListItem from '@/components/clusters/ClustersListItem.vue'
import stats from '../../assets/stats.json'
import { init_plugins } from '../../lib/common'
import { useRuntimeStore } from '@/stores/runtime'
import LoadingSpinner from '@/components/LoadingSpinner.vue'

const mockGatewayAPI = {
stats: vi.fn()
}

vi.mock('@/composables/GatewayAPI', () => ({
useGatewayAPI: () => mockGatewayAPI
}))

let router

describe('ClustersView.vue', () => {
beforeEach(() => {
router = init_plugins()
useRuntimeStore().availableClusters = [
{
name: 'foo',
permissions: { roles: [], actions: [] },
racksdb: true,
infrastructure: 'foo',
metrics: true
}
]
mockGatewayAPI.stats.mockReset()
})
test('cluster with permission', async () => {
useRuntimeStore().availableClusters[0].permissions.actions = ['view-stats', 'view-jobs']
mockGatewayAPI.stats.mockReturnValueOnce(Promise.resolve(stats))
const wrapper = shallowMount(ClusterListItem, {
props: {
cluster: useRuntimeStore().availableClusters[0]
}
})
// Wait for result of clusters requests
await flushPromises()
// assert stats have been retrieved
expect(mockGatewayAPI.stats).toBeCalled()
// Check presence of Slurm version
expect(wrapper.get('span span').text()).toContain('Slurm ')
// Check presence of nodes/jobs stats
const statsElements = wrapper.findAll('p')
expect(statsElements[0].text()).toContain('nodes')
expect(statsElements[1].text()).toContain('jobs')
// Check cluster status is available
expect(wrapper.get('div div p').text()).toBe('Available')
})
test('cluster loading', async () => {
useRuntimeStore().availableClusters[0].permissions.actions = ['view-stats', 'view-jobs']
mockGatewayAPI.stats.mockReturnValueOnce(Promise.resolve(stats))
const wrapper = shallowMount(ClusterListItem, {
props: {
cluster: useRuntimeStore().availableClusters[0]
}
})
// assert stats are being retrieved
expect(mockGatewayAPI.stats).toBeCalled()
// Check presence of loading spinner
expect(wrapper.findComponent(LoadingSpinner).exists()).toBeTruthy()
// Check cluster status is loading
expect(wrapper.get('div div p').text()).toBe('Loading')
})
test('cluster without permission', async () => {
mockGatewayAPI.stats.mockReturnValueOnce(Promise.resolve(stats))
const wrapper = shallowMount(ClusterListItem, {
props: {
cluster: useRuntimeStore().availableClusters[0]
}
})
// Wait for result of clusters requests
await flushPromises()
// assert stats not retrieved
expect(mockGatewayAPI.stats).not.toBeCalled()
// Check Slurm version is absent
expect(wrapper.find('span span').exists()).toBeFalsy()
// Check there is only one paragraph for cluster status, not for stats
expect(wrapper.findAll('p').length).toBe(1)
expect(wrapper.get('div div p').text()).toBe('Denied')
})
test('cluster without view-stats permission', async () => {
useRuntimeStore().availableClusters[0].permissions.actions = ['view-jobs']
const wrapper = shallowMount(ClusterListItem, {
props: {
cluster: useRuntimeStore().availableClusters[0]
}
})
await flushPromises()
// assert stats not retrieved
expect(mockGatewayAPI.stats).not.toBeCalled()
// Check Slurm version is absent
expect(wrapper.find('span span').exists()).toBeFalsy()
// Check there is only one paragraph for cluster status, not for stats
expect(wrapper.findAll('p').length).toBe(1)
expect(wrapper.get('div div p').text()).toBe('Available')
})
})
61 changes: 61 additions & 0 deletions frontend/tests/views/ClustersView.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { describe, test, expect, beforeEach, vi } from 'vitest'
import { flushPromises, shallowMount } from '@vue/test-utils'
import ClustersView from '@/views/ClustersView.vue'
import clusters from '../assets/clusters.json'
import { init_plugins } from '../lib/common'
import LoadingSpinner from '@/components/LoadingSpinner.vue'
import ClusterListItem from '@/components/clusters/ClustersListItem.vue'
import { APIServerError, AuthenticationError } from '@/composables/HTTPErrors'

const mockGatewayAPI = {
clusters: vi.fn()
}

vi.mock('@/composables/GatewayAPI', () => ({
useGatewayAPI: () => mockGatewayAPI
}))

let router

describe('ClustersView.vue', () => {
beforeEach(() => {
router = init_plugins()
})
test('display clusters list', async () => {
// Check at least one cluster is present in test asset or the test is pointless.
expect(clusters.length).toBeGreaterThan(0)
mockGatewayAPI.clusters.mockReturnValueOnce(Promise.resolve(clusters))
const wrapper = shallowMount(ClustersView)
// Wait for result of clusters requests
await flushPromises()
// Check page title
expect(wrapper.get('h1').text()).toBe('Select a cluster')
// Check there are as many ClusterListItem as the number of clusters in test asset.
expect(wrapper.findAllComponents(ClusterListItem).length).toBe(clusters.length)
})
test('show loading spinner before loaded', async () => {
const wrapper = shallowMount(ClustersView)
wrapper.getComponent(LoadingSpinner)
expect(wrapper.get('div').text()).toBe('Loading clusters…')
})
test('authentication error', async () => {
mockGatewayAPI.clusters.mockImplementationOnce(() => {
throw new AuthenticationError('fake authentication error')
})
const wrapper = shallowMount(ClustersView)
// Wait for result of clusters requests
await flushPromises()
// Check redirect to signout on authentication error
expect(router.push).toHaveBeenCalledTimes(1)
expect(router.push).toHaveBeenCalledWith({ name: 'signout' })
})
test('server error', async () => {
mockGatewayAPI.clusters.mockImplementationOnce(() => {
throw new APIServerError(500, 'fake error')
})
const wrapper = shallowMount(ClustersView)
// Wait for result of clusters requests
await flushPromises()
expect(wrapper.get('div h3').text()).toBe('Unable to load cluster list')
})
})

0 comments on commit 6da46b0

Please sign in to comment.