- TypeScript 71.7%
- Vue 25.4%
- CSS 1.5%
- HTML 0.9%
- JavaScript 0.5%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
* fix(security): resolve npm audit high-severity vulnerabilities Bump axios override 1.16.0 -> 1.19.0 and update transitive deps (dompurify, postcss, brace-expansion) via npm audit fix. Resolves all high-severity advisories that were failing the CI security check across the open dependabot PRs (#202, #204, #205). npm audit --audit-level=high now passes with 0 vulnerabilities. * chore(deps): update dependencies to latest compatible versions Applies all non-breaking (patch/minor) updates via npm update, and bumps range constraints for eslint-plugin-vue (~10.10.0) and prettier (3.9.6). Type-check, lint, unit tests (91/91) and production build all pass. * chore(deps): upgrade pinia to v4 and @pinia/testing to v2 Pinia 4 is compatible with Vue 3.5.40 and TS 6. Type-check, lint, unit tests (91/91) and build all pass. |
||
| .github | ||
| .vscode | ||
| badges | ||
| cypress | ||
| public | ||
| scripts | ||
| src | ||
| .editorconfig | ||
| .env.development | ||
| .env.production | ||
| .gitattributes | ||
| .gitignore | ||
| .npmrc | ||
| .prettierrc.json | ||
| cypress.config.ts | ||
| env.d.ts | ||
| eslint.config.ts | ||
| index.html | ||
| LICENSE | ||
| package-lock.json | ||
| package.json | ||
| publiccode.yml | ||
| README.md | ||
| tsconfig.app.json | ||
| tsconfig.json | ||
| tsconfig.node.json | ||
| tsconfig.vitest.json | ||
| vite.config.ts | ||
| vitest.config.ts | ||
drill-frontend
Vue.js application with a mapping component to provide information on the possibilities of installing geothermal probes in Switzerland, using the cantons' geoservices.
This application supports languages DE, FR, IT, EN. You can select default using query string ?lang=IT
Project Setup
Backend
ℹ️ This Vue.js app needs a backend to work.
The backend is published here, please follow instructions: https://github.com/SFOE/drillapi
A docker image can also be pulled from https://github.com/SFOE/drillapi/pkgs/container/drillapi
Install Vue.js dev environment
This project uses Node.js. Checkout official documentation in order to manage node versions correctly with Node Version Manager (NVM) at https://nodejs.org/en/download
git clone git@github.com:SFOE/drill-frontend.git
cd drill-frontend
npm ci
⚠️ Never use npm install — the project enforces npm ci via a preinstall guard script.
Compile and Hot-Reload for Development
npm run dev
Upgrade packages
npx npm-check-updates -u
npm install --ignore-scripts
After upgrading, run npm audit to check for vulnerabilities. Known transitive vulnerabilities are pinned via overrides in package.json.
Type-Check, Compile and Minify for Production
npm run build
Run Unit Tests with Vitest
npm run test:unit
Run with coverage report:
npx vitest --run --coverage
Unit test structure
Tests live in __tests__/ folders colocated with their source:
src/
├── components/__tests__/
│ ├── AddressFulltextSearchComponent.test.ts # Rendering, debounce, ARIA, selection
│ ├── InfoboxComponent.test.ts # Color mapping, loading state, layout
│ ├── InfoboxLinksComponent.test.ts # Link rendering, security attrs
│ └── LoadingSpinner.test.ts # Basic rendering
├── composables/__tests__/
│ ├── useDevice.test.ts # Mobile detection, resize handling
│ └── useGeoadminReverseGeocoding.test.ts # Address formatting, edge cases
├── stores/__tests__/
│ ├── languageStore.test.ts # Locale persistence
│ ├── mapStore.test.ts # fetchGroundCategory, clearSearchState, getters
│ └── searchStore.test.ts # State management, clearSearchState
└── utils/__tests__/
├── debounce.test.ts # Timer behavior, argument passing
└── stripHtml.test.ts # Tag removal, XSS safety, property-based
Testing patterns used
- Property-based testing (
fast-check) —mapStoretests all 26 Swiss cantons × valid LV95 coordinate ranges;stripHtmlverifies invariants (idempotency, no tags in output) against random input. - Component testing (
@vue/test-utils+@pinia/testing) — shallow rendering with mocked stores to test rendering logic and user interactions. - Composable testing — pure function tests with mocked HTTP layer for
useGeoAdmin; lifecycle-aware tests via wrapper components foruseDevice.
Run End-to-End Tests with Cypress
Interactive mode (opens Cypress UI):
npm run test:e2e:dev
Headless mode (CI):
npm run test:e2e
E2E test structure
cypress/e2e/
├── AddressFultextSearchComponent.cy.ts # Search input, dropdown display, clearing
├── FooterComponent.cy.ts # Footer layout, links, copyright year
├── HeaderComponent.cy.ts # Logo, header visibility
├── InfoboxComponent.cy.ts # All harmonized_value colors, mobile expand/collapse
├── LanguageSwitcherComponent.cy.ts # DE ↔ EN switching
├── MapComponent.cy.ts # Map rendering, click interaction
├── StaticElementsComponent.cy.ts # Info block, canton info, external links
└── UserJourney.cy.ts # Integrated flows (see below)
UserJourney.cy.ts — integrated regression tests
This file covers the scenarios most likely to break during refactoring:
- Search → select → infobox — full primary user flow
- Clear button — resets infobox and input after selection
- Backend error (500) — shows purple error infobox
- Geoservice unavailable (98) — preserves canton name in error message
- Loading spinner — visible during fetch, disappears after
- Keyboard navigation — ArrowDown/Up, Escape, Enter
- URL query parameter —
?lang=fr/?lang=itloads correct locale - Click outside — closes dropdown
E2E test utilities
cypress/support/mock-backend.ts— providesmockDrillCategoryApi()andmockDrillCategoryError()helpers with predefined responses for allharmonized_valuestates (1-6, 98, 99).
CI
Both test suites run automatically on every PR and push to main via GitHub Actions:
| Workflow | File | What it runs |
|---|---|---|
| Unit tests & type check | .github/workflows/unit_tests.yml |
vue-tsc → vitest --coverage → eslint |
| E2E tests | .github/workflows/e2e_tests.yml |
Builds app → starts preview → cypress run |
Lint with ESLint
npm run lint
Format with Prettier
npm run format
Architecture
src/
├── assets/ # CSS (design tokens in base.css), images, SVGs
├── components/ # Vue SFCs (Composition API + script setup)
├── composables/ # Reusable logic (useDevice, useProjections, useGeoAdmin)
├── locales/ # i18n translation files (de, en, fr, it)
├── router/ # Vue Router (single route)
├── stores/ # Pinia stores (mapStore, languageStore)
├── types/ # TypeScript interfaces
├── utils/ # Pure utility functions (debounce, stripHtml)
└── views/ # Page-level components
CSS Design Tokens
Global design tokens (colors, radii, shadows) are defined as CSS custom properties in src/assets/base.css. Components reference these variables instead of hardcoded values:
var(--color-primary) /* #2f4356 */
var(--color-link) /* #005ea5 */
var(--radius-md) /* 8px */
var(--shadow-sm) /* subtle box shadow */
Security
- Content-Security-Policy meta tag in
index.html npm cienforced via preinstall guard (nonpm install)npm auditruns in CI at--audit-level=high- Dependency overrides pin known vulnerable transitive packages
stripHtmluses DOMParser (XSS-safe) instead of innerHTML- Address search input is debounced (300ms) to prevent API abuse
Environment Variables
| Variable | Description | Default |
|---|---|---|
VITE_BACKEND_URL |
Backend API base URL | http://localhost:8000/ (dev), empty = relative (prod) |
Environment files: .env.development, .env.production
Type Support for .vue Imports in TS
TypeScript cannot handle type information for .vue imports by default, so we replace the tsc CLI with vue-tsc for type checking. In editors, we need Volar to make the TypeScript language service aware of .vue types.