Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ jobs:
- run: |
touch .env
echo UNIT_TOKEN=${{ secrets.UNIT_TOKEN }} >> .env
echo UNIT_THREAD_TOKEN=${{ secrets.UNIT_THREAD_TOKEN }} >> .env
echo UNIT_API_URL=${{ secrets.UNIT_API_URL }} >> .env
echo TEST_COUNTERPARTY_PLAID_TOKEN=${{ secrets.TEST_COUNTERPARTY_PLAID_TOKEN }} >> .env
- run: npm run test
22 changes: 18 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@unit-finance/unit-node-sdk",
"version": "1.3.17",
"version": "1.4.0",
"description": "",
"main": "dist/unit.js",
"types": "dist/unit.d.ts",
Expand Down
23 changes: 22 additions & 1 deletion resources/application.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Application, BeneficialOwner, BeneficialOwnerDTO, ApplicationDocument, CreateApplicationRequest, DownloadDocumentRequest, PatchApplicationRequest, UploadDocumentRequest, VerifyDocumentRequest, CancelApplicationRequest, PatchBusinessApplicationBeneficialOwner, ApplicationStatus } from "../types/application"
import { Application, BeneficialOwner, BeneficialOwnerDTO, ApplicationDocument, CreateApplicationRequest, DownloadDocumentRequest, PatchApplicationRequest, UploadDocumentRequest, VerifyDocumentRequest, CancelApplicationRequest, PatchBusinessApplicationBeneficialOwner, ApplicationStatus, ApplicationMissingFields } from "../types/application"
import { CreateThreadApplicationRequest, UpdateThreadApplicationRequest, ThreadApplication, BeneficialOwnerThreadApplication, UpdateBusinessBeneficialOwnerThreadApplicationRequest, UpgradeToThreadApplicationRequest } from "../types/threadApplication"
import { UnitResponse, Include, UnitConfig, BaseListParams, Tags, Sort } from "../types/common"
import { BaseResource } from "./baseResource"

Expand Down Expand Up @@ -33,6 +34,22 @@ export class Applications extends BaseResource {
return this.httpPost<UnitResponse<Application> & Include<ApplicationDocument[] | BeneficialOwner[]>>("", { data: request })
}

public async createThreadApplication(request: CreateThreadApplicationRequest): Promise<UnitResponse<ThreadApplication> & Include<ApplicationDocument[] | BeneficialOwner[]>> {
return this.httpPost<UnitResponse<ThreadApplication> & Include<ApplicationDocument[] | BeneficialOwner[]>>("", { data: request })
}

public async updateThreadApplication(request: Exclude<UpdateThreadApplicationRequest, UpdateBusinessBeneficialOwnerThreadApplicationRequest>): Promise<UnitResponse<ThreadApplication>> {
return this.httpPatch<UnitResponse<ThreadApplication>>(`/${request.applicationId}`, { data: request.data })
}

public async updateThreadApplicationBeneficialOwner(request: UpdateBusinessBeneficialOwnerThreadApplicationRequest): Promise<UnitResponse<BeneficialOwnerThreadApplication>> {
return this.httpPatchFullPath<UnitResponse<BeneficialOwnerThreadApplication>>(`${this.basePath}/beneficial-owner/${request.beneficialOwnerId}`, { data: request.data })
}

public async upgradeToThreadApplication(request: UpgradeToThreadApplicationRequest): Promise<UnitResponse<ThreadApplication>> {
return this.httpPatch<UnitResponse<ThreadApplication>>(`/${request.applicationId}`, { data: request.data })
}

public async upload(request: UploadDocumentRequest) : Promise<UnitResponse<ApplicationDocument>> {

let path = `/${request.applicationId}/documents/${request.documentId}`
Expand Down Expand Up @@ -102,6 +119,10 @@ export class Applications extends BaseResource {
public async updateBeneficialOwner(request: PatchBusinessApplicationBeneficialOwner): Promise<UnitResponse<BeneficialOwnerDTO>> {
return this.httpPatchFullPath<UnitResponse<BeneficialOwnerDTO>>(`${this.basePath}/beneficial-owner/${request.beneficialOwnerId}`, {data: request.data})
}

public async getMissingFields(applicationId: string): Promise<UnitResponse<ApplicationMissingFields>> {
return this.httpGet<UnitResponse<ApplicationMissingFields>>(`/${applicationId}/missing-fields`)
}
}

export interface ApplicationListParams extends BaseListParams {
Expand Down
71 changes: 71 additions & 0 deletions tests/applications.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { createAddress, createFullName, createPhone } from "../helpers"
import {
Agent,
ApplicationMissingFields,
BusinessApplication,
CancelApplicationRequest,
CreateBusinessApplicationRequest,
CreateIndividualApplicationRequest,
CreateSoleProprietorApplicationRequest,
IndividualApplication,
IndividualApplicationMissingFields,
BusinessApplicationMissingFields,
PatchApplicationRequest,
PatchBusinessApplicationBeneficialOwner,
RelationshipsArrayData,
Expand Down Expand Up @@ -943,6 +946,74 @@ describe("Create Document", () => {
}, 90000)
})

describe("Get Missing Fields", () => {
test("Get Missing Fields for Individual Application", async () => {
const createRes = await createIndividualApplication(unit)
const res = await unit.applications.getMissingFields(createRes.data.id)

expect(res.data.type).toBe("individualApplicationMissingFields")
expect(res.data.attributes.missingFields).toBeInstanceOf(Array)
})

test("Get Missing Fields for Business Application", async () => {
const createRes = await createBusinessApplication(unit)
const res = await unit.applications.getMissingFields(createRes.data.id)

expect(res.data.type).toBe("businessApplicationMissingFields")
expect(res.data.attributes.missingFields).toBeInstanceOf(Array)
})

test("Simulate IndividualApplicationMissingFields response from API", () => {
const missingFields: IndividualApplicationMissingFields = {
type: "individualApplicationMissingFields",
attributes: {
missingFields: [
{
fieldName: "usNexus",
description: "usNexus is required"
},
{
fieldName: "transactionVolume",
description: "transactionVolume is required. transactionVolumeDescription is required when transaction volume is one of the following: Between30KAnd60K, GreaterThan60K"
}
]
}
}

expect(missingFields.type).toBe("individualApplicationMissingFields")
expect(missingFields.attributes.missingFields).toHaveLength(2)
expect(missingFields.attributes.missingFields[0].fieldName).toBe("usNexus")
})

test("Simulate BusinessApplicationMissingFields response from API", () => {
const missingFields: BusinessApplicationMissingFields = {
type: "businessApplicationMissingFields",
attributes: {
missingFields: [
{
fieldName: "sourceOfFunds",
description: "sourceOfFunds is required"
}
]
}
}

expect(missingFields.type).toBe("businessApplicationMissingFields")
expect(missingFields.attributes.missingFields).toHaveLength(1)
})

test("Simulate empty missingFields array", () => {
const missingFields: ApplicationMissingFields = {
type: "individualApplicationMissingFields",
attributes: {
missingFields: []
}
}

expect(missingFields.attributes.missingFields).toHaveLength(0)
})
})

describe("Create and Close Application", () => {
test("Create and Close Individual Application", async () => {

Expand Down
Loading