From 1dc77fb3de697df7c3e7e6495eb4c039bab1e762 Mon Sep 17 00:00:00 2001 From: hudson-newey Date: Tue, 17 Oct 2023 10:19:08 +1000 Subject: [PATCH] Uncommented not working test --- src/app/app.menus.ts | 8 ++ src/app/components/projects/projects.menus.ts | 5 +- .../regions/pages/new/new.component.spec.ts | 131 +++++++++--------- src/app/components/reports/reports.menu.ts | 6 +- .../typeahead-input.component.html | 2 +- .../typeahead-input.component.ts | 4 +- 6 files changed, 84 insertions(+), 72 deletions(-) diff --git a/src/app/app.menus.ts b/src/app/app.menus.ts index e2a7e49c5..0577268ce 100644 --- a/src/app/app.menus.ts +++ b/src/app/app.menus.ts @@ -47,3 +47,11 @@ export const isProjectEditorPredicate = ( */ export const isAdminPredicate = (user: User): boolean => isLoggedInPredicate(user) && user.isAdmin; + +/** + * Returns true only if the user is an admin and can see work in progress items + * This predicate differs from the `isAdminPredicate` for semantic reasons + * + * @param user User session data. This will be used to check if the user is an admin + */ +export const isWorkInProgressPredicate = isAdminPredicate; diff --git a/src/app/components/projects/projects.menus.ts b/src/app/components/projects/projects.menus.ts index 56d127f46..16072a7da 100644 --- a/src/app/components/projects/projects.menus.ts +++ b/src/app/components/projects/projects.menus.ts @@ -9,6 +9,7 @@ import { isAdminPredicate, isLoggedInPredicate, isProjectEditorPredicate, + isWorkInProgressPredicate, } from "src/app/app.menus"; import { CommonRouteTitles } from "src/app/stringConstants"; import { @@ -111,8 +112,8 @@ export const uploadAnnotationsProjectMenuItem = menuRoute({ icon: ["fas", "file-import"], label: "Batch Upload Annotations", parent: projectMenuItem, - // TODO Change to isProjectEditorPredicate - predicate: isAdminPredicate, + // TODO: Once functionality is implemented, this should be changed to isProjectEditorPredicate + predicate: isWorkInProgressPredicate, route: projectMenuItem.route.add("batch-annotations"), tooltip: () => "(UNDER DEVELOPMENT) Upload multiple annotations to this project", diff --git a/src/app/components/regions/pages/new/new.component.spec.ts b/src/app/components/regions/pages/new/new.component.spec.ts index 7cb10ca23..01bee3c9e 100644 --- a/src/app/components/regions/pages/new/new.component.spec.ts +++ b/src/app/components/regions/pages/new/new.component.spec.ts @@ -128,68 +128,69 @@ describe("RegionsNewComponent", () => { }); }); -// xdescribe("routing and resolvers", () => { -// const nestedRoutes = regionsRoute.compileRoutes(getRouteConfigForPage); -// const shallowRoutes = shallowRegionsRoute.compileRoutes( -// getRouteConfigForPage -// ); - -// let project: Project; -// let defaultProject: Project; - -// beforeEach(() => { -// // create 2 stub projects so we can clearly assert different ones are loaded -// // on different routes -// project = new Project(generateProject()); -// defaultProject = new Project(generateProject()); - -// // stub both api methods that the two resolvers use -// const api = createSpyObject(ProjectsService); -// api.show.and.callFake(() => of(project)); -// api.filter.and.callFake(() => of([defaultProject])); - -// // set up ngMocks according to https://ng-mocks.sudo.eu/guides/routing-resolver -// const builder = MockBuilder([ -// NewComponent, -// RouterTestingModule.withRoutes([...nestedRoutes, ...shallowRoutes]), -// ]) -// .keep(MockBawApiModule, { export: true }) -// .provide({ provide: ProjectsService, useValue: api }); - -// // augment builder with out app level module imports -// return addStandardFormImportsToMockBuilder(builder); -// }); - -// function setup(path) { -// // boiler plate adapted from https://ng-mocks.sudo.eu/guides/route -// const fixture = MockRender(RouterOutlet); -// const router = fixture.point.injector.get(Router); -// const location = fixture.point.injector.get(Location); - -// location.go(path); - -// router.initialNavigation(); -// tick(); - -// expect(location.path()).toBe(path); - -// const component = ngMocks.find(fixture, NewComponent); -// fixture.detectChanges(); - -// return component; -// } - -// it("should resolve with project id in the the route", fakeAsync(() => { -// const path = `/projects/${project.id}/regions/new`; -// const component = setup(path); - -// expect(component.componentInstance.project).toBe(project); -// })); - -// it("should resolve the default project for the shallow route", fakeAsync(() => { -// const path = "/regions/new"; -// const component = setup(path); - -// expect(component.componentInstance.project).toBe(defaultProject); -// })); -// }); +describe("routing and resolvers", () => { + const nestedRoutes = regionsRoute.compileRoutes(getRouteConfigForPage); + const shallowRoutes = shallowRegionsRoute.compileRoutes( + getRouteConfigForPage + ); + + let project: Project; + let defaultProject: Project; + + beforeEach(() => { + // create 2 stub projects so we can clearly assert different ones are loaded + // on different routes + project = new Project(generateProject()); + defaultProject = new Project(generateProject()); + + // stub both api methods that the two resolvers use + const api = createSpyObject(ProjectsService); + api.show.and.callFake(() => of(project)); + api.filter.and.callFake(() => of([defaultProject])); + + // set up ngMocks according to https://ng-mocks.sudo.eu/guides/routing-resolver + const builder = MockBuilder([ + NewComponent, + RouterTestingModule.withRoutes([...nestedRoutes, ...shallowRoutes]), + ]) + .keep(MockBawApiModule, { export: true }) + .provide({ provide: ProjectsService, useValue: api }); + + // augment builder with out app level module imports + return addStandardFormImportsToMockBuilder(builder); + }); + + function setup(path) { + // boiler plate adapted from https://ng-mocks.sudo.eu/guides/route + const fixture = MockRender(RouterOutlet); + const router = fixture.point.injector.get(Router); + const location = fixture.point.injector.get(Location); + + location.go(path); + + router.initialNavigation(); + tick(); + + expect(location.path()).toBe(path); + + fixture.detectChanges(); + const component = ngMocks.find(fixture, NewComponent); + fixture.detectChanges(); + + return component; + } + + fit("should resolve with project id in the the route", fakeAsync(() => { + const path = `/projects/${project.id}/regions/new`; + const component = setup(path); + + expect(component.componentInstance.project).toBe(project); + })); + + it("should resolve the default project for the shallow route", fakeAsync(() => { + const path = "/regions/new"; + const component = setup(path); + + expect(component.componentInstance.project).toBe(defaultProject); + })); +}); diff --git a/src/app/components/reports/reports.menu.ts b/src/app/components/reports/reports.menu.ts index 73f70d0bb..27c38a8d0 100644 --- a/src/app/components/reports/reports.menu.ts +++ b/src/app/components/reports/reports.menu.ts @@ -3,7 +3,7 @@ import { projectMenuItem } from "@components/projects/projects.menus"; import { regionMenuItem } from "@components/regions/regions.menus"; import { siteMenuItem } from "@components/sites/sites.menus"; import { pointMenuItem } from "@components/sites/points.menus"; -import { isAdminPredicate } from "src/app/app.menus"; +import { isWorkInProgressPredicate } from "src/app/app.menus"; import { ReportRoute, newEventReportRoute, @@ -37,7 +37,7 @@ function makeViewEventReportMenuItem( label: "Event Summary Report", tooltip: () => "Event summary report", route: eventReportRoute[subRoute], - predicate: isAdminPredicate, + predicate: isWorkInProgressPredicate, parent, }); } @@ -51,7 +51,7 @@ function makeNewEventReportMenuItem( label: "New Event Summary Report", tooltip: () => "New event summary report", route: newEventReportRoute[subRoute], - predicate: isAdminPredicate, + predicate: isWorkInProgressPredicate, parent, }); } diff --git a/src/app/components/shared/typeahead-input/typeahead-input.component.html b/src/app/components/shared/typeahead-input/typeahead-input.component.html index 28509931b..40d6f11aa 100644 --- a/src/app/components/shared/typeahead-input/typeahead-input.component.html +++ b/src/app/components/shared/typeahead-input/typeahead-input.component.html @@ -19,7 +19,7 @@ diff --git a/src/app/components/shared/typeahead-input/typeahead-input.component.ts b/src/app/components/shared/typeahead-input/typeahead-input.component.ts index 93b13b0ae..87d7551a7 100644 --- a/src/app/components/shared/typeahead-input/typeahead-input.component.ts +++ b/src/app/components/shared/typeahead-input/typeahead-input.component.ts @@ -35,7 +35,7 @@ export class TypeaheadInputComponent { */ @Input() public searchCallback: TypeaheadSearchCallback; /** Describes how to convert an object model into a human readable form for use in the pills and typeahead dropdown */ - @Input() public resultTemplate: TemplateRef; + @Input() public resultTemplate: TemplateRef; /** Whether the typeahead input should allow multiple inputs in pill form */ @Input() public multipleInputs = true; /** Text to show above the input field. Usually a one 1-2 word description. */ @@ -65,6 +65,8 @@ export class TypeaheadInputComponent { ); }; + public templateFormatter = (item: object): string => item.toString(); + public onItemSelected($event: NgbTypeaheadSelectItemEvent): void { $event.preventDefault(); const selectedItem: object = $event.item;