Skip to content

Commit

Permalink
Allow users to remove location from site/points
Browse files Browse the repository at this point in the history
Fixes: #2040
  • Loading branch information
hudson-newey committed Dec 20, 2023
1 parent aaf873e commit 7b36191
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 16 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ This website can be customised through the environment file located at `./src/as
| `settings.links` | This is a list of external links used throughout the website. Check the template for the list of modifiable links |
| `settings.customMenu` | This is a list of custom menu items which changes the contents of the header with instance specific links. Check the template for examples |

To use the embedded Google Maps in both development and production, it is required that the `keys.googleMaps` property is set.
If you have not set this value the embedded maps will not work, and an error will be thrown in the console with the message "Google Maps JavaScript API error: InvalidKeyMapError".

### Testing

#### Unit tests
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

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

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"@angular/compiler": "16.2.9",
"@angular/core": "16.2.9",
"@angular/forms": "16.2.9",
"@angular/google-maps": "16.2.8",
"@angular/google-maps": "16.2.12",
"@angular/localize": "16.2.9",
"@angular/platform-browser": "16.2.9",
"@angular/platform-browser-dynamic": "16.2.9",
Expand Down Expand Up @@ -136,4 +136,4 @@
"@angular/core": "14.0.6"
}
}
}
}
53 changes: 45 additions & 8 deletions src/app/components/shared/formly/location-input.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,19 @@ describe("FormlyLocationInput", () => {

beforeAll(async () => await embedGoogleMaps());

const getLatitudeInput = () => spectator.query<HTMLInputElement>("#latitude");
beforeEach(() => setup());

const getLatitudeInput = () =>
spectator.query<HTMLInputElement>("#latitude");
const getLongitudeInput = () =>
spectator.query<HTMLInputElement>("#longitude");
const getErrorElements = () =>
spectator.queryAll<HTMLDivElement>(".invalid-feedback");

function updateMarkerThroughInput(longitude: number, latitude: number) {
function updateMarkerThroughInput(
longitude: number | string,
latitude: number | string
) {
const latitudeInput = getLatitudeInput();
const longitudeInput = getLongitudeInput();

Expand Down Expand Up @@ -100,12 +107,10 @@ describe("FormlyLocationInput", () => {
}

it("should create", () => {
setup();
expect(spectator.component).toBeInstanceOf(LocationInputComponent);
});

it("should display the position of the marker in input boxes", fakeAsync(() => {
setup();
const defaultLongitudeValue = modelData.longitude();
const defaultLatitudeValue = modelData.latitude();

Expand All @@ -118,7 +123,6 @@ describe("FormlyLocationInput", () => {
}));

it("should update the marker model if the location is updated through the input field/form", () => {
setup();
const map = spectator.query(MapComponent);
const defaultLongitudeValue = modelData.longitude();
const defaultLatitudeValue = modelData.latitude();
Expand All @@ -137,7 +141,6 @@ describe("FormlyLocationInput", () => {
});

it("should update the marker model if the marker is dragged", () => {
setup();
const map = spectator.query(MapComponent);
const defaultLongitudeValue = modelData.longitude();
const defaultLatitudeValue = modelData.latitude();
Expand All @@ -151,13 +154,13 @@ describe("FormlyLocationInput", () => {
const updatedLongitude = modelData.longitude();
const updatedLatitude = modelData.latitude();
// simulate dragging and dropping the marker by sending a drag event to the map
const newPosition = {
const newPosition: google.maps.LatLng = {
lng: () => updatedLongitude,
lat: () => updatedLatitude,
equals: () => null,
toJSON: () => null,
toUrlValue: () => null,
} as google.maps.LatLng;
};

map.newLocation.emit({
domEvent: new Event("mapDragend"),
Expand All @@ -173,4 +176,38 @@ describe("FormlyLocationInput", () => {
);
assertMapModelCoordinates(map, updatedLongitude, updatedLatitude);
});

it("should emit 'null' if both the input fields are empty", () => {
const expectedValue = { longitude: null, latitude: null };
updateMarkerThroughInput("", "");

expect(spectator.component.formControl.value).toEqual(expectedValue);
});

it("should display an error if there is a longitude but no latitude", () => {
const expectedError =
"Both latitude and longitude must be set or left empty";
const longitude = modelData.longitude();

updateMarkerThroughInput(longitude, "");

expect(getErrorElements()).toEqual(
jasmine.arrayContaining([
jasmine.objectContaining({ innerText: expectedError }),
])
);
});

it("should display an error if there is a latitude but no longitude", () => {
const expectedError = "Both latitude and longitude must be set or left empty";
const latitude = modelData.latitude();

updateMarkerThroughInput("", latitude);

expect(getErrorElements()).toEqual(
jasmine.arrayContaining([
jasmine.objectContaining({ innerText: expectedError }),
])
);
});
});
4 changes: 4 additions & 0 deletions src/app/components/shared/formly/location-input.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,12 @@ export class LocationInputComponent extends FieldType implements OnInit {
latitude: this.latitude,
longitude: this.longitude,
});

this.model["latitude"] = this.latitude;
this.model["longitude"] = this.longitude;
this.model["customLatitude"] = this.latitude;
this.model["customLongitude"] = this.longitude;

this.setMarker(this.latitude, this.longitude);
}

Expand Down
33 changes: 31 additions & 2 deletions src/app/components/sites/pages/edit/edit.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import { assertPageInfo } from "@test/helpers/pageRoute";
import { testFormImports } from "@test/helpers/testbed";
import { ToastrService } from "ngx-toastr";
import { BehaviorSubject, Subject } from "rxjs";
import { MockComponent } from "ng-mocks";
import { MapComponent } from "@shared/map/map.component";
import pointSchema from "../../point.base.json";
import siteSchema from "../../site.base.json";
import { SiteEditComponent } from "./edit.component";
Expand All @@ -32,7 +34,7 @@ describe("SiteEditComponent", () => {
const createComponent = createRoutingFactory({
component: SiteEditComponent,
imports: [...testFormImports, MockBawApiModule],
declarations: [FormComponent],
declarations: [FormComponent, MockComponent(MapComponent)],
mocks: [ToastrService],
stubsEnabled: true,
});
Expand Down Expand Up @@ -86,7 +88,7 @@ describe("SiteEditComponent", () => {
let defaultRegion: Region;
let defaultSite: Site;

assertPageInfo(SiteEditComponent, "Edit")
assertPageInfo(SiteEditComponent, "Edit");

function setup(
project: Errorable<Project>,
Expand Down Expand Up @@ -117,6 +119,11 @@ describe("SiteEditComponent", () => {
spec.detectChanges();
}

const longitudeInputElement = (): HTMLInputElement =>
spec.query<HTMLInputElement>("#longitude");
const latitudeInputElement = (): HTMLInputElement =>
spec.query<HTMLInputElement>("#latitude");

[true, false].forEach((withRegion) => {
describe(withRegion ? "withRegion" : "withoutRegion", () => {
beforeEach(() => {
Expand Down Expand Up @@ -171,6 +178,28 @@ describe("SiteEditComponent", () => {
site.getViewUrl(defaultProject)
);
});

it("should handle being modified to have a null location", () => {
setup(defaultProject, defaultSite, defaultRegion);
api.update.and.callFake(() => new Subject());

// by setting longitude and latitude to empty strings, we should see the model set location properties to null
const longitudeInput = longitudeInputElement();
const latitudeInput = latitudeInputElement();

spec.typeInElement("", longitudeInput);
spec.typeInElement("", latitudeInput);
spec.detectChanges();

spec.component.submit(spec.component.model);
expect(api.update).toHaveBeenCalledWith(
jasmine.objectContaining({
longitude: null,
latitude: null,
}),
defaultProject
);
});
});
});
});
Expand Down

0 comments on commit 7b36191

Please sign in to comment.