diff --git a/cypress/e2e/pensjon/kalkulator/ufoeretrygd.cy.ts b/cypress/e2e/pensjon/kalkulator/ufoeretrygd.cy.ts index 2badcc4f4..96be34a98 100644 --- a/cypress/e2e/pensjon/kalkulator/ufoeretrygd.cy.ts +++ b/cypress/e2e/pensjon/kalkulator/ufoeretrygd.cy.ts @@ -26,7 +26,7 @@ describe('Med ufoeretrygd', () => { { ...loependeVedtakMock, ufoeretrygd: { - grad: 100, + grad: 90, }, } ).as('getLoependeVedtak') @@ -54,7 +54,7 @@ describe('Med ufoeretrygd', () => { { ...loependeVedtakMock, ufoeretrygd: { - grad: 100, + grad: 90, }, } ).as('getLoependeVedtak') @@ -200,7 +200,7 @@ describe('Med ufoeretrygd', () => { { ...loependeVedtakMock, ufoeretrygd: { - grad: 100, + grad: 90, }, } ).as('getLoependeVedtak') diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts index 0fe9557a8..547ad3a84 100644 --- a/cypress/support/e2e.ts +++ b/cypress/support/e2e.ts @@ -3,6 +3,11 @@ import 'cypress-axe' import { userInputActions } from '../../src/state/userInput/userInputReducer' beforeEach(() => { + cy.setCookie( + 'navno-consent', + '{%22consent%22:{%22analytics%22:false%2C%22surveys%22:false}%2C%22userActionTaken%22:true%2C%22meta%22:{%22createdAt%22:%222025-02-17T09:17:38.688Z%22%2C%22updatedAt%22:%222025-02-17T09:17:38.688Z%22%2C%22version%22:1}}' + ) // Skjuler cookiebanner (har ingenting å si for testene, er kun for å slippe å se det når tester lokalt) + cy.intercept( { method: 'GET', diff --git a/src/components/Grunnlag/GrunnlagAFP/GrunnlagAFP.tsx b/src/components/Grunnlag/GrunnlagAFP/GrunnlagAFP.tsx index b57e1f175..30156c58e 100644 --- a/src/components/Grunnlag/GrunnlagAFP/GrunnlagAFP.tsx +++ b/src/components/Grunnlag/GrunnlagAFP/GrunnlagAFP.tsx @@ -58,20 +58,29 @@ export const GrunnlagAFP: React.FC = ({ goToStart }) => { if (!harSamtykketOffentligAFP && !ufoeregrad && afp === 'ja_offentlig') { return `${afpString} (${intl.formatMessage({ id: 'grunnlag.afp.ikke_beregnet' })})` } + + if (ufoeregrad === 100) { + return formatAfp(intl, 'nei') + } + return afpString }, [afp]) const formatertAfpIngress = React.useMemo(() => { if (isEndring && loependeVedtak.afpPrivat) { - return `grunnlag.afp.ingress.ja_privat.endring` + return 'grunnlag.afp.ingress.ja_privat.endring' } if (loependeVedtak.afpOffentlig) { - return `grunnlag.afp.ingress.ja_offentlig.endring` + return 'grunnlag.afp.ingress.ja_offentlig.endring' } if (isEndring && afp === 'nei') { - return `grunnlag.afp.ingress.nei.endring` + return 'grunnlag.afp.ingress.nei.endring' + } + + if (ufoeregrad === 100) { + return 'grunnlag.afp.ingress.full_ufoeretrygd' } const afpString = diff --git a/src/components/Grunnlag/GrunnlagAFP/__tests__/GrunnlagAFP.test.tsx b/src/components/Grunnlag/GrunnlagAFP/__tests__/GrunnlagAFP.test.tsx index 9577763c7..e41456380 100644 --- a/src/components/Grunnlag/GrunnlagAFP/__tests__/GrunnlagAFP.test.tsx +++ b/src/components/Grunnlag/GrunnlagAFP/__tests__/GrunnlagAFP.test.tsx @@ -3,6 +3,7 @@ import { add, endOfDay, format } from 'date-fns' import { GrunnlagAFP } from '..' import { fulfilledGetLoependeVedtak0Ufoeregrad, + fulfilledGetLoependeVedtak100Ufoeregrad, fulfilledGetLoependeVedtak75Ufoeregrad, fulfilledGetLoependeVedtakLoepende50Alderspensjon, fulfilledGetLoependeVedtakLoependeAFPoffentlig, @@ -170,8 +171,8 @@ describe('Grunnlag - AFP', () => { ).toBeVisible() }) - describe('Gitt at brukeren har uføretrygd,', () => { - describe('Gitt at brukeren er eldre enn minimum uttaksalderen,', () => { + describe('Gitt at brukeren har gradert uføretrygd,', () => { + describe('Gitt at brukeren er eldre enn AFP-Uføre oppsigelsesalder,', () => { const minAlderYearsBeforeNow = add(endOfDay(new Date()), { years: -63, months: -1, @@ -194,8 +195,8 @@ describe('Grunnlag - AFP', () => { }, } - it('Når hen er yngre enn 62 år, returneres null', async () => { - render(, { + it('returneres null', async () => { + const { asFragment } = render(, { preloadedState: { api: { // @ts-ignore @@ -207,12 +208,11 @@ describe('Grunnlag - AFP', () => { }, }, }) - - expect(screen.queryByText('grunnlag.afp.title')).toBeNull() + expect(asFragment()).toMatchInlineSnapshot('') }) }) - describe('Gitt at brukeren er yngre enn minimum uttaksalderen,', () => { + describe('Gitt at brukeren er yngre enn AFP-Uføre oppsigelsesalder,', () => { const minAlderYearsBeforeNow = add(endOfDay(new Date()), { years: -61, months: -11, @@ -328,6 +328,29 @@ describe('Grunnlag - AFP', () => { }) }) + describe('Gitt at brukeren har 100% uføretrygd,', () => { + it('Viser riktig tittel og tekst', () => { + render(, { + preloadedState: { + api: { + // @ts-ignore + queries: { ...fulfilledGetLoependeVedtak100Ufoeregrad }, + }, + userInput: { ...userInputInitialState }, + }, + }) + + expect(screen.getByText('grunnlag.afp.title')).toBeVisible() + expect(screen.getByText('afp.nei')).toBeVisible() + expect( + screen.getByText( + 'For å ha rett til AFP, må du være ansatt i offentlig sektor eller i en bedrift med AFP-ordning i privat sektor. Det gjelder de siste årene og helt fram til du tar ut AFP. Hvis du mottar full uføretrygd, har du derfor normalt ikke rett til AFP.', + { exact: false } + ) + ).toBeInTheDocument() + }) + }) + describe('Gitt at brukeren har vedtak om alderspensjon,', () => { it('Når hen har valgt AFP privat, viser riktig tittel med formatert inntekt og tekst', async () => { const user = userEvent.setup() diff --git a/src/router/__tests__/loaders.test.tsx b/src/router/__tests__/loaders.test.tsx index c08c48540..dba6469b2 100644 --- a/src/router/__tests__/loaders.test.tsx +++ b/src/router/__tests__/loaders.test.tsx @@ -19,6 +19,7 @@ import { fulfilledGetLoependeVedtak75Ufoeregrad, fulfilledGetLoependeVedtakLoependeAFPprivat, fulfilledGetLoependeVedtakLoependeAFPoffentlig, + fulfilledGetLoependeVedtak100Ufoeregrad, } from '@/mocks/mockedRTKQueryApiCalls' import { mockErrorResponse, mockResponse } from '@/mocks/server' import { externalUrls, henvisningUrlParams, paths } from '@/router/constants' @@ -436,7 +437,6 @@ describe('Loaders', () => { }) const returnedFromLoader = await stepSivilstandAccessGuard() - console.log(returnedFromLoader) const person = await ( returnedFromLoader as StepSivilstandAccessGuardLoader ).getPersonQuery @@ -584,7 +584,7 @@ describe('Loaders', () => { expect(shouldRedirectToResponse).toBe('') }) - it('brukere med uføretrygd som ikke er fylt minimum uttaksalder, er ikke redirigert', async () => { + it('brukere med gradert uføretrygd som er yngre enn AFP-Uføre oppsigelsesalder, er ikke redirigert', async () => { const minAlderYearsBeforeNow = add(endOfDay(new Date()), { years: -61, months: -11, @@ -622,7 +622,7 @@ describe('Loaders', () => { expect(shouldRedirectToResponse).toBe('') }) - it('brukere med uføretrygd som er fylt minimum uttaksalder, er redirigert', async () => { + it('brukere med gradert uføretrygd som er eldre enn AFP-Uføre oppsigelsesalder, er redirigert', async () => { const minAlderYearsBeforeNow = add(endOfDay(new Date()), { years: -62, }) @@ -700,6 +700,25 @@ describe('Loaders', () => { ).shouldRedirectTo expect(shouldRedirectToResponse).toBe(paths.ufoeretrygdAFP) }) + + it('brukere med 100% uføretrygd er redirigert', async () => { + const mockedState = { + api: { + queries: { + ...mockedVellykketQueries, + ...fulfilledGetLoependeVedtak100Ufoeregrad, + ...fulfilledGetPerson, + }, + }, + userInput: { ...userInputInitialState }, + } + store.getState = vi.fn().mockImplementation(() => mockedState) + const returnedFromLoader = await stepAFPAccessGuard() + const shouldRedirectToResponse = + 'shouldRedirectTo' in returnedFromLoader && + (await returnedFromLoader.shouldRedirectTo) + expect(shouldRedirectToResponse).toBe(paths.ufoeretrygdAFP) + }) }) it('Gitt at getInntekt har tidligere feilet kalles den på nytt. Når den er vellykket i tillegg til de to andre kallene, er brukeren ikke redirigert', async () => { @@ -1053,63 +1072,27 @@ describe('Loaders', () => { }) describe('Gitt at brukeren har uføretrygd, ', () => { - it('Når hen har svart ja til spørsmål om afp og er ikke fylt minimum uttaksalder, er hen ikke redirigert', async () => { - const minAlderYearsBeforeNow = add(endOfDay(new Date()), { - years: -61, - months: -11, - }) - const foedselsdato = format(minAlderYearsBeforeNow, DATE_BACKEND_FORMAT) - + it('Når hen har svart ja til spørsmål om afp, er hen ikke redirigert', async () => { const mockedState = { api: { queries: { - ['getPerson(undefined)']: { - status: 'fulfilled', - endpointName: 'getPerson', - requestId: 'xTaE6mOydr5ZI75UXq4Wi', - startedTimeStamp: 1688046411971, - data: { - navn: 'Aprikos', - sivilstand: 'UGIFT', - foedselsdato, - }, - fulfilledTimeStamp: 1688046412103, - }, + ...fulfilledGetPerson, ...fulfilledGetLoependeVedtak75Ufoeregrad, }, }, userInput: { ...userInputInitialState, afp: 'ja_privat' }, } - store.getState = vi.fn().mockImplementation(() => { - return mockedState - }) + store.getState = vi.fn().mockImplementation(() => mockedState) const returnedFromLoader = await stepUfoeretrygdAFPAccessGuard() expect(returnedFromLoader).toBeNull() }) - it('Når hen har svart nei til spørsmål om afp og er ikke fylt minimum uttaksalder, er hen ikke redirigert', async () => { - const minAlderYearsBeforeNow = add(endOfDay(new Date()), { - years: -61, - months: -11, - }) - const foedselsdato = format(minAlderYearsBeforeNow, DATE_BACKEND_FORMAT) - + it('Når hen har svart nei til spørsmål om afp, er hen redirigert', async () => { const mockedState = { api: { queries: { - ['getPerson(undefined)']: { - status: 'fulfilled', - endpointName: 'getPerson', - requestId: 'xTaE6mOydr5ZI75UXq4Wi', - startedTimeStamp: 1688046411971, - data: { - navn: 'Aprikos', - sivilstand: 'UGIFT', - foedselsdato, - }, - fulfilledTimeStamp: 1688046412103, - }, + ...fulfilledGetPerson, ...fulfilledGetLoependeVedtak75Ufoeregrad, }, }, @@ -1120,68 +1103,27 @@ describe('Loaders', () => { }) const returnedFromLoader = await stepUfoeretrygdAFPAccessGuard() - expect(returnedFromLoader).not.toBeNull() + expect(returnedFromLoader?.headers.get('location')).toBe( + '/samtykke-offentlig-afp' + ) }) - it('Når hen er fylt minimum uttaksalder, er hen redirigert', async () => { - const minAlderYearsBeforeNow = add(endOfDay(new Date()), { - years: -62, - }) - const foedselsdato = format(minAlderYearsBeforeNow, DATE_BACKEND_FORMAT) - + it('Når hen ikke har fått afp-steget (og dermed ikke har svart på spørsmål om afp), er hen redirigert', async () => { const mockedState = { api: { queries: { - ['getPerson(undefined)']: { - status: 'fulfilled', - endpointName: 'getPerson', - requestId: 'xTaE6mOydr5ZI75UXq4Wi', - startedTimeStamp: 1688046411971, - data: { - navn: 'Aprikos', - sivilstand: 'UGIFT', - foedselsdato, - }, - fulfilledTimeStamp: 1688046412103, - }, + ...fulfilledGetPerson, ...fulfilledGetLoependeVedtak75Ufoeregrad, }, }, - userInput: { ...userInputInitialState, afp: 'nei' }, + userInput: { ...userInputInitialState, afp: null }, } - store.getState = vi.fn().mockImplementation(() => { - return mockedState - }) + store.getState = vi.fn().mockImplementation(() => mockedState) const returnedFromLoader = await stepUfoeretrygdAFPAccessGuard() - expect(returnedFromLoader).not.toBeNull() - expect(returnedFromLoader).toMatchInlineSnapshot(` - Response { - Symbol(state): { - "aborted": false, - "cacheState": "", - "headersList": HeadersList { - "cookies": null, - Symbol(headers map): Map { - "location" => { - "name": "location", - "value": "/samtykke-offentlig-afp", - }, - }, - Symbol(headers map sorted): null, - }, - "rangeRequested": false, - "requestIncludesCredentials": false, - "status": 302, - "statusText": "", - "timingAllowPassed": false, - "timingInfo": null, - "type": "default", - "urlList": [], - }, - Symbol(headers): Headers {}, - } - `) + expect(returnedFromLoader?.headers.get('location')).toBe( + '/samtykke-offentlig-afp' + ) }) }) }) diff --git a/src/router/__tests__/routes.test.tsx b/src/router/__tests__/routes.test.tsx index ee81e46dd..2b06aa1ee 100644 --- a/src/router/__tests__/routes.test.tsx +++ b/src/router/__tests__/routes.test.tsx @@ -545,16 +545,13 @@ describe('routes', () => { ...fulfilledGetLoependeVedtak75Ufoeregrad, }, }, - userInput: { ...userInputInitialState }, + userInput: { ...userInputInitialState, afp: 'ja_offentlig' }, })) const router = createMemoryRouter(routes, { basename: BASE_PATH, initialEntries: [`${BASE_PATH}${paths.ufoeretrygdAFP}`], }) render(, { - preloadedState: { - userInput: { ...userInputInitialState, afp: 'ja_offentlig' }, - }, hasRouter: false, }) expect( diff --git a/src/router/constants.ts b/src/router/constants.ts index 5c7c0d865..0159063fa 100644 --- a/src/router/constants.ts +++ b/src/router/constants.ts @@ -23,6 +23,7 @@ export const externalUrls = { trygdetid: 'https://www.nav.no/no/person/flere-tema/arbeid-og-opphold-i-norge/relatert-informasjon/medlemskap-i-folketrygden', kortBotid: 'https://www.nav.no/alderspensjon#kort-botid', + ufoeretrygdOgAfp: 'https://www.nav.no/ufor-til-pensjon#afp', byttBruker: import.meta.env.VITE_BYTT_BRUKER_URL, personopplysninger: 'https://www.nav.no/personopplysninger-i-pensjonskalkulator', diff --git a/src/router/loaders.tsx b/src/router/loaders.tsx index 793291bc2..7d755e1e0 100644 --- a/src/router/loaders.tsx +++ b/src/router/loaders.tsx @@ -302,12 +302,14 @@ export const stepAFPAccessGuard = async (): Promise< ? stegvisningOrderEndring : stegvisningOrder - // Hvis brukeren mottar AFP skal hen ikke se AFP steget - // Hvis brukeren har uføretrygd og er eldre enn min uttaksalder skal hen ikke se AFP steget + // Hvis brukeren mottar AFP skal hen ikke se AFP-steget + // Hvis brukeren har 100% uføretrygd skal hen ikke se AFP-steget + // Hvis brukeren har gradert uføretrygd og er eldre enn AFP-Uføre oppsigelsesalder skal hen ikke se AFP-steget const redirectFromAFPSteg = (): string => { if ( afpPrivat || afpOffentlig || + ufoeretrygd.grad === 100 || (ufoeretrygd.grad && foedselsdato && isFoedselsdatoOverEllerLikMinUttaksalder(foedselsdato)) @@ -421,23 +423,20 @@ export const stepUfoeretrygdAFPAccessGuard = return redirect(paths.start) } - const afp = selectAfp(store.getState()) - const foedselsdato = selectFoedselsdato(store.getState()) - const getLoependeVedtakResponse = - apiSlice.endpoints.getLoependeVedtak.select(undefined)(store.getState()) + const state = store.getState() + const afp = selectAfp(state) + const foedselsdato = selectFoedselsdato(state) + if (!foedselsdato) throw new Error('Missing foedselsdato') + const loependeVedtak = + apiSlice.endpoints.getLoependeVedtak.select()(state).data + if (!loependeVedtak) throw new Error('Missing loependeVedtak') - const stepArrays = isLoependeVedtakEndring( - getLoependeVedtakResponse.data as LoependeVedtak - ) + const stepArrays = isLoependeVedtakEndring(loependeVedtak) ? stegvisningOrderEndring : stegvisningOrder - // Bruker med uføretrygd, som svarer ja til afp, og som er under 62 kan se steget - if ( - (getLoependeVedtakResponse.data as LoependeVedtak).ufoeretrygd.grad && - afp !== 'nei' && - !isFoedselsdatoOverEllerLikMinUttaksalder(foedselsdato as string) - ) { + // Brukere med uføretrygd som har svart ja eller vet_ikke til AFP kan se steget + if (loependeVedtak.ufoeretrygd.grad && afp && afp !== 'nei') { return null } return redirect(stepArrays[stepArrays.indexOf(paths.ufoeretrygdAFP) + 1]) @@ -460,6 +459,8 @@ export const stepSamtykkeOffentligAFPAccessGuard = ) ? stegvisningOrderEndring : stegvisningOrder + + // Bruker uten uføretrygd som svarer ja_offentlig til AFP kan se steget if ( (getLoependeVedtakResponse.data as LoependeVedtak).ufoeretrygd.grad === 0 && diff --git a/src/translations/nb.ts b/src/translations/nb.ts index bdde4886f..59e93dea9 100644 --- a/src/translations/nb.ts +++ b/src/translations/nb.ts @@ -599,6 +599,8 @@ const translations = { 'Du har AFP i privat sektor. Din AFP er ikke påvirket av endringen din av alderspensjon. Den fortsetter som før.', 'grunnlag.afp.ingress.nei.endring': 'Du har oppgitt at du ikke har rett til AFP. Hvis du er usikker på om du har AFP bør du spørre arbeidsgiveren din. AFP kan påvirke når du kan ta ut alderspensjon.', + 'grunnlag.afp.ingress.full_ufoeretrygd': + 'For å ha rett til AFP, må du være ansatt i offentlig sektor eller i en bedrift med AFP-ordning i privat sektor. Det gjelder de siste årene og helt fram til du tar ut AFP. Hvis du mottar full uføretrygd, har du derfor normalt ikke rett til AFP.{br}{br}Du kan ikke kombinere AFP og uføretrygd. Får du utbetalt uføretrygd etter du fyller 62 år mister du retten til AFP.{br}{br}Vil du vite mer? Les mer om Uføretrygd og AFP.', 'grunnlag.afp.reset_link': 'ny beregning', 'grunnlag.forbehold.ingress_1': 'Pensjonen er beregnet med opplysningene vi har om deg og opplysningene du har oppgitt. Beregningen er gjort med gjeldende regelverk. Dette er et foreløpig estimat på hva du kan forvente deg i pensjon. Nav er ikke ansvarlig for beløpene som er hentet inn fra andre. ', diff --git a/src/utils/__tests__/test-translations.ts b/src/utils/__tests__/test-translations.ts index 53a787669..be4f27c19 100644 --- a/src/utils/__tests__/test-translations.ts +++ b/src/utils/__tests__/test-translations.ts @@ -28,6 +28,8 @@ const translations = { 'lorem ipsum dolor my link', 'translation.test.kortBotidLink': 'lorem ipsum dolor my link', + 'translation.test.ufoeretrygdOgAfpLink': + 'lorem ipsum dolor my link', 'translation.test.personopplysningerLink': 'lorem ipsum dolor my link', 'translation.test.spkLink': 'lorem ipsum dolor my link', diff --git a/src/utils/__tests__/translations.test.tsx b/src/utils/__tests__/translations.test.tsx index 40fb3c86d..40bd09488 100644 --- a/src/utils/__tests__/translations.test.tsx +++ b/src/utils/__tests__/translations.test.tsx @@ -330,6 +330,29 @@ describe('translations-utils', () => { ).toBeInTheDocument() }) + it('formaterer med riktig url og ikon', async () => { + render( + + ) + expect( + screen.getByText('lorem ipsum dolor', { exact: false }) + ).toBeInTheDocument() + + expect(screen.getByText('my link', { exact: false })).toBeInTheDocument() + + expect(screen.queryByRole('link')).toHaveAttribute( + 'href', + externalUrls.ufoeretrygdOgAfp + ) + + expect( + await screen.findByRole('img', { hidden: true }) + ).toBeInTheDocument() + }) + it('formaterer med riktig url og ikon', async () => { render( ), + ufoeretrygdOgAfpLink: (chunks: string) => ( + + {chunks} + + + ), personopplysningerLink: (chunks: string) => (