diff --git a/.changeset/console-fb35e4828fdb.md b/.changeset/console-fb35e4828fdb.md new file mode 100644 index 000000000..502529420 --- /dev/null +++ b/.changeset/console-fb35e4828fdb.md @@ -0,0 +1,18 @@ +--- +"@objectstack/console": minor +--- + +Console (objectui) refreshed to `fb35e4828fdb`. Frontend changes in this range: + +- fix(data-objectstack): emit MutationEvents from batchTransaction and bulk so master-detail saves refresh bound views (#2584) +- feat(dashboard-filters): #2578 item-5 enhancements — nested variable merging, metadata-aware default bindings, server-side optionsFrom distinct (#2590) +- feat(fields+form+detail): file/image upload cells in inline line-item grids (#2360) (#2585) +- feat(app-shell): visual filterBindings editor in the dashboard widget inspector (#2578) (#2586) +- fix(detail): highlight strip lookup editor honors ObjectStack `reference` key (#2407) (#2587) +- fix(app-shell): guard Studio Access pillar against silently discarding unsaved matrix edits (#2588) +- feat(dashboard-filters): #2578 follow-ups — catalog examples, guide tutorial, i18n entries, spec-alignment cleanup (#2581) +- fix(detail+fields+app-shell): ADR-0085 #2548 follow-ups — strip title dedupe, group icon/description, currency channel, approvals Bearer (#2577) +- feat(dashboard): dashboard-level filters driving multiple charts (framework#2501) (#2576) +- feat(page-header): metadata-driven multi-button record header (#2361) (#2574) + +objectui range: `092bd859934f...fb35e4828fdb` diff --git a/.objectui-sha b/.objectui-sha index 87ae99c74..29df0f044 100644 --- a/.objectui-sha +++ b/.objectui-sha @@ -1 +1 @@ -092bd859934f7bbc2654510aef912062c4c4f3a8 +fb35e4828fdb3b6ecc23761a82e9ec4a13890727 diff --git a/examples/app-showcase/e2e/detail-shapes.spec.ts b/examples/app-showcase/e2e/detail-shapes.spec.ts index 308df0de2..9bfabe658 100644 --- a/examples/app-showcase/e2e/detail-shapes.spec.ts +++ b/examples/app-showcase/e2e/detail-shapes.spec.ts @@ -19,9 +19,11 @@ import { test, expect } from '@playwright/test'; * semantic-zoo fixtures are objects but not seeded records — each run * creates its own rows via the REST API. * - * NOTE: assertions are scoped to what the *pinned* console build supports - * (.objectui-sha). Group icon/description chrome ships with a later objectui - * bump — extend the grouped case then. + * Assertions are scoped to what the *pinned* console build supports + * (.objectui-sha). The fb35e48 bump brought in objectui#2577, so the grouped + * case also pins the follow-up UX contract: highlight strip drops the record + * title, group icon/description render, and currencyConfig money shows its + * symbol. */ const APP = process.env.SHOWCASE_APP || 'com.example.showcase'; @@ -85,6 +87,14 @@ test('grouped: fieldGroup sections render and Money starts collapsed', async ({ // record:path renders a desktop + a mobile variant — assert the visible one. await expect(page.locator(PATH_STEPPER).first()).toBeVisible(); + // objectui#2577: the record title is the page H1 — it must NOT repeat as a + // (truncated) chip in the highlight strip; status/amount still do. + const strip = page.locator('section[aria-label="Record highlights"]'); + await expect(strip).toBeVisible(); + const stripText = (await strip.innerText()).replace(/\s+/g, ' '); + expect(stripText, 'strip repeats the record title').not.toContain('E2E Zoo'); + expect(stripText).toContain('4,200'); + // Declared groups render as titled sections. Their highlighted members // (status/amount) are hoisted to the strip; the non-highlighted members // (code/budget) keep the groups visible in the body. @@ -92,10 +102,22 @@ test('grouped: fieldGroup sections render and Money starts collapsed', async ({ await expect(page.getByText('Money', { exact: true })).toBeVisible(); await expect(page.getByText('ZG-1')).toBeVisible(); + // objectui#2577: fieldGroups[].icon renders as a real (Lucide svg) icon in + // the section header — not as literal icon-name text. + await expect( + page.locator('div:has(> span:text-is("Money")) svg').first(), + 'Money header icon svg', + ).toBeVisible(); + await expect(page.getByText('banknote', { exact: true })).toHaveCount(0); + // collapse: 'collapsed' — Budget stays hidden until the header is opened. await expect(page.getByText('Budget', { exact: true })).toHaveCount(0); await page.getByText('Money', { exact: true }).click(); await expect(page.getByText('Budget', { exact: true })).toBeVisible(); + // objectui#2577: fieldGroups[].description renders under the expanded + // header, and currencyConfig.defaultCurrency drives a real $ symbol. + await expect(page.getByText('Financial fields — collapsed by default.')).toBeVisible(); + await expect(page.getByText('$100,000', { exact: false }).first()).toBeVisible(); expect(errors, 'uncaught page errors on grouped detail').toEqual([]); }); @@ -134,6 +156,16 @@ test('ungrouped + related-heavy: flat details and related-list tabs on Contoso', // (Contoso declares no fieldGroups; spot-check a body field label.) await expect(page.getByText('Basics', { exact: true })).toHaveCount(0); + // objectui#2577 + currencyConfig: annual revenue renders with its symbol + // in the strip, and the meta footer doesn't dangle "Created by" on the + // actor-less seeded row. + await expect(page.getByText('$25,000,000', { exact: false }).first()).toBeVisible(); + const footer = page.locator('[data-testid="record-meta-footer"]'); + await expect(footer).toBeVisible(); + const footerText = (await footer.innerText()).replace(/\s+/g, ' '); + expect(footerText, 'footer dangles "Created by" without an actor').not.toMatch(/Created by/); + expect(footerText).toMatch(/Created/); + // Related lists self-fetch lazily when their tab is shown. await invoicesTab.click(); const panel = page.getByRole('tabpanel');