Skip to content

Commit

Permalink
fix: add map layer geocoding checks (#3825)
Browse files Browse the repository at this point in the history
* fix: add map layer geocoding checks

* fix: review comment fix
  • Loading branch information
ludtkemorgan authored Jan 24, 2024
1 parent aa8e3a6 commit 6fe5374
Show file tree
Hide file tree
Showing 8 changed files with 605 additions and 33 deletions.
1 change: 1 addition & 0 deletions backend/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"@turf/buffer": "6.5.0",
"@turf/helpers": "6.5.0",
"@turf/boolean-point-in-polygon": "6.5.0",
"@turf/points-within-polygon": "6.5.0",
"@types/cache-manager": "^3.4.0",
"async-retry": "^1.3.1",
"axios": "0.21.3",
Expand Down
3 changes: 2 additions & 1 deletion backend/core/src/applications/applications.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { SharedModule } from "../shared/shared.module"
import { ListingsModule } from "../listings/listings.module"
import { Address } from "../shared/entities/address.entity"
import { Applicant } from "./entities/applicant.entity"
import { MapLayer } from "../map-layers/entities/map-layer.entity"
import { ApplicationsSubmissionController } from "./applications-submission.controller"
import { TranslationsModule } from "../translations/translations.module"
import { Listing } from "../listings/entities/listing.entity"
Expand All @@ -20,7 +21,7 @@ import { GeocodingService } from "./services/geocoding.service"

@Module({
imports: [
TypeOrmModule.forFeature([Application, Applicant, Address, Listing]),
TypeOrmModule.forFeature([Application, Applicant, Address, Listing, MapLayer]),
AuthModule,
ActivityLogModule,
SharedModule,
Expand Down
163 changes: 152 additions & 11 deletions backend/core/src/applications/services/geocoding.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { Application } from "../entities/application.entity"
import { ValidationMethod } from "../../multiselect-question/types/validation-method-enum"
import { Listing } from "../../listings/entities/listing.entity"
import { InputType } from "../../shared/types/input-type"
import { MapLayer } from "../../map-layers/entities/map-layer.entity"
import { FeatureCollection } from "@turf/helpers"

describe("GeocodingService", () => {
let service: GeocodingService
Expand All @@ -15,7 +17,7 @@ describe("GeocodingService", () => {
update: applicationRepoUpdate,
}
const date = new Date()
const listingAddress: Address = {
const address: Address = {
id: "id",
createdAt: date,
updatedAt: date,
Expand All @@ -28,6 +30,47 @@ describe("GeocodingService", () => {
latitude: 38.8977,
longitude: -77.0365,
}
const featureCollection: FeatureCollection = {
type: "FeatureCollection",
features: [
{
type: "Feature",
properties: {},
geometry: {
coordinates: [
[
[
[-77.0392589333301, 38.79186072967565],
[-76.90981025809415, 38.89293952026222],
[-77.04122027689426, 38.996161202682146],
[-77.12000091005532, 38.93465307055658],
[-77.10561772391833, 38.91990351952725],
[-77.09123453778136, 38.90565966392609],
[-77.06802530560486, 38.9015894658674],
[-77.06181438431805, 38.889377471720564],
[-77.03697069917165, 38.870801038935525],
[-77.03043288729134, 38.850437727576235],
[-77.03435557441966, 38.80816525459605],
[-77.0392589333301, 38.79186072967565],
],
],
],
type: "Polygon",
},
},
],
}
const mockMapLayerRepo = {
createQueryBuilder: jest.fn(),
findBy: jest.fn().mockResolvedValue([
{
id: "mapLayerId",
name: "map layer",
jurisdictionId: "1",
featureCollection: featureCollection,
},
]),
}

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
Expand All @@ -37,6 +80,10 @@ describe("GeocodingService", () => {
provide: getRepositoryToken(Application),
useValue: mockApplicationRepo,
},
{
provide: getRepositoryToken(MapLayer),
useValue: mockMapLayerRepo,
},
],
}).compile()

Expand All @@ -48,56 +95,81 @@ describe("GeocodingService", () => {
expect(
service.verifyRadius(
{
...listingAddress,
...address,
latitude: null,
longitude: null,
},
5,
listingAddress
address
)
).toBe("unknown")
})
it("should return 'true' if within radius", () => {
expect(
service.verifyRadius(
{
...listingAddress,
...address,
latitude: 38.89485,
longitude: -77.04251,
},
5,
listingAddress
address
)
).toBe("true")
})
it("should return 'false' if not within radius", () => {
expect(
service.verifyRadius(
{
...listingAddress,
...address,
latitude: 39.284205,
longitude: -76.621698,
},
5,
listingAddress
address
)
).toBe("false")
})
it("should return 'true' if same lat long", () => {
expect(
service.verifyRadius(
{
...listingAddress,
...address,
},
5,
listingAddress
address
)
).toBe("true")
})
})
describe("verifyLayers", () => {
it("should return 'unknown' if no lat/long", () => {
expect(
service.verifyLayers(
{
...address,
latitude: null,
longitude: null,
},
featureCollection
)
).toBe("unknown")
})
it("should return 'true' if address is within layer", () => {
expect(service.verifyLayers(address, featureCollection)).toBe("true")
})
it("should return 'false' if address is within layer", () => {
expect(
service.verifyLayers(
{ ...address, latitude: 39.284205, longitude: -76.621698 },
featureCollection
)
).toBe("false")
})
})
describe("validateRadiusPreferences", () => {
const listing = {
buildingAddress: listingAddress,
buildingAddress: address,
listingMultiselectQuestions: [
{
multiselectQuestion: {
Expand All @@ -113,7 +185,7 @@ describe("GeocodingService", () => {
},
],
}
const preferenceAddress = { ...listingAddress, latitude: 38.89485, longitude: -77.04251 }
const preferenceAddress = { ...address, latitude: 38.89485, longitude: -77.04251 }
const application = {
id: "applicationId",
preferences: [
Expand Down Expand Up @@ -164,4 +236,73 @@ describe("GeocodingService", () => {
)
})
})
describe("validateGeoLayerPreferences", () => {
const listing = {
buildingAddress: address,
listingMultiselectQuestions: [
{
multiselectQuestion: {
options: [
{
text: "Geocoding option by map",
collectAddress: true,
mapLayerId: "mapLayerId",
validationMethod: ValidationMethod.map,
},
],
},
},
],
}
const preferenceAddress = { ...address, latitude: 38.89485, longitude: -77.04251 }
const application = {
id: "applicationId",
preferences: [
{
key: "Geocoding preference",
options: [
{
key: "Geocoding option by map",
checked: true,
extraData: [
{
type: InputType.address,
value: preferenceAddress,
},
],
},
],
},
],
}
it("should save the validated value as extraData for map layer", async () => {
await service.validateGeoLayerPreferences(
(application as unknown) as Application,
listing as Listing
)
expect(applicationRepoUpdate).toBeCalledWith(
{ id: "applicationId" },
{
preferences: expect.arrayContaining([
expect.objectContaining({
key: "Geocoding preference",
options: [
{
checked: true,
extraData: [
{
type: "address",
value: preferenceAddress,
},
{ key: "geocodingVerified", type: "text", value: "true" },
],
key: "Geocoding option by map",
},
],
}),
]),
}
)
})
})
})
Loading

0 comments on commit 6fe5374

Please sign in to comment.