fix: preserve safe motion and consent failures

This commit is contained in:
Evandro Fonseca Junior committed 2026-09-04 22:02:00 -03:00
1 parent a4e5e5c048
commit bea235d6fd
4 files changed
+61 -14

No files matched your search

+27 -1
View File
@@ -240,7 +240,7 @@ describe("GoogleAnalytics consent", () => {
expect( expect(
screen.getByRole("alert", { screen.getByRole("alert", {
name: "Falha ao salvar a revogação", name: "Falha ao salvar o consentimento",
}), }),
).toHaveTextContent( ).toHaveTextContent(
"Não foi possível salvar a revogação. Tente novamente para concluir.", "Não foi possível salvar a revogação. Tente novamente para concluir.",
@@ -250,4 +250,30 @@ describe("GoogleAnalytics consent", () => {
screen.getByRole("button", { name: "Revogar analytics" }), screen.getByRole("button", { name: "Revogar analytics" }),
).toBeVisible(); ).toBeVisible();
}); });
it("reports when refusal cannot be persisted", async () => {
const user = userEvent.setup();
jest.spyOn(Storage.prototype, "setItem").mockImplementation(() => {
throw new Error("storage blocked");
});
render(<GoogleAnalytics />);
await user.click(
await screen.findByRole("button", { name: "Recusar analytics" }),
);
expect(
screen.getByRole("alert", {
name: "Falha ao salvar o consentimento",
}),
).toHaveTextContent(
"Não foi possível salvar sua recusa. Tente novamente para concluir.",
);
expect(
screen.getByRole("button", { name: "Recusar analytics" }),
).toBeVisible();
expect(
screen.queryByRole("button", { name: "Preferências de analytics" }),
).not.toBeInTheDocument();
});
}); });
+29 -8
View File
@@ -98,7 +98,7 @@ const buttonClassName =
function GoogleAnalyticsConsent() { function GoogleAnalyticsConsent() {
const [consent, setConsent] = useState<AnalyticsConsent | null>(); const [consent, setConsent] = useState<AnalyticsConsent | null>();
const [preferencesOpen, setPreferencesOpen] = useState(false); const [preferencesOpen, setPreferencesOpen] = useState(false);
const [revokeError, setRevokeError] = useState<string | null>(null); const [consentError, setConsentError] = useState<string | null>(null);
const configuredRef = useRef(false); const configuredRef = useRef(false);
const preferencesButtonRef = useRef<HTMLButtonElement>(null); const preferencesButtonRef = useRef<HTMLButtonElement>(null);
@@ -138,26 +138,38 @@ function GoogleAnalyticsConsent() {
} }
function acceptAnalytics() { function acceptAnalytics() {
if (!persistConsent("granted")) return; if (!persistConsent("granted")) {
setConsentError(
"Não foi possível salvar sua aceitação. Tente novamente para concluir.",
);
return;
}
setConsentError(null);
enableAnalytics(); enableAnalytics();
setConsent("granted"); setConsent("granted");
closePreferences(); closePreferences();
} }
function denyAnalytics() { function denyAnalytics() {
persistConsent("denied"); if (!persistConsent("denied")) {
setConsentError(
"Não foi possível salvar sua recusa. Tente novamente para concluir.",
);
return;
}
setConsentError(null);
setConsent("denied"); setConsent("denied");
closePreferences(); closePreferences();
} }
function revokeAnalytics() { function revokeAnalytics() {
if (!persistConsent("denied")) { if (!persistConsent("denied")) {
setRevokeError( setConsentError(
"Não foi possível salvar a revogação. Tente novamente para concluir.", "Não foi possível salvar a revogação. Tente novamente para concluir.",
); );
return; return;
} }
setRevokeError(null); setConsentError(null);
window[GA_DISABLE_KEY] = true; window[GA_DISABLE_KEY] = true;
window.gtag?.("consent", "update", deniedConsent); window.gtag?.("consent", "update", deniedConsent);
expireAnalyticsCookies(); expireAnalyticsCookies();
@@ -189,6 +201,15 @@ function GoogleAnalyticsConsent() {
Você decide se permite métricas anônimas para melhorar este site. Você decide se permite métricas anônimas para melhorar este site.
Publicidade e personalização continuam desativadas. Publicidade e personalização continuam desativadas.
</p> </p>
{consentError && (
<p
role="alert"
aria-label="Falha ao salvar o consentimento"
className="mt-sp-3 text-[13px] leading-6 text-[var(--slash)]"
>
{consentError}
</p>
)}
<div className="mt-sp-4 flex flex-wrap gap-sp-2"> <div className="mt-sp-4 flex flex-wrap gap-sp-2">
<button <button
type="button" type="button"
@@ -257,13 +278,13 @@ function GoogleAnalyticsConsent() {
Analytics está {consent === "granted" ? "ativo" : "desativado"}. Analytics está {consent === "granted" ? "ativo" : "desativado"}.
Dados de publicidade permanecem negados. Dados de publicidade permanecem negados.
</p> </p>
{revokeError && ( {consentError && (
<p <p
role="alert" role="alert"
aria-label="Falha ao salvar a revogação" aria-label="Falha ao salvar o consentimento"
className="mt-sp-3 text-[13px] leading-6 text-[var(--slash)]" className="mt-sp-3 text-[13px] leading-6 text-[var(--slash)]"
> >
{revokeError} {consentError}
</p> </p>
)} )}
<div className="mt-sp-4 flex flex-wrap gap-sp-2"> <div className="mt-sp-4 flex flex-wrap gap-sp-2">
@@ -133,7 +133,7 @@ describe("ControlRoomGlobe lifecycle", () => {
expect(state.height).toBe(1040); expect(state.height).toBe(1040);
}); });
it("keeps the reduced-motion globe static", async () => { it("keeps the reduced-motion globe static while tracking dimensions", async () => {
render(<ControlRoomGlobe autoRotate={false} />); render(<ControlRoomGlobe autoRotate={false} />);
await waitFor(() => expect(createGlobe).toHaveBeenCalled()); await waitFor(() => expect(createGlobe).toHaveBeenCalled());
setGlobeIntersects(true); setGlobeIntersects(true);
@@ -141,6 +141,6 @@ describe("ControlRoomGlobe lifecycle", () => {
renderCallback()(state); renderCallback()(state);
expect(state).toEqual({ phi: 0, theta: 0, width: 0, height: 0 }); expect(state).toEqual({ phi: 0, theta: 0, width: 800, height: 800 });
}); });
}); });
@@ -123,6 +123,9 @@ export function ControlRoomGlobe({
width: initialRenderWidth, width: initialRenderWidth,
height: initialRenderWidth, height: initialRenderWidth,
onRender: (state) => { onRender: (state) => {
const renderWidth = widthRef.current * dpr;
state.width = renderWidth;
state.height = renderWidth;
if (!autoRotate || !intersectsRef.current || document.hidden) if (!autoRotate || !intersectsRef.current || document.hidden)
return; return;
if (!pointerInteracting.current) { if (!pointerInteracting.current) {
@@ -135,9 +138,6 @@ export function ControlRoomGlobe({
(config.theta ?? TROPIC_OF_CAPRICORN_RAD) + (config.theta ?? TROPIC_OF_CAPRICORN_RAD) +
Math.sin(thetaPhaseRef.current) * 0.35 + Math.sin(thetaPhaseRef.current) * 0.35 +
thetaDragRef.current; thetaDragRef.current;
const renderWidth = widthRef.current * dpr;
state.width = renderWidth;
state.height = renderWidth;
}, },
}); });
} }