Put the open tab in the address bar, including the first one
Reported as "die Tabs fehlen in der Query beim Kunden". The binding was there and identical to the settings page — checked in the rendered snapshot, which is where Livewire's JS reads it from — but `except` hid the parameter while the DEFAULT tab was open. So arriving on a customer showed no ?tab= at all, and a link to the page could not say which tab it meant unless the tab happened not to be the first one. From the address bar that is indistinguishable from the feature not existing. No `except` now, on all three tabbed pages: the parameter is there from the first render. And `history: true`, so each tab is a step the back button can take rather than a silent replaceState — which also makes the change unmistakable while clicking. Asserted against the rendered page rather than the component, because the parameter is written client-side from the `url` memo in the snapshot: the memo IS the behaviour, and asserting the property would have passed throughout the bug. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>feature/betriebsmodus v1.3.43
parent
0a89695189
commit
518bc9aa41
|
|
@ -50,7 +50,17 @@ class CustomerDetail extends Component
|
|||
|
||||
public Customer $customer;
|
||||
|
||||
#[Url(except: 'overview')]
|
||||
/**
|
||||
* Which tab is open, in the address bar.
|
||||
*
|
||||
* `history: true`, so each tab is a step the back button can take — and no
|
||||
* `except`, so the parameter is there from the first render rather than
|
||||
* appearing only once somebody leaves the default tab. Hiding it on the
|
||||
* default read as "the tab is not in the URL", which is exactly how it was
|
||||
* reported: a link to this page could not say which tab it meant unless the
|
||||
* tab happened not to be the first one.
|
||||
*/
|
||||
#[Url(history: true)]
|
||||
public string $tab = 'overview';
|
||||
|
||||
// ---- Writing to them ----
|
||||
|
|
|
|||
|
|
@ -76,7 +76,17 @@ class Integrations extends Component
|
|||
*/
|
||||
public const TABS = ['services', 'platform', 'env'];
|
||||
|
||||
#[Url(except: 'services')]
|
||||
/**
|
||||
* Which tab is open, in the address bar.
|
||||
*
|
||||
* `history: true`, so each tab is a step the back button can take — and no
|
||||
* `except`, so the parameter is there from the first render rather than
|
||||
* appearing only once somebody leaves the default tab. Hiding it on the
|
||||
* default read as "the tab is not in the URL", which is exactly how it was
|
||||
* reported: a link to this page could not say which tab it meant unless the
|
||||
* tab happened not to be the first one.
|
||||
*/
|
||||
#[Url(history: true)]
|
||||
public string $tab = 'services';
|
||||
|
||||
use ConfirmsPassword {
|
||||
|
|
|
|||
|
|
@ -64,7 +64,17 @@ class Settings extends Component
|
|||
* needs no parameter, and a query string that appears the moment a page
|
||||
* loads makes every link to it look different from the one in the menu.
|
||||
*/
|
||||
#[Url(except: 'installation')]
|
||||
/**
|
||||
* Which tab is open, in the address bar.
|
||||
*
|
||||
* `history: true`, so each tab is a step the back button can take — and no
|
||||
* `except`, so the parameter is there from the first render rather than
|
||||
* appearing only once somebody leaves the default tab. Hiding it on the
|
||||
* default read as "the tab is not in the URL", which is exactly how it was
|
||||
* reported: a link to this page could not say which tab it meant unless the
|
||||
* tab happened not to be the first one.
|
||||
*/
|
||||
#[Url(history: true)]
|
||||
public string $tab = 'installation';
|
||||
|
||||
/** This page changes the signed-in OPERATOR's password, never a portal one. */
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ beforeEach(function () {
|
|||
]);
|
||||
});
|
||||
|
||||
it('opens on the details, and keeps that tab out of the address bar', function () {
|
||||
it('opens on the details', function () {
|
||||
Livewire::actingAs(operator('Owner'), 'operator')
|
||||
->test(CustomerDetail::class, ['uuid' => $this->customer->uuid])
|
||||
->assertSet('tab', 'overview')
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use Livewire\Livewire;
|
|||
* refreshes itself while an update runs, so a tab kept only in the component
|
||||
* would drop them back to the first one mid-deployment.
|
||||
*/
|
||||
it('opens the installation tab by default and keeps it out of the address bar', function () {
|
||||
it('opens the installation tab by default', function () {
|
||||
Livewire::actingAs(operator('Owner'), 'operator')
|
||||
->test(Settings::class)
|
||||
->assertSet('tab', 'installation')
|
||||
|
|
@ -133,3 +133,34 @@ it('tabs the integrations page the same way, and keeps the raw file to the Owner
|
|||
->assertSet('tab', 'services')
|
||||
->assertViewHas('tabs', fn (array $tabs) => ! in_array('env', $tabs, true));
|
||||
});
|
||||
|
||||
it('puts the open tab in the address bar from the first render, on every tabbed page', function () {
|
||||
// Reported as "die Tabs fehlen in der Query beim Kunden". The binding was
|
||||
// there, but `except` hid the parameter while the default tab was open — so
|
||||
// a link to the page could not say which tab it meant unless the tab
|
||||
// happened not to be the first one, and the address bar looked like the
|
||||
// feature was missing.
|
||||
//
|
||||
// Asserted against the rendered page rather than the component: the
|
||||
// parameter is written by Livewire's JS from the `url` memo in the snapshot,
|
||||
// so the memo IS the behaviour.
|
||||
$customer = App\Models\Customer::factory()->create();
|
||||
|
||||
$pages = [
|
||||
route('admin.settings'),
|
||||
route('admin.integrations'),
|
||||
route('admin.customer', $customer->uuid),
|
||||
];
|
||||
|
||||
foreach ($pages as $url) {
|
||||
$html = html_entity_decode(
|
||||
(string) $this->actingAs(operator('Owner'), 'operator')->get($url)->getContent()
|
||||
);
|
||||
|
||||
expect($html)->toContain('"url":{"tab":')
|
||||
// No `except`: shown even on the default tab.
|
||||
->and($html)->toMatch('/"tab":\{[^}]*"except":null/')
|
||||
// push, not replace: each tab is a step the back button can take.
|
||||
->and($html)->toMatch('/"tab":\{[^}]*"use":"push"/');
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue