feat: v0.3.1 — show app version in header (sourced from package.json)
This commit is contained in:
@@ -1,5 +1,10 @@
|
||||
# Changelog
|
||||
|
||||
## v0.3.1 — 2026-09-17 06:35
|
||||
- Header now shows the app version between the "Flight Ops" title and the airport count (`<small>v{version}</small>` in `components/Map.tsx`), sourced dynamically from `package.json` via a JSON import — future version bumps show up automatically with no code change; subtle 11px muted style added to `app/globals.css`
|
||||
- Tests: new unit suite `components/version.test.ts` (valid semver in package.json + guard that the header sources the version from package.json rather than hardcoding it); `e2e/map.spec.ts`: new test asserting the header shows `v{version}` with the expected value read from `package.json` at test time, so it stays in sync automatically
|
||||
- Verified: unit suite 10/10; `tsc --noEmit` clean; e2e suite 4/4 green against the rebuilt compose instance
|
||||
|
||||
## v0.3.0 — 2026-09-17 00:32
|
||||
- Removed the zoom-driven camera tilt (`lib/camera.ts` pitch curve + the map `move` handler): the map is now always flat/top-down with standard pan/zoom only; deleted `lib/camera.ts` and its unit tests
|
||||
- Removed terrain: no more DEM raster source / `map.setTerrain`, and the `?terrain=0` / `NEXT_PUBLIC_TERRAIN` toggles are gone — pure 2D view, no 3D elements
|
||||
|
||||
@@ -43,6 +43,11 @@ body {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.app-header small {
|
||||
font-size: 11px;
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
[data-testid='airport-count'] {
|
||||
font-size: 12px;
|
||||
color: #cbd5e1;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import * as maplibregl from 'maplibre-gl';
|
||||
import 'maplibre-gl/dist/maplibre-gl.css';
|
||||
import pkg from '../package.json';
|
||||
|
||||
const EUROPE_CENTER: [number, number] = [10, 52];
|
||||
const INITIAL_ZOOM = 4;
|
||||
@@ -93,6 +94,7 @@ export default function Map() {
|
||||
<div className="map-wrap">
|
||||
<header data-testid="app-header" className="app-header">
|
||||
<h1>Flight Ops</h1>
|
||||
<small>v{pkg.version}</small>
|
||||
<span data-testid="airport-count">
|
||||
{airportCount === null ? 'loading airports…' : `${airportCount} EU airports`}
|
||||
</span>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { readFileSync } from 'node:fs';
|
||||
import pkg from '../package.json';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
const mapSource = readFileSync(new URL('./Map.tsx', import.meta.url), 'utf8');
|
||||
|
||||
describe('app version display', () => {
|
||||
it('package.json carries a valid semver version (single source of truth)', () => {
|
||||
expect(pkg.version).toMatch(/^\d+\.\d+\.\d+$/);
|
||||
});
|
||||
|
||||
it('the header sources the version from package.json instead of hardcoding it', () => {
|
||||
expect(mapSource).toContain("from '../package.json'");
|
||||
expect(mapSource).toContain('v{pkg.version}');
|
||||
});
|
||||
});
|
||||
@@ -1,7 +1,12 @@
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { test, expect, type Page } from '@playwright/test';
|
||||
|
||||
const APP_URL = '/';
|
||||
|
||||
// Read at test time so the assertion tracks package.json automatically.
|
||||
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8')) as { version: string };
|
||||
|
||||
// Must match MIN_ZOOM / MAX_ZOOM exported from components/Map.tsx.
|
||||
const MIN_ZOOM = 3;
|
||||
const MAX_ZOOM = 11;
|
||||
@@ -24,6 +29,12 @@ test('page loads with the map and EU airport count', async ({ page }) => {
|
||||
expect(count).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test('header shows the app version sourced from package.json', async ({ page }) => {
|
||||
await page.goto(APP_URL);
|
||||
const header = page.getByTestId('app-header');
|
||||
await expect(header).toContainText(`v${pkg.version}`);
|
||||
});
|
||||
|
||||
test('clicking an airport marker opens a popup with name and ICAO', async ({ page }) => {
|
||||
await page.goto(APP_URL);
|
||||
await waitForAirportCount(page);
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "flight-ops",
|
||||
"version": "0.3.0",
|
||||
"version": "0.3.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev -p 3000",
|
||||
|
||||
Reference in New Issue
Block a user