Right pane tabs Jobs/Planes market + 5 new plane types with tech-spec panels + sell-plane cargo guard (ISS-047 part A)
CI / build + unit + e2e (pull_request) Successful in 8m56s
CI / build + unit + e2e (pull_request) Successful in 8m56s
This commit is contained in:
@@ -190,4 +190,9 @@ test('right pane placeholder exists with the Jobs & Market heading', async ({ pa
|
||||
const right = page.getByTestId('right-pane');
|
||||
await expect(right).toBeVisible();
|
||||
await expect(right).toContainText('Jobs & Market');
|
||||
|
||||
// v0.28.0 (ISS-047): the Jobs / Planes market tab bar renders once a snapshot lands; Jobs is default-active.
|
||||
await expect(page.getByTestId('tab-jobs'), 'the Jobs tab button appears').toBeVisible({ timeout: 15_000 });
|
||||
await expect(page.getByTestId('tab-planes-market')).toBeVisible();
|
||||
await expect(page.getByTestId('tab-jobs')).toHaveAttribute('aria-selected', 'true');
|
||||
});
|
||||
|
||||
@@ -151,6 +151,12 @@ function requiredFuelFor(burnPerKm: number, emptyWeightKg: number, maxFuel: numb
|
||||
return (emptyWeightKg / FUEL_DENSITY_KG_PER_L) * (Math.exp(k * FUEL_DENSITY_KG_PER_L * distanceKm) - 1);
|
||||
}
|
||||
|
||||
// Mirrors maxRangeKm in lib/sim/movement.ts (v0.28.0): full-tank range under the weighted model.
|
||||
function maxRangeKm(burnPerKm: number, emptyWeightKg: number, maxFuel: number): number {
|
||||
const rho = FUEL_DENSITY_KG_PER_L;
|
||||
return Math.log(1 + (rho * maxFuel) / emptyWeightKg) * ((emptyWeightKg + rho * maxFuel) / (rho * burnPerKm));
|
||||
}
|
||||
|
||||
// Test hook (FLIGHT_TEST_HOOKS=1): create an open package on a known route.
|
||||
async function createPackage(page: Page, fromIcao: string, toIcao: string, deadlineOffsetMs?: number): Promise<PackageState> {
|
||||
const created = await page.request.post('/api/test/create-package', {
|
||||
@@ -312,6 +318,9 @@ test('market buy/sell render with previews from the catalog in /api/state; left-
|
||||
expect(entry.maxPayloadKg).toBe(4_800); // ATR 72-600 max payload (lib/game/catalog.ts)
|
||||
|
||||
await page.goto('/');
|
||||
// v0.28.0 (ISS-047): the market rows live in the Planes market tab — switch to it first.
|
||||
await page.getByTestId('tab-planes-market').click();
|
||||
|
||||
// Buy: the model picker lists the catalog entry and the price preview is its full price.
|
||||
const buyModel = page.getByTestId('market-buy-model');
|
||||
await expect(buyModel).toBeVisible({ timeout: 15_000 });
|
||||
@@ -425,3 +434,23 @@ test('on-board row Refuel tops up just enough for the package leg; left-pane but
|
||||
// Top the tank back up so later specs start with a full tank.
|
||||
expect((await page.request.post('/api/planes/plane-starter/refuel')).status()).toBe(200);
|
||||
});
|
||||
|
||||
test('Planes market tab lists all plane types with tech specs', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
const body = await getState(page); // authoritative catalog — v0.28.0 ships six types
|
||||
expect(body.catalog.length).toBe(6);
|
||||
|
||||
await page.getByTestId('tab-planes-market').click();
|
||||
|
||||
// ATR card: name + full-tank range from the same closed form as lib/sim/movement.ts (v0.28.0).
|
||||
const atr = body.catalog.find((e) => e.model === 'atr72')!;
|
||||
await expect(page.getByTestId('plane-type-atr72'), 'the ATR card appears').toBeVisible({ timeout: 15_000 });
|
||||
await expect(page.getByTestId('plane-type-atr72')).toContainText(atr.label);
|
||||
const atrRange = Math.round(maxRangeKm(atr.burnPerKm, atr.emptyWeightKg, atr.maxFuel));
|
||||
await expect(page.getByTestId('plane-type-range-atr72')).toContainText(`${atrRange} km`);
|
||||
|
||||
// Ladder sanity: the most expensive type (Boeing 777-300ER) is present with its €9M price.
|
||||
const b777 = page.getByTestId('plane-type-b777');
|
||||
await expect(b777).toBeVisible();
|
||||
await expect(b777).toContainText(eur(9_000_000)); // lib/game/catalog.ts
|
||||
});
|
||||
|
||||
@@ -25,6 +25,9 @@ async function getState(page: Page): Promise<StateBody> {
|
||||
|
||||
test('failed actions toast at the map right edge, clear of the right pane (inline error stays), and the Time section offers a notifications opt-in', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
// v0.28.0 (ISS-047): the market rows live in the Planes market tab — switch to it first.
|
||||
await page.getByTestId('tab-planes-market').click();
|
||||
|
||||
const buyModel = page.getByTestId('market-buy-model');
|
||||
await expect(buyModel, 'the market section renders once the first snapshot lands').toBeVisible({ timeout: 15_000 });
|
||||
|
||||
|
||||
Reference in New Issue
Block a user