From 1c64c079d4511f9ec6c997b848c883c4eb7c1bba Mon Sep 17 00:00:00 2001 From: Matthew Guest - Work Date: Thu, 6 Mar 2025 12:44:33 -0800 Subject: [PATCH 1/4] Added new vets_verification_status endpoint into the app --- .../types/VeteranVerificationStatusData.ts | 15 ++++++++ VAMobile/src/api/types/index.ts | 1 + .../api/veteranStatus/getVeteranStatus.tsx | 34 +++++++++++++++++++ VAMobile/src/api/veteranStatus/index.ts | 2 ++ VAMobile/src/api/veteranStatus/queryKeys.ts | 3 ++ 5 files changed, 55 insertions(+) create mode 100644 VAMobile/src/api/types/VeteranVerificationStatusData.ts create mode 100644 VAMobile/src/api/veteranStatus/getVeteranStatus.tsx create mode 100644 VAMobile/src/api/veteranStatus/index.ts create mode 100644 VAMobile/src/api/veteranStatus/queryKeys.ts diff --git a/VAMobile/src/api/types/VeteranVerificationStatusData.ts b/VAMobile/src/api/types/VeteranVerificationStatusData.ts new file mode 100644 index 00000000000..35a84716f9e --- /dev/null +++ b/VAMobile/src/api/types/VeteranVerificationStatusData.ts @@ -0,0 +1,15 @@ +export type VeteranStatus = 'confirmed' | 'not confirmed' + +export type VeteranVerificationStatusDataAttributes = { + veteranStatus: VeteranStatus + notConfirmedReason?: string +} + +export type VeteranVerificationStatusData = { + data: { + id: string + type: string + attributes: VeteranVerificationStatusDataAttributes + message?: string[] + } +} diff --git a/VAMobile/src/api/types/index.ts b/VAMobile/src/api/types/index.ts index 6147a71e951..9d2c8bac323 100644 --- a/VAMobile/src/api/types/index.ts +++ b/VAMobile/src/api/types/index.ts @@ -18,3 +18,4 @@ export * from './PrescriptionData' export * from './SecureMessagingData' export * from './ServiceHistoryData' export * from './VaccineData' +export * from './VeteranVerificationStatusData' diff --git a/VAMobile/src/api/veteranStatus/getVeteranStatus.tsx b/VAMobile/src/api/veteranStatus/getVeteranStatus.tsx new file mode 100644 index 00000000000..704c4804ade --- /dev/null +++ b/VAMobile/src/api/veteranStatus/getVeteranStatus.tsx @@ -0,0 +1,34 @@ +import { useQuery } from '@tanstack/react-query' + +import { VeteranVerificationStatusData } from 'api/types' +import { ACTIVITY_STALE_TIME } from 'constants/common' +import { get } from 'store/api' + +import { veteranStatusKeys } from './queryKeys' + +/** + * Fetch user veteran verification status + */ +const getVeteranStatus = async (): Promise => { + const response = await get('/v0/vet_verification_status') + if (response) { + return { + ...response, + } + } +} + +/** + * Returns a query for a users veteran verification status + */ +export const useVeteranStatus = (options?: { enabled?: boolean }) => { + return useQuery({ + ...options, + queryKey: veteranStatusKeys.verification, + queryFn: () => getVeteranStatus(), + meta: { + errorName: 'getVeteranStatus: Service error', + }, + staleTime: ACTIVITY_STALE_TIME, + }) +} diff --git a/VAMobile/src/api/veteranStatus/index.ts b/VAMobile/src/api/veteranStatus/index.ts new file mode 100644 index 00000000000..ab77de4165b --- /dev/null +++ b/VAMobile/src/api/veteranStatus/index.ts @@ -0,0 +1,2 @@ +export * from './getVeteranStatus' +export * from './queryKeys' diff --git a/VAMobile/src/api/veteranStatus/queryKeys.ts b/VAMobile/src/api/veteranStatus/queryKeys.ts new file mode 100644 index 00000000000..fa85fab3dcc --- /dev/null +++ b/VAMobile/src/api/veteranStatus/queryKeys.ts @@ -0,0 +1,3 @@ +export const veteranStatusKeys = { + verification: ['verification'] as const, +} From db83e7c6c39b329d94f52e9d5401343de0f2a53b Mon Sep 17 00:00:00 2001 From: Matthew Guest - Work Date: Thu, 6 Mar 2025 15:34:43 -0800 Subject: [PATCH 2/4] Added a test file that tests the query function getVeteranStatus. These tests cover all the various responses and reasons we can get back from the vet_verification_status endpoint. --- .../veteranStatus/getVeteranStatus.test.tsx | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 VAMobile/src/api/veteranStatus/getVeteranStatus.test.tsx diff --git a/VAMobile/src/api/veteranStatus/getVeteranStatus.test.tsx b/VAMobile/src/api/veteranStatus/getVeteranStatus.test.tsx new file mode 100644 index 00000000000..f6112c10ed1 --- /dev/null +++ b/VAMobile/src/api/veteranStatus/getVeteranStatus.test.tsx @@ -0,0 +1,140 @@ +import React from 'react' + +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { renderHook, waitFor } from '@testing-library/react-native' + +import { VeteranVerificationStatusData } from 'api/types' +import { get } from 'store/api' + +import { useVeteranStatus } from './getVeteranStatus' + +jest.mock('store/api', () => ({ + get: jest.fn(), +})) + +const createWrapper = () => { + const queryClient = new QueryClient() + return ({ children }: { children: React.ReactNode }) => ( + {children} + ) +} + +describe('useVeteranStatus', () => { + it('returns data on success when "confirmed"', async () => { + const mockData: VeteranVerificationStatusData = { + data: { + id: '', + type: 'veteran_status_confirmations', + attributes: { + veteranStatus: 'confirmed', + }, + }, + } + ;(get as jest.Mock).mockResolvedValue(mockData) + + const { result } = renderHook(() => useVeteranStatus(), { wrapper: createWrapper() }) + await waitFor(() => expect(result.current.isSuccess).toBe(true)) + + expect(result.current.data).toEqual(mockData) + }) + + it('returns "not confirmed" with reason "NOT_TITLE_38"', async () => { + const mockData: VeteranVerificationStatusData = { + data: { + id: '', + type: 'veteran_status_confirmations', + attributes: { + veteranStatus: 'not confirmed', + notConfirmedReason: 'NOT_TITLE_38', + }, + message: ['Our records show that you’re not eligible...', 'If you think your discharge status is incorrect...'], + }, + } + ;(get as jest.Mock).mockResolvedValue(mockData) + + const { result } = renderHook(() => useVeteranStatus(), { wrapper: createWrapper() }) + await waitFor(() => expect(result.current.isSuccess).toBe(true)) + + expect(result.current.data?.data.attributes.veteranStatus).toBe('not confirmed') + expect(result.current.data?.data.attributes.notConfirmedReason).toBe('NOT_TITLE_38') + expect(result.current.data?.data.message).toHaveLength(2) + }) + + it('returns "not confirmed" with reason "MORE_RESEARCH_REQUIRED"', async () => { + const mockData: VeteranVerificationStatusData = { + data: { + id: '', + type: 'veteran_status_confirmations', + attributes: { + veteranStatus: 'not confirmed', + notConfirmedReason: 'MORE_RESEARCH_REQUIRED', + }, + message: [ + 'We’re sorry. There’s a problem with your discharge status records.', + 'To fix the problem with your records...', + ], + }, + } + ;(get as jest.Mock).mockResolvedValue(mockData) + + const { result } = renderHook(() => useVeteranStatus(), { wrapper: createWrapper() }) + await waitFor(() => expect(result.current.isSuccess).toBe(true)) + + expect(result.current.data?.data.attributes.veteranStatus).toBe('not confirmed') + expect(result.current.data?.data.attributes.notConfirmedReason).toBe('MORE_RESEARCH_REQUIRED') + expect(result.current.data?.data.message).toHaveLength(2) + }) + + it('returns "not confirmed" with reason "PERSON_NOT_FOUND"', async () => { + const mockData: VeteranVerificationStatusData = { + data: { + id: '', + type: 'veteran_status_confirmations', + attributes: { + veteranStatus: 'not confirmed', + notConfirmedReason: 'PERSON_NOT_FOUND', + }, + message: [ + 'We’re sorry. There’s a problem with your discharge status records.', + 'To fix the problem with your records...', + ], + }, + } + ;(get as jest.Mock).mockResolvedValue(mockData) + + const { result } = renderHook(() => useVeteranStatus(), { wrapper: createWrapper() }) + await waitFor(() => expect(result.current.isSuccess).toBe(true)) + + expect(result.current.data?.data.attributes.veteranStatus).toBe('not confirmed') + expect(result.current.data?.data.attributes.notConfirmedReason).toBe('PERSON_NOT_FOUND') + expect(result.current.data?.data.message).toHaveLength(2) + }) + + it('returns "not confirmed" with reason "ERROR"', async () => { + const mockData: VeteranVerificationStatusData = { + data: { + id: '', + type: 'veteran_status_confirmations', + attributes: { + veteranStatus: 'not confirmed', + notConfirmedReason: 'ERROR', + }, + message: ["We're sorry. Something went wrong on our end. Try to view your Veteran status card later."], + }, + } + ;(get as jest.Mock).mockResolvedValue(mockData) + + const { result } = renderHook(() => useVeteranStatus(), { + wrapper: createWrapper(), + }) + + await waitFor(() => expect(result.current.isSuccess).toBe(true)) + + expect(result.current.isSuccess).toBe(true) + expect(result.current.data?.data.attributes.veteranStatus).toBe('not confirmed') + expect(result.current.data?.data.attributes.notConfirmedReason).toBe('ERROR') + expect(result.current.data?.data.message).toEqual([ + "We're sorry. Something went wrong on our end. Try to view your Veteran status card later.", + ]) + }) +}) From 54bc10bc24ced3a7a1c0319c7a00696f14355c9a Mon Sep 17 00:00:00 2001 From: Matthew Guest - Work Date: Thu, 6 Mar 2025 15:47:50 -0800 Subject: [PATCH 3/4] Updated some function text. --- VAMobile/src/api/veteranStatus/getVeteranStatus.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/VAMobile/src/api/veteranStatus/getVeteranStatus.tsx b/VAMobile/src/api/veteranStatus/getVeteranStatus.tsx index 704c4804ade..0749fd8e29e 100644 --- a/VAMobile/src/api/veteranStatus/getVeteranStatus.tsx +++ b/VAMobile/src/api/veteranStatus/getVeteranStatus.tsx @@ -7,7 +7,7 @@ import { get } from 'store/api' import { veteranStatusKeys } from './queryKeys' /** - * Fetch user veteran verification status + * Fetch veteran verification status */ const getVeteranStatus = async (): Promise => { const response = await get('/v0/vet_verification_status') @@ -19,7 +19,7 @@ const getVeteranStatus = async (): Promise { return useQuery({ From b637feb292f98e9e154776d71f5dc126ffd7b179 Mon Sep 17 00:00:00 2001 From: Matthew Guest - Work Date: Fri, 7 Mar 2025 13:01:59 -0800 Subject: [PATCH 4/4] Addressed PR comments. Removed unit tests and updated name of data type for veteran status. --- ...ts => VeteranVerificationStatusPayload.ts} | 2 +- VAMobile/src/api/types/index.ts | 2 +- .../veteranStatus/getVeteranStatus.test.tsx | 140 ------------------ .../api/veteranStatus/getVeteranStatus.tsx | 10 +- 4 files changed, 6 insertions(+), 148 deletions(-) rename VAMobile/src/api/types/{VeteranVerificationStatusData.ts => VeteranVerificationStatusPayload.ts} (86%) delete mode 100644 VAMobile/src/api/veteranStatus/getVeteranStatus.test.tsx diff --git a/VAMobile/src/api/types/VeteranVerificationStatusData.ts b/VAMobile/src/api/types/VeteranVerificationStatusPayload.ts similarity index 86% rename from VAMobile/src/api/types/VeteranVerificationStatusData.ts rename to VAMobile/src/api/types/VeteranVerificationStatusPayload.ts index 35a84716f9e..824a80b0653 100644 --- a/VAMobile/src/api/types/VeteranVerificationStatusData.ts +++ b/VAMobile/src/api/types/VeteranVerificationStatusPayload.ts @@ -5,7 +5,7 @@ export type VeteranVerificationStatusDataAttributes = { notConfirmedReason?: string } -export type VeteranVerificationStatusData = { +export type VeteranVerificationStatusPayload = { data: { id: string type: string diff --git a/VAMobile/src/api/types/index.ts b/VAMobile/src/api/types/index.ts index 9d2c8bac323..7de75507d2c 100644 --- a/VAMobile/src/api/types/index.ts +++ b/VAMobile/src/api/types/index.ts @@ -18,4 +18,4 @@ export * from './PrescriptionData' export * from './SecureMessagingData' export * from './ServiceHistoryData' export * from './VaccineData' -export * from './VeteranVerificationStatusData' +export * from './VeteranVerificationStatusPayload' diff --git a/VAMobile/src/api/veteranStatus/getVeteranStatus.test.tsx b/VAMobile/src/api/veteranStatus/getVeteranStatus.test.tsx deleted file mode 100644 index f6112c10ed1..00000000000 --- a/VAMobile/src/api/veteranStatus/getVeteranStatus.test.tsx +++ /dev/null @@ -1,140 +0,0 @@ -import React from 'react' - -import { QueryClient, QueryClientProvider } from '@tanstack/react-query' -import { renderHook, waitFor } from '@testing-library/react-native' - -import { VeteranVerificationStatusData } from 'api/types' -import { get } from 'store/api' - -import { useVeteranStatus } from './getVeteranStatus' - -jest.mock('store/api', () => ({ - get: jest.fn(), -})) - -const createWrapper = () => { - const queryClient = new QueryClient() - return ({ children }: { children: React.ReactNode }) => ( - {children} - ) -} - -describe('useVeteranStatus', () => { - it('returns data on success when "confirmed"', async () => { - const mockData: VeteranVerificationStatusData = { - data: { - id: '', - type: 'veteran_status_confirmations', - attributes: { - veteranStatus: 'confirmed', - }, - }, - } - ;(get as jest.Mock).mockResolvedValue(mockData) - - const { result } = renderHook(() => useVeteranStatus(), { wrapper: createWrapper() }) - await waitFor(() => expect(result.current.isSuccess).toBe(true)) - - expect(result.current.data).toEqual(mockData) - }) - - it('returns "not confirmed" with reason "NOT_TITLE_38"', async () => { - const mockData: VeteranVerificationStatusData = { - data: { - id: '', - type: 'veteran_status_confirmations', - attributes: { - veteranStatus: 'not confirmed', - notConfirmedReason: 'NOT_TITLE_38', - }, - message: ['Our records show that you’re not eligible...', 'If you think your discharge status is incorrect...'], - }, - } - ;(get as jest.Mock).mockResolvedValue(mockData) - - const { result } = renderHook(() => useVeteranStatus(), { wrapper: createWrapper() }) - await waitFor(() => expect(result.current.isSuccess).toBe(true)) - - expect(result.current.data?.data.attributes.veteranStatus).toBe('not confirmed') - expect(result.current.data?.data.attributes.notConfirmedReason).toBe('NOT_TITLE_38') - expect(result.current.data?.data.message).toHaveLength(2) - }) - - it('returns "not confirmed" with reason "MORE_RESEARCH_REQUIRED"', async () => { - const mockData: VeteranVerificationStatusData = { - data: { - id: '', - type: 'veteran_status_confirmations', - attributes: { - veteranStatus: 'not confirmed', - notConfirmedReason: 'MORE_RESEARCH_REQUIRED', - }, - message: [ - 'We’re sorry. There’s a problem with your discharge status records.', - 'To fix the problem with your records...', - ], - }, - } - ;(get as jest.Mock).mockResolvedValue(mockData) - - const { result } = renderHook(() => useVeteranStatus(), { wrapper: createWrapper() }) - await waitFor(() => expect(result.current.isSuccess).toBe(true)) - - expect(result.current.data?.data.attributes.veteranStatus).toBe('not confirmed') - expect(result.current.data?.data.attributes.notConfirmedReason).toBe('MORE_RESEARCH_REQUIRED') - expect(result.current.data?.data.message).toHaveLength(2) - }) - - it('returns "not confirmed" with reason "PERSON_NOT_FOUND"', async () => { - const mockData: VeteranVerificationStatusData = { - data: { - id: '', - type: 'veteran_status_confirmations', - attributes: { - veteranStatus: 'not confirmed', - notConfirmedReason: 'PERSON_NOT_FOUND', - }, - message: [ - 'We’re sorry. There’s a problem with your discharge status records.', - 'To fix the problem with your records...', - ], - }, - } - ;(get as jest.Mock).mockResolvedValue(mockData) - - const { result } = renderHook(() => useVeteranStatus(), { wrapper: createWrapper() }) - await waitFor(() => expect(result.current.isSuccess).toBe(true)) - - expect(result.current.data?.data.attributes.veteranStatus).toBe('not confirmed') - expect(result.current.data?.data.attributes.notConfirmedReason).toBe('PERSON_NOT_FOUND') - expect(result.current.data?.data.message).toHaveLength(2) - }) - - it('returns "not confirmed" with reason "ERROR"', async () => { - const mockData: VeteranVerificationStatusData = { - data: { - id: '', - type: 'veteran_status_confirmations', - attributes: { - veteranStatus: 'not confirmed', - notConfirmedReason: 'ERROR', - }, - message: ["We're sorry. Something went wrong on our end. Try to view your Veteran status card later."], - }, - } - ;(get as jest.Mock).mockResolvedValue(mockData) - - const { result } = renderHook(() => useVeteranStatus(), { - wrapper: createWrapper(), - }) - - await waitFor(() => expect(result.current.isSuccess).toBe(true)) - - expect(result.current.isSuccess).toBe(true) - expect(result.current.data?.data.attributes.veteranStatus).toBe('not confirmed') - expect(result.current.data?.data.attributes.notConfirmedReason).toBe('ERROR') - expect(result.current.data?.data.message).toEqual([ - "We're sorry. Something went wrong on our end. Try to view your Veteran status card later.", - ]) - }) -}) diff --git a/VAMobile/src/api/veteranStatus/getVeteranStatus.tsx b/VAMobile/src/api/veteranStatus/getVeteranStatus.tsx index 0749fd8e29e..5c832a5b861 100644 --- a/VAMobile/src/api/veteranStatus/getVeteranStatus.tsx +++ b/VAMobile/src/api/veteranStatus/getVeteranStatus.tsx @@ -1,6 +1,6 @@ import { useQuery } from '@tanstack/react-query' -import { VeteranVerificationStatusData } from 'api/types' +import { VeteranVerificationStatusPayload } from 'api/types' import { ACTIVITY_STALE_TIME } from 'constants/common' import { get } from 'store/api' @@ -9,12 +9,10 @@ import { veteranStatusKeys } from './queryKeys' /** * Fetch veteran verification status */ -const getVeteranStatus = async (): Promise => { - const response = await get('/v0/vet_verification_status') +const getVeteranStatus = async (): Promise => { + const response = await get('/v0/vet_verification_status') if (response) { - return { - ...response, - } + return response } }