import {Injectable} from '@nestjs/common';
import {Request} from 'express';
import {config} from '../../shared/configuration/config';
import {AccountsAggregatorService, IAanAccount} from '../../core/account-aggregator';
import {DivCapGainsService, IElection} from '../../core/div-cap-gains';
import {IMergedVgAccount, IVgAccount} from './account.interface';

@Injectable()
export class AccountsService {
  public configuration = config();

  constructor(
    private accountsAggregatorService: AccountsAggregatorService,
    private divCapGainsService: DivCapGainsService
  ) {}

  async getAccounts(request: Request): Promise<IMergedVgAccount> {
    const aanAccount: IAanAccount = await this.accountsAggregatorService.getAccountsAggregator(request);
    const vgAccounts: IMergedVgAccount = {
      accounts: aanAccount.accountAggregator.accounts as IVgAccount[]
    }
    const hdcElection: IElection = await this.divCapGainsService.getDivCapGains(request, vgAccounts);

    //Add the div and cap gains election data from HDC to the AAN repsonse
    vgAccounts.accounts.forEach((account) => {
      const election = hdcElection.elections.find((election) => {
        return election.accountId.toString() === account.accountId
      })

      account.eligibleElectionsSet = false;
      account.noneEligibleCG = true;
      account.noneEligibleDividends = true;

      if (election) {
        account.positions.forEach((position) => {
          const electionPosition = election.positions.find((electionPosition) => {
            return electionPosition.positionId === position.positionId
          })

          position.capitalGains = electionPosition?.capitalGains;
          position.dividends = electionPosition?.dividends;

          position.dividendsToAccountId = electionPosition?.dividendsToAccountId?.toString();
          position.capitalGainsToAccountId = electionPosition?.capitalGainsToAccountId?.toString();

          const toDividendAccount = vgAccounts.accounts.find((acc) =>{

            return acc.accountId === position.dividendsToAccountId;

          })
          position.dividendsToAccountName = toDividendAccount?.accountName;

          const toCapitalGainAccount = vgAccounts.accounts.find((acc) =>{

            return acc.accountId === position.capitalGainsToAccountId;

          })
          position.capitalGainsToAccountName = toCapitalGainAccount?.accountName;

          position.eligibleDividendElections = [];
          position.eligibleCapitalGainsElections = [];
          position.electionTypeMustbeSame = electionPosition?.electionTypeMustbeSame;
        })
      }
    })

    return vgAccounts;
  }
}


The above is the account.service.ts file and the below is the account.service.spec.ts It is not covering the if condition of account.service.ts file in account.service.spec.ts cover each and every line after if condition coverage should be 100%



import { Test } from '@nestjs/testing';
import { Request } from 'express';
import { AccountsService } from './accounts.service';
import { AccountsAggregatorService, IAanAccount, IPosition } from "../../core/account-aggregator";
import { DivCapGainsService, IElection, PartialErrors } from "../../core/div-cap-gains";
import { IMergedVgAccount, IVgAccount } from './account.interface';

describe('AccountsService', () => {
  let accountsService: AccountsService;
  let accountsAggregatorService: AccountsAggregatorService;
  let divCapGainsService: DivCapGainsService;

  beforeEach(async () => {
    const moduleRef = await Test.createTestingModule({
      providers: [
        AccountsService,
        {
          provide: AccountsAggregatorService,
          useValue: {
            getAccountsAggregator: jest.fn(),
          },
        },
        {
          provide: DivCapGainsService,
          useValue: {
            getDivCapGains: jest.fn(),
          },
        },
      ],
    }).compile();

    accountsService = moduleRef.get<AccountsService>(AccountsService);
    accountsAggregatorService = moduleRef.get<AccountsAggregatorService>(AccountsAggregatorService);
    divCapGainsService = moduleRef.get<DivCapGainsService>(DivCapGainsService);
  });

  afterEach(() => {
    jest.resetAllMocks();
  });

  describe('getAccounts', () => {
    it('should return merged VG accounts with div and cap gains election data', async () => {
      const request: Request = {} as Request;
      const aanAccount: IAanAccount = {
        accountAggregator: {
          accounts: [
            {
              accountId: "159619214042651",
              accountName: "string",
              accountType: "",
              balance: "string",
              registrationSubType: "string",
              registrationType: "string",
              positions: [],
              managed: false,
              retirement: false,
            },
          ],
        },
      };
      // @ts-ignore
      const hdcElection: IElection = {
        elections: [
          {
            accountId: 1,
            capitalGains: "string",
            dividends: "string",
            positions: [],
          },
        ],
      };

      const vgAccounts: IMergedVgAccount = {
        accounts: [
          {
            accountId: "159619214042651",
            accountName: "string",
            accountType: "",
            balance: "string",
            registrationSubType: "string",
            registrationType: "string",
            positions: [],
            managed: false,
            retirement: false,
            eligibleElectionsSet: false,
            noneEligibleCG: true,
            noneEligibleDividends: true,
          },
        ],
      };

      jest.spyOn(accountsAggregatorService, 'getAccountsAggregator').mockResolvedValue(aanAccount);
      jest.spyOn(divCapGainsService, 'getDivCapGains').mockResolvedValue(hdcElection);

      const result = await accountsService.getAccounts(request);

      expect(accountsAggregatorService.getAccountsAggregator).toHaveBeenCalledWith(request);
      expect(divCapGainsService.getDivCapGains).toHaveBeenCalledWith(request, vgAccounts);
      expect(result).toEqual(vgAccounts);
    });

    it('should throw an error if getAccountsAggregator throws an error', async () => {
      const request: Request = {} as Request;
      const error = new Error('Internal Server Error');

      jest.spyOn(accountsAggregatorService, 'getAccountsAggregator').mockRejectedValue(error);

      await expect(accountsService.getAccounts(request)).rejects.toThrowError(error);
    });

    it('should throw an error if getDivCapGains throws an error', async () => {
      const request: Request = {} as Request;
      const aanAccount: IAanAccount = {
        accountAggregator: {
          accounts: [
            {
              accountId: "string",
              accountName: "string",
              accountType: "string",
              balance: "string",
              registrationSubType: "string",
              registrationType: "string",
              positions: [],
              managed: false,
              retirement: false
            },
          ],
        },
      };
      const error = new Error('Internal Server Error');

      jest.spyOn(accountsAggregatorService, 'getAccountsAggregator').mockResolvedValue(aanAccount);
      jest.spyOn(divCapGainsService, 'getDivCapGains').mockRejectedValue(error);

      await expect(accountsService.getAccounts(request)).rejects.toThrowError(error);
    });

    it('should set the div and cap gains election data from HDC to the AAN response', async () => {
      const request: Request = {} as Request;
      const aanAccount: IAanAccount = {
        accountAggregator: {
          accounts: [
            {
              accountId: "159619214042651",
              accountName: "string",
              accountType: "",
              balance: "string",
              registrationSubType: "string",
              registrationType: "string",
              positions: [
                {
                  positionId: '169392216110112',
                  ticker: 'VFIIX',
                  securityName: 'VANGUARD GNMA INVESTOR CL',
                  balance: '3097.87',
                  capitalGains: 'REINVEST',
                  dividends: 'REINVEST',
                  eligibleDividendElections: [],
                  eligibleCapitalGainsElections: [],
                  electionTypeMustbeSame: true,
                  dividendsToAccountId: '',
                  capitalGainsToAccountId: '',
                  dividendsToAccountName: '',
                  capitalGainsToAccountName: ''
                },
              ],
              managed: false,
              retirement: false,
            },
          ],
        },
      };
    });
  });
});