Skip to content

Commit

Permalink
fix: correctly load records for a specific day in any timezone (#2034)
Browse files Browse the repository at this point in the history
and tests in two timezones +  adjusted tests to pass in any timezone
  • Loading branch information
TheSlimvReal authored Oct 18, 2023
1 parent 616fc9d commit 6444f44
Show file tree
Hide file tree
Showing 14 changed files with 116 additions and 51 deletions.
13 changes: 13 additions & 0 deletions .github/workflows/pull-request-update.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,19 @@ jobs:
BUILD=${{ false }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Run tests with timezone
uses: docker/build-push-action@v3
with:
context: ./
file: ./build/Dockerfile
builder: ${{ steps.buildx.outputs.name }}
target: builder
build-args: |
RUN_TESTS=${{ true }}
TZ=America/Detroit
BUILD=${{ false }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy-prod-image:
runs-on: ubuntu-latest
steps:
Expand Down
10 changes: 8 additions & 2 deletions build/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Run the following commands from the root folder to build, run and kill the application
# >> docker build -f build/Dockerfile -t aam-digital .
# >> docker run -p=80:80 aam-digital
FROM node:16.14.2-alpine3.15 as builder
FROM node:16.14.2-alpine3.15 AS builder
WORKDIR /app

COPY package*.json ./
Expand Down Expand Up @@ -32,6 +32,12 @@ RUN if [ "$UPLOAD_COVERAGE" = true ] ; then \
chmod +x ./cc-test-reporter &&\
./cc-test-reporter before-build ; fi

ARG TZ
RUN if [ -n "${TZ}" ] ; then \
apk --no-cache add tzdata && \
cp /usr/share/zoneinfo/Europe/Brussels /etc/localtime && \
echo "$TZ" > /etc/timezone ; fi

# When set to true, chromium is installed an tests are executed
ARG RUN_TESTS=false
ARG CHROME_BIN=/usr/bin/chromium-browser
Expand Down Expand Up @@ -59,7 +65,7 @@ ARG SENTRY_ORG
ARG SENTRY_PROJECT
RUN if [ "$SENTRY_AUTH_TOKEN" != "" ] ; then \
npm install -g @sentry/cli &&\
sentry-cli --auth-token=$SENTRY_AUTH_TOKEN releases --org=$SENTRY_ORG --project=$SENTRY_PROJECT files ndb-core@$APP_VERSION upload-sourcemaps dist && \
sentry-cli --auth-token="$SENTRY_AUTH_TOKEN" releases --org="$SENTRY_ORG" --project="$SENTRY_PROJECT" files "ndb-core@$APP_VERSION" upload-sourcemaps dist && \
rm dist/*.map ; fi

### PROD image
Expand Down
38 changes: 24 additions & 14 deletions src/app/child-dev-project/attendance/attendance.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ describe("AttendanceService", () => {
activity1 = RecurringActivity.create("activity 1");
activity2 = RecurringActivity.create("activity 2");

e1_1 = createEvent(new Date("2020-01-01"), activity1.getId(true));
e1_2 = createEvent(new Date("2020-01-02"), activity1.getId(true));
e1_3 = createEvent(new Date("2020-03-02"), activity1.getId(true));
e2_1 = createEvent(new Date("2020-01-01"), activity2.getId(true));
e1_1 = createEvent(moment("2020-01-01").toDate(), activity1.getId(true));
e1_2 = createEvent(moment("2020-01-02").toDate(), activity1.getId(true));
e1_3 = createEvent(moment("2020-03-02").toDate(), activity1.getId(true));
e2_1 = createEvent(moment("2020-01-01").toDate(), activity2.getId(true));

TestBed.configureTestingModule({
imports: [DatabaseTestingModule],
Expand All @@ -69,40 +69,50 @@ describe("AttendanceService", () => {
});

it("gets events for a date", async () => {
const actualEvents = await service.getEventsOnDate(new Date("2020-01-01"));
const actualEvents = await service.getEventsOnDate(
moment("2020-01-01").toDate(),
);
expectEntitiesToMatch(actualEvents, [e1_1, e2_1]);
});

it("gets events including Notes for a date", async () => {
const note1 = Note.create(new Date("2020-01-01"), "manual event note 1");
const note1 = Note.create(
moment("2020-01-01").toDate(),
"manual event note 1",
);
note1.addChild("1");
note1.addChild("2");
note1.category = meetingInteractionCategory;
await entityMapper.save(note1);

const note2 = Note.create(new Date("2020-01-02"), "manual event note 2");
const note2 = Note.create(
moment("2020-01-02").toDate(),
"manual event note 2",
);
note2.addChild("1");
note2.category = meetingInteractionCategory;
await entityMapper.save(note2);

const nonMeetingNote = Note.create(
new Date("2020-01-02"),
moment("2020-01-02").toDate(),
"manual event note 3",
);
nonMeetingNote.addChild("1");
nonMeetingNote.category = defaultInteractionTypes.find((t) => !t.isMeeting);
await entityMapper.save(nonMeetingNote);

const actualEvents = await service.getEventsOnDate(
new Date("2020-01-01"),
new Date("2020-01-02"),
moment("2020-01-01").toDate(),
moment("2020-01-02").toDate(),
);

expectEntitiesToMatch(actualEvents, [e1_1, e1_2, e2_1, note1, note2]);
});

it("gets empty array for a date without events", async () => {
const actualEvents = await service.getEventsOnDate(new Date("2007-01-01"));
const actualEvents = await service.getEventsOnDate(
moment("2007-01-01").toDate(),
);
expect(actualEvents).toBeEmpty();
});

Expand Down Expand Up @@ -210,7 +220,7 @@ describe("AttendanceService", () => {
const childSchoolRelation = new ChildSchoolRelation();
childSchoolRelation.childId = "testChild";
childSchoolRelation.schoolId = "testSchool";
childSchoolRelation.start = new Date("2020-01-01");
childSchoolRelation.start = moment("2020-01-01").toDate();
const testActivity = RecurringActivity.create("new activity");
testActivity.linkedGroups.push("testSchool");

Expand Down Expand Up @@ -329,10 +339,10 @@ describe("AttendanceService", () => {

it("should load the events for a date with date-picker format", async () => {
const datePickerDate = new Date(
new Date("2021-04-05").setHours(0, 0, 0, 0),
moment("2021-04-05").toDate().setHours(0, 0, 0, 0),
);
const sameDayEvent = EventNote.create(
new Date("2021-04-05"),
moment("2021-04-05").toDate(),
"Same Day Event",
);
sameDayEvent.category = meetingInteractionCategory;
Expand Down
19 changes: 14 additions & 5 deletions src/app/child-dev-project/attendance/attendance.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,27 @@ export class AttendanceService {
by_date: {
map: `(doc) => {
if (doc._id.startsWith("${EventNote.ENTITY_TYPE}")) {
var d = new Date(doc.date || null);
var dString = d.getFullYear() + "-" + String(d.getMonth()+1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0")
emit(dString);
if (doc.date && doc.date.length === 10) {
emit(doc.date);
} else {
var d = new Date(doc.date || null);
var dString = d.getFullYear() + "-" + String(d.getMonth()+1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0");
emit(dString);
}
}
}`,
},
// TODO: remove this and use general Note's relatedEntities index?
by_activity: {
map: `(doc) => {
if (doc._id.startsWith("${EventNote.ENTITY_TYPE}") && doc.relatesTo) {
var d = new Date(doc.date || null);
var dString = d.getFullYear() + "-" + String(d.getMonth()+1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0")
var dString;
if (doc.date && doc.date.length === 10) {
dString = doc.date;
} else {
var d = new Date(doc.date || null);
dString = d.getFullYear() + "-" + String(d.getMonth()+1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0");
}
emit(doc.relatesTo + "_" + dString);
}
}`,
Expand Down
16 changes: 16 additions & 0 deletions src/app/child-dev-project/children/children.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,22 @@ describe("ChildrenService", () => {
res = await service.getNotesRelatedTo(s1.getId(true));
expect(res).toEqual([n1]);
});

it("should return the correct notes in a timespan", async () => {
const n1 = Note.create(moment("2023-01-01").toDate());
const n2 = Note.create(moment("2023-01-02").toDate());
const n3 = Note.create(moment("2023-01-03").toDate());
const n4 = Note.create(moment("2023-01-03").toDate());
const n5 = Note.create(moment("2023-01-04").toDate());
await entityMapper.saveAll([n1, n2, n3, n4, n5]);

const res = await service.getNotesInTimespan(
moment("2023-01-02"),
moment("2023-01-03"),
);

expect(res).toEqual(jasmine.arrayWithExactContents([n2, n3, n4]));
});
});

function generateChildEntities(): Child[] {
Expand Down
22 changes: 14 additions & 8 deletions src/app/child-dev-project/children/children.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,12 @@ export class ChildrenService {
map: `(doc) => {
if (!doc._id.startsWith("${Note.ENTITY_TYPE}")) return;
if (!Array.isArray(doc.children) || !doc.date) return;
var d = new Date(doc.date || null);
var dString = d.getFullYear() + "-" + String(d.getMonth()+1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0")
emit(dString);
if (doc.date.length === 10) {
emit(doc.date);
} else {
var d = new Date(doc.date || null);
emit(d.getFullYear() + "-" + String(d.getMonth()+1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0"));
}
}`,
},
},
Expand All @@ -246,12 +249,15 @@ export class ChildrenService {
map: `(doc) => {
if (!doc._id.startsWith("${Note.ENTITY_TYPE}")) return;
if (!Array.isArray(doc.relatedEntities)) return;
var d = new Date(doc.date || null);
var dateString = d.getFullYear() + "-" + String(d.getMonth()+1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0")
var dString;
if (doc.date && doc.date.length === 10) {
dString = doc.date;
} else {
var d = new Date(doc.date || null);
dString = d.getFullYear() + "-" + String(d.getMonth()+1).padStart(2, "0") + "-" + String(d.getDate()).padStart(2, "0");
}
doc.relatedEntities.forEach((relatedEntity) => {
emit([relatedEntity, dateString]);
emit([relatedEntity, dString]);
});
}`,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ describe("DateRangeFilterPanelComponent", () => {
beforeEach(async () => {
dateFilter = new DateFilter("test", "Test", defaultDateFilters);
dateFilter.selectedOption = "1";
jasmine.clock().mockDate(new Date("2023-04-08"));
jasmine.clock().mockDate(moment("2023-04-08").toDate());
await TestBed.configureTestingModule({
imports: [MatNativeDateModule],
providers: [
Expand Down Expand Up @@ -73,8 +73,8 @@ describe("DateRangeFilterPanelComponent", () => {
await cells[12].select();

const filterRange = dateFilter.getDateRange();
expect(filterRange.start).toEqual(new Date("2023-04-08"));
expect(filterRange.end).toEqual(new Date("2023-04-13"));
expect(filterRange.start).toEqual(moment("2023-04-08").toDate());
expect(filterRange.end).toEqual(moment("2023-04-13").toDate());
});

it("should set the dates selected via the preset options", async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { MatNativeDateModule } from "@angular/material/core";
import { NoopAnimationsModule } from "@angular/platform-browser/animations";
import { DateFilter } from "../../../filter/filters/filters";
import { defaultDateFilters } from "./date-range-filter-panel/date-range-filter-panel.component";
import moment from "moment";

describe("DateRangeFilterComponent", () => {
let component: DateRangeFilterComponent<any>;
Expand Down Expand Up @@ -33,7 +34,7 @@ describe("DateRangeFilterComponent", () => {
component.filterConfig = dateFilter;
expect(component.dateFilter.getFilter()).toEqual({});

jasmine.clock().mockDate(new Date("2023-05-18"));
jasmine.clock().mockDate(moment("2023-05-18").toDate());
dateFilter.selectedOption = "0";
component.filterConfig = dateFilter;
let expectedDataFilter = {
Expand Down Expand Up @@ -101,8 +102,8 @@ describe("DateRangeFilterComponent", () => {

it("should set the correct date filter when changing the date range manually", () => {
component.filterConfig = new DateFilter("test", "test", []);
component.fromDate = new Date("2021-10-28");
component.toDate = new Date("2024-02-12");
component.fromDate = moment("2021-10-28").toDate();
component.toDate = moment("2024-02-12").toDate();

component.dateChangedManually();

Expand Down
5 changes: 3 additions & 2 deletions src/app/core/basic-datatypes/map/map.datatype.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { TestBed, waitForAsync } from "@angular/core/testing";
import { DatabaseField } from "../../entity/database-field.decorator";
import { EntitySchemaService } from "../../entity/schema/entity-schema.service";
import { MockedTestingModule } from "../../../utils/mocked-testing.module";
import moment from "moment";

describe("Schema data type: map", () => {
class TestEntity extends Entity {
Expand All @@ -39,8 +40,8 @@ describe("Schema data type: map", () => {
it("converts contained dates to month for saving", () => {
const id = "test1";
const entity = new TestEntity(id);
entity.dateMap.set("a", new Date("2020-01-01"));
entity.dateMap.set("b", new Date("1999-01-25"));
entity.dateMap.set("a", moment("2020-01-01").toDate());
entity.dateMap.set("b", moment("1999-01-25").toDate());

const rawData = entitySchemaService.transformEntityToDatabaseFormat(entity);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { DatabaseField } from "../../entity/database-field.decorator";
import { EntitySchemaService } from "../../entity/schema/entity-schema.service";
import { TestBed, waitForAsync } from "@angular/core/testing";
import { MockedTestingModule } from "../../../utils/mocked-testing.module";
import moment from "moment";

describe("Schema data type: schema-embed", () => {
class InnerClass {
Expand Down Expand Up @@ -55,7 +56,7 @@ describe("Schema data type: schema-embed", () => {

it("applies inner schema transformation for database format", () => {
const entity = new TestEntity();
entity.embedded.value = new Date("2020-01-01");
entity.embedded.value = moment("2020-01-01").toDate();

const rawData = entitySchemaService.transformEntityToDatabaseFormat(entity);
expect(rawData.embedded.value).toEqual("2020-01");
Expand Down
5 changes: 3 additions & 2 deletions src/app/core/export/download-service/download.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { DatabaseEntity } from "../../entity/database-entity.decorator";
import { Entity } from "../../entity/model/entity";
import { ConfigurableEnumValue } from "../../basic-datatypes/configurable-enum/configurable-enum.interface";
import { DatabaseField } from "../../entity/database-field.decorator";
import moment from "moment";

describe("DownloadService", () => {
let service: DownloadService;
Expand Down Expand Up @@ -96,7 +97,7 @@ describe("DownloadService", () => {

const testEntity = new TestEntity();
testEntity.enumProperty = testEnumValue;
testEntity.dateProperty = new Date(testDate);
testEntity.dateProperty = moment(testDate).toDate();
testEntity.boolProperty = true;

const csvExport = await service.createCsv([testEntity]);
Expand All @@ -112,7 +113,7 @@ describe("DownloadService", () => {

it("should export a date as YYYY-MM-dd only", async () => {
const dateString = "2021-01-01";
const dateObject = new Date(dateString);
const dateObject = moment(dateString).toDate();
dateObject.setHours(10, 11, 12);

const exportData = [
Expand Down
11 changes: 6 additions & 5 deletions src/app/core/filter/filter.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { DataFilter } from "../common-components/entity-subrecord/entity-subreco
import { Note } from "../../child-dev-project/notes/model/note";
import { ConfigurableEnumService } from "../basic-datatypes/configurable-enum/configurable-enum.service";
import { createTestingConfigurableEnumService } from "../basic-datatypes/configurable-enum/configurable-enum-testing";
import moment from "moment";

describe("FilterService", () => {
let service: FilterService;
Expand Down Expand Up @@ -67,11 +68,11 @@ describe("FilterService", () => {
});

it("should support filtering dates with day granularity", () => {
const n1 = Note.create(new Date("2022-01-01"));
const n2 = Note.create(new Date("2022-01-02"));
const n3 = Note.create(new Date("2022-01-03"));
const n4 = Note.create(new Date("2022-01-04"));
const n5 = Note.create(new Date("2022-01-05"));
const n1 = Note.create(moment("2022-01-01").toDate());
const n2 = Note.create(moment("2022-01-02").toDate());
const n3 = Note.create(moment("2022-01-03").toDate());
const n4 = Note.create(moment("2022-01-04").toDate());
const n5 = Note.create(moment("2022-01-05").toDate());
const notes = [n1, n2, n3, n4, n5];

let predicate = service.getFilterPredicate({
Expand Down
8 changes: 4 additions & 4 deletions src/app/core/filter/filter.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { EntitySchemaField } from "../entity/schema/entity-schema-field";
import { DataFilter } from "../common-components/entity-subrecord/entity-subrecord/entity-subrecord-config";
import { Entity } from "../entity/model/entity";
import {
createFactory,
allParsingInstructions,
allInterpreters,
Filter,
allParsingInstructions,
compare,
createFactory,
Filter,
} from "@ucast/mongo2js";
import moment from "moment";
import { ConfigurableEnumService } from "../basic-datatypes/configurable-enum/configurable-enum.service";
Expand Down Expand Up @@ -72,7 +72,7 @@ export class FilterService {
value = this.parseConfigurableEnumValue(property, value);
}
if (property.dataType.includes("date")) {
value = new Date(value);
value = moment(value).toDate();
}
newEntity[key] = value;
}
Expand Down
Loading

0 comments on commit 6444f44

Please sign in to comment.