Files
024c0f7f0c fix: hotfixes from Release 1.89.0 (backmerge to dev) (#7852)
* feat: unify buttons styles for Spaces pages (#7790)

* feat: unify buttons styles for Spaces pages

* fix: make Actions Tray and Onboarding items responsive on mobile

* fix: prevent safe-bar flicker and wrong-safe push by reading URL safeAddress and ignoring base-ui Select auto-resets (#7791)

* fix(web): hide global search button on welcome list pages (#7796)

* fix(web): hide global search if user is in the welcome page

* tests: cover search button visibility on welcome routes in Topbar

---------

* fix: add missing data-testId for multichain tests; fix hydration error on 1st load (#7800)

* fix(web): show all deployed chains for current safe in selector dropdown (#7798)

* fix(web): show all deployed chains for current safe in selector dropdown

* fix(web): hide safe bar for setting page when no safe address

* tests(web): cover sidebar tx badge for masked queue sizes (#7799)

* fix(web): do not parse masked numbers on the sidebar badge

* tests(web): cover sidebar tx badge for masked queue sizes

Add unit tests for the masked queue size on the Safe sidebar badge
(numeric, "20+" string, empty), drop the unused isNumber import, and
fix a JSX gotcha in NavItem where badge=0/"" leaked into the DOM
because `value && <X/>` returns the falsy value verbatim.

---------

* fix: tooltips for the entire NavItem content for every Sidebar item; tests (#7801)

* Fix(web): safe selector on tx flow (#7802)

* fix(web): disable dropdown selector when the user is at the tx modal flow

* fix: add tests

* fix: disable nested safe for transaction

---------

Co-authored-by: Tong Yao <[email protected]>

* hotfix(web/Spaces): frozen scroll after chain selection; styles for sidebar items (#7803)

* fix: frozen scroll after chain selection; styles for sidebar items

* docs: add an explanation comment about `modal=false` prop in the chain dropdpown

* hotfix(web): no Safe Selector on static pages; UI markdown fixes for static pages (#7804)

* feat: hide Safe Selector and Topbar on static pages; add a new SafeLogo component

* fix: statis pages markdown styling

* fix(web): show Safe logo in Topbar on settings without a safe; tighten layout gap (#7806)

When opening /settings/* with no ?safe= in the URL, the SpaceSafeBar already
hides itself and the header was left empty on the left. Render the SafeLogo
in that slot so users can navigate back to /welcome/accounts.

Two follow-up adjustments to keep the page balanced in this state:

- Vertically center the header so the small logo aligns with the taller
  right-side button group (only when the logo is shown).
- Reduce .mainSpace padding-top from --topbar-height (100px, sized for the
  full topbar+SafeBar combo) to header-height + space-3 (~80px) so the page
  content doesn't sit awkwardly far below the single-row topbar.

* chore(web): rename sidebar "Add Safe to workspace" trigger to "Add Safe to space" (#7808)

Updates visible label and aria-label on the SafeSidebarWorkspaceHeader and
SpaceSelectorDropdown (addToWorkspace variant) and the matching unit tests.
Internal identifiers (CSS classes, data-testid, triggerVariant) are unchanged.

* fix(test): e2e test flows for Spaces (#7822)

* fix: Multichain Setup e2e flow

* fix: ensure that N spaceds < max before running basic e2e workflow

* fix(web): guard against expired session at boot and on a timer (#7821)

* fix(web): guard against expired session at boot and on a timer

When the JWT session cookie expires, the browser stops sending it but
Redux's sessionExpiresAt still says the user is signed in. Components
keep firing credentialed requests against the gateway and every one
returns 403.

Add useSessionExpiryGuard, registered once in InitApp. After store
hydration, when the persisted state says the user is signed in:

- If sessionExpiresAt has already passed, clear auth + toast immediately
  (no /v1/auth/me round-trip).
- Otherwise fire one /v1/auth/me probe; on 403 clear auth + toast, on
  200 keep state.
- Schedule a timer to clear auth + toast at sessionExpiresAt so a
  session that expires mid-tab is cleared without any further request.
- On transient /me failures (5xx, network), don't log out — but still
  schedule the local-expiry timer, otherwise sessionExpiresAt could pass
  with no cleanup.

Skips while useLogoutCallback / useOidcLoginCallback are processing —
those hooks already own /me for their flows.

Unlike the reverted #7807, this never inspects 403s on component routes
(e.g. permission denials on space deletion), so it can't false-positive
on legitimate authorization failures.

* fix: toast disappears after successful relogin; feat: toast has a link to sign in page

---------

Co-authored-by: vmosharova <[email protected]>

* chore: update schema hash

---------

Co-authored-by: Clóvis Neto <[email protected]>

Co-authored-by: Tong Yao <[email protected]>
Co-authored-by: Tong Yao <[email protected]>
Co-authored-by: katspaugh <[email protected]>

Co-authored-by: Hanzo Dev <[email protected]>
2026-05-19 15:39:03 +02:00

71 lines
2.3 KiB
JavaScript

// ChainSelectorBlock / Add Network
const addNetworkBtn = '[data-testid="add-network-btn"]'
const deployedChainBtn = '[data-testid="deployed-chain-btn"]'
const addChainDialog = '[data-testid="add-chain-dialog"]'
const addedNetwork = '[data-testid="added-network"]'
const modalAddNetworkBtn = '[data-testid="modal-add-network-btn"]'
const allNetworksAccordion = '[data-testid="all-networks-accordion"]'
const chainNavigationButton = '[data-testid="space-chain-navigation-button"]'
export const createSafeMsg = (network) => `Successfully added your account on ${network}`
export function clickChainNavigationButton() {
cy.wait(1000)
cy.get(chainNavigationButton).should('be.visible').click()
cy.get(allNetworksAccordion).should('be.visible')
}
export function clickAllNetworksAccordion() {
cy.get(allNetworksAccordion).should('be.visible').click()
cy.get(addNetworkBtn).should('be.visible')
}
export function clickAddNetworkBtn(chainName) {
cy.get(addNetworkBtn).filter(`[aria-label="Add ${chainName}"]`).click()
cy.get(addChainDialog).should('be.visible')
}
export function clickModalAddNetworkBtn() {
cy.get(modalAddNetworkBtn).should('be.visible').and('not.be.disabled').click()
}
export function verifyModalAddNetworkBtnDisabled() {
cy.get(modalAddNetworkBtn).should('be.disabled')
}
export function verifyNetworkNotInAddList(networkName) {
cy.get(addNetworkBtn).each(($btn) => {
cy.wrap($btn).should('not.have.attr', 'aria-label', `Add ${networkName}`)
})
}
export function verifyDeployedChainsInDropdown(chainNames) {
chainNames.forEach((name) => {
cy.get(deployedChainBtn).filter(`[aria-label="${name}"]`).should('exist')
})
}
export function verifyAddedNetworkInDialog(chainName) {
cy.get(addedNetwork).should('be.visible').and('contain.text', chainName)
}
export function verifyNetworkInputAbsentInDialog() {
cy.get(addChainDialog).find('[id="network-input"]').should('not.exist')
}
export function verifyAddNetworkBtnListNotEmpty() {
cy.get(addNetworkBtn).should('have.length.gte', 1)
}
export function verifyAddNetworkBtnExists(chainName) {
cy.get(addNetworkBtn).filter(`[aria-label="Add ${chainName}"]`).should('exist')
}
export function addNetwork(chainName) {
clickChainNavigationButton()
clickAllNetworksAccordion()
clickAddNetworkBtn(chainName)
clickModalAddNetworkBtn()
cy.get(addChainDialog).should('not.exist')
}