Skip to content
Merged
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
22 changes: 22 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,28 @@ jobs:
- name: Run tests
run: pytest

frontend_tests:
name: Frontend unit tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: lts/*
cache: npm
cache-dependency-path: frontend/package-lock.json

- name: Install frontend dependencies
run: |
cd frontend
npm ci

- name: Run frontend unit tests
run: |
cd frontend
npm run test:unit -- --run

os_rpm_tests:
name: OS integration tests (rpm)
strategy:
Expand Down
21 changes: 17 additions & 4 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"build-only": "vite build",
"type-check": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix",
"format": "prettier --write src/"
"format": "prettier --write src/ tests/"
},
"dependencies": {
"@headlessui/vue": "^1.7.17",
Expand Down Expand Up @@ -44,6 +44,7 @@
"typescript": "~5.2.0",
"vite": "^6.2.3",
"vitest": "^3.0.9",
"vue-router-mock": "^2.0.0",
"vue-tsc": "^2.0.29"
}
}
69 changes: 69 additions & 0 deletions frontend/tests/components/BreadCrumbs.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
Copyright (c) 2025 Rackslab

This file is part of RacksDB.

SPDX-License-Identifier: GPL-3.0-or-later
*/

import { describe, test, expect } from 'vitest'
import { mount } from '@vue/test-utils'

import { getRouter } from 'vue-router-mock'

import BreadCrumbs from '@/components/BreadCrumbs.vue'

describe('BreadCrumbs', () => {
test('renders logo and datacenter breadcrumb when route meta entry is datacenters', () => {
const router = getRouter()
router.currentRoute.value = {
meta: { entry: 'datacenters' },
name: 'datacenterdetails'
}

const wrapper = mount(BreadCrumbs, {
props: {
datacenterName: 'paris'
}
})

expect(wrapper.find('img[alt="Rackslab logo"]').exists()).toBe(true)
expect(wrapper.text()).toContain('Datacenters')
expect(wrapper.text()).toContain('paris')
})

test('renders infrastructure breadcrumb when route meta entry is infrastructures', () => {
const router = getRouter()
router.currentRoute.value = {
meta: { entry: 'infrastructures' },
name: 'infrastructuredetails'
}

const wrapper = mount(BreadCrumbs, {
props: {
infrastructureName: 'core'
}
})

expect(wrapper.text()).toContain('Infrastructures')
expect(wrapper.text()).toContain('core')
})

test('renders room breadcrumb when route name is datacenterroom', () => {
const router = getRouter()
router.currentRoute.value = {
meta: { entry: 'datacenters' },
name: 'datacenterroom'
}

const wrapper = mount(BreadCrumbs, {
props: {
datacenterName: 'paris',
datacenterRoom: 'room1'
}
})

expect(wrapper.text()).toContain('paris')
expect(wrapper.text()).toContain('room1')
})
})
69 changes: 69 additions & 0 deletions frontend/tests/components/ComboBox.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
Copyright (c) 2025 Rackslab

This file is part of RacksDB.

SPDX-License-Identifier: GPL-3.0-or-later
*/

import { describe, test, expect, vi, beforeEach } from 'vitest'
import { mount } from '@vue/test-utils'
import { nextTick } from 'vue'
import { getRouter } from 'vue-router-mock'

import ComboBox from '@/components/ComboBox.vue'

describe('ComboBox', () => {
test('renders with datacenter items and filters correctly', async () => {
const items = [
{ name: 'paris', rooms: [] },
{ name: 'london', rooms: [] }
]

const wrapper = mount(ComboBox, {
props: {
itemType: 'datacenter',
items
}
})

expect(wrapper.text()).toContain('Select a datacenter')
})

test('renders with infrastructure items', () => {
const items = [
{ name: 'core', description: 'Core infrastructure' },
{ name: 'edge', description: 'Edge infrastructure' }
]

const wrapper = mount(ComboBox, {
props: {
itemType: 'infrastructure',
items
}
})

expect(wrapper.text()).toContain('Select an infrastructure')
})

test('navigates to correct route when item is selected', async () => {
const router = getRouter()
const items = [{ name: 'paris', rooms: [] }]

const wrapper = mount(ComboBox, {
props: {
itemType: 'datacenter',
items
}
})

// Simulate item selection
wrapper.vm.goToItem('paris')
await nextTick()

expect(router.push).toHaveBeenCalledWith({
name: 'datacenterdetails',
params: { name: 'paris' }
})
})
})
40 changes: 40 additions & 0 deletions frontend/tests/components/DatacenterListInfrastructures.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { describe, test, expect } from 'vitest'
import { mount } from '@vue/test-utils'

import DatacenterListInfrastructures from '@/components/DatacenterListInfrastructures.vue'

describe('DatacenterListInfrastructures', () => {
test('renders infrastructure links when infrastructures are provided', () => {
const wrapper = mount(DatacenterListInfrastructures, {
props: {
infrastructures: ['core', 'edge', 'storage']
}
})

expect(wrapper.text()).toContain('core')
expect(wrapper.text()).toContain('edge')
expect(wrapper.text()).toContain('storage')
expect(wrapper.text()).toContain(',') // comma separators
})

test('renders dash when no infrastructures are provided', () => {
const wrapper = mount(DatacenterListInfrastructures, {
props: {
infrastructures: []
}
})

expect(wrapper.text()).toContain('-')
})

test('renders single infrastructure without comma', () => {
const wrapper = mount(DatacenterListInfrastructures, {
props: {
infrastructures: ['core']
}
})

expect(wrapper.text()).toContain('core')
expect(wrapper.text()).not.toContain(',')
})
})
Loading