diff --git a/source/calendarwebapp/event.d b/source/calendarwebapp/event.d index bf6d0db..be4fde7 100644 --- a/source/calendarwebapp/event.d +++ b/source/calendarwebapp/event.d @@ -2,7 +2,7 @@ module calendarwebapp.event; import poodinis; -import std.algorithm : map; +import std.algorithm : filter, map; import std.conv : to; import std.datetime : Date; import std.range.interfaces : InputRange, inputRangeObject; @@ -82,7 +82,8 @@ public: scope (exit) cn.close; auto prepared = cn.prepare( - "SELECT id begin end name description type shout FROM " ~ eventsTableName ~ " WHERE id = ?"); + "SELECT id begin end name description type shout FROM " + ~ eventsTableName ~ " WHERE id = ?"); prepared.setArg(0, id.to!uint); return toEvent(prepared.query.front); } @@ -103,7 +104,8 @@ public: scope (exit) cn.close; auto prepared = cn.prepare( - "INSERT INTO " ~ eventsTableName ~ " (begin, end, name, description, type, shout) VALUES(?, ?, ?, ?, ?, ?)"); + "INSERT INTO " ~ eventsTableName + ~ " (begin, end, name, description, type, shout) VALUES(?, ?, ?, ?, ?, ?)"); prepared.setArgs(event.begin, event.end, event.name, event.description, event.type.to!uint, event.shout); prepared.exec(); @@ -148,6 +150,42 @@ private: } } +class StubEventStore : EventStore +{ +private: + Event[string] events; + +public: + Event getEvent(string id) @safe + { + import std.exception : enforce; + + enforce((id in events) != null, "No event with id \"" ~ id ~ "\"."); + return events[id]; + } + + InputRange!Event getAllEvents() nothrow + { + return events.byValue.inputRangeObject; + } + + void addEvent(Event event) @safe nothrow + { + events[event.id] = event; + } + + InputRange!Event getEventsBeginningBetween(Date begin, Date end) nothrow + { + return events.byValue.filter!(event => event.begin >= begin + && event.begin < end).inputRangeObject; + } + + void removeEvent(string id) @safe nothrow + { + events.remove(id); + } +} + enum EventType { Holiday, diff --git a/source/calendarwebapp/jsonexport.d b/source/calendarwebapp/jsonexport.d index f9e3b02..21540ee 100644 --- a/source/calendarwebapp/jsonexport.d +++ b/source/calendarwebapp/jsonexport.d @@ -70,10 +70,9 @@ public: { dayJSONManager.addEvent(event); } - auto trackedDays = Interval!Date(startDate, endDate).fwdRange(date => date + 1.dur!"days") + return Interval!Date(startDate, endDate).fwdRange(date => date + 1.dur!"days") .map!(day => dayJSONManager.getDayData(day)).array; } - } private: diff --git a/test/calendarwebapp/testevent.d b/test/calendarwebapp/testevent.d index 4f0024b..a0787ce 100644 --- a/test/calendarwebapp/testevent.d +++ b/test/calendarwebapp/testevent.d @@ -165,3 +165,366 @@ public: collection.verify; } + +@("StubEventStore.getEvent no event") +@safe unittest +{ + auto store = new StubEventStore; + + store.getEvent("").shouldThrow; + store.getEvent("599090de97355141140fc698").shouldThrow; +} + +@("StubEventStore.getEvent 1 event") +@safe unittest +{ + auto store = new StubEventStore; + store.addEvent(Event("599090de97355141140fc698")); + + store.getEvent("599090de97355141140fc698").shouldEqual(Event("599090de97355141140fc698")); + store.getEvent("59cb9ad8fc0ba5751c0df02b").shouldThrow; + store.getEvent("").shouldThrow; +} + +@("StubEventStore.getEvent 2 events") +@safe unittest +{ + auto store = new StubEventStore; + store.addEvent(Event("599090de97355141140fc698")); + store.addEvent(Event("59cb9ad8fc0ba5751c0df02b")); + + store.getEvent("599090de97355141140fc698").shouldEqual(Event("599090de97355141140fc698")); + store.getEvent("59cb9ad8fc0ba5751c0df02b").shouldEqual(Event("59cb9ad8fc0ba5751c0df02b")); + store.getEvent("").shouldThrow; +} + +@("StubEventStore.getAllEvents no event") +@system unittest +{ + auto store = new StubEventStore; + + store.getAllEvents.empty.shouldBeTrue; +} + +@("StubEventStore.getAllEvents 1 event") +@system unittest +{ + auto store = new StubEventStore; + store.addEvent(Event("599090de97355141140fc698")); + + store.getAllEvents.array.shouldEqual([Event("599090de97355141140fc698")]); +} + +@("StubEventStore.getAllEvents 2 events") +@system unittest +{ + auto store = new StubEventStore; + store.addEvent(Event("599090de97355141140fc698")); + store.addEvent(Event("59cb9ad8fc0ba5751c0df02b")); + + store.getAllEvents.array.shouldEqual([Event("599090de97355141140fc698"), + Event("59cb9ad8fc0ba5751c0df02b")]); +} + +@("StubEventStore.getEventsBeginningBetween no event") +@system unittest +{ + import std.datetime.date : Date; + + auto store = new StubEventStore; + store.getEventsBeginningBetween(Date(2017, 12, 10), Date(2018, 1, 1)).empty.shouldBeTrue; +} + +@("StubEventStore.getEventsBeginningBetween 1 event on begin") +@system unittest +{ + import std.datetime.date : Date; + + auto store = new StubEventStore; + auto event = Event("599090de97355141140fc698", Date(2017, 12, 10)); + store.addEvent(event); + + store.getEventsBeginningBetween(Date(2017, 12, 10), Date(2018, 1, 1)).front.shouldEqual(event); +} + +@("StubEventStore.getEventsBeginningBetween 1 event on end excluded") +@system unittest +{ + import std.datetime.date : Date; + + auto store = new StubEventStore; + auto event = Event("599090de97355141140fc698", Date(2018, 1, 1)); + store.addEvent(event); + + store.getEventsBeginningBetween(Date(2017, 12, 10), Date(2018, 1, 1)).empty.shouldBeTrue; +} + +@("StubEventStore.getEventsBeginningBetween 1 event on end included") +@system unittest +{ + import std.datetime.date : Date; + + auto store = new StubEventStore; + auto event = Event("599090de97355141140fc698", Date(2017, 12, 31)); + store.addEvent(event); + + store.getEventsBeginningBetween(Date(2017, 12, 10), Date(2018, 1, 1)).front.shouldEqual(event); +} + +@("StubEventStore.getEventsBeginningBetween 1 event somwhere inbetween") +@system unittest +{ + import std.datetime.date : Date; + + auto store = new StubEventStore; + auto event = Event("599090de97355141140fc698", Date(2017, 12, 17)); + store.addEvent(event); + + store.getEventsBeginningBetween(Date(2017, 12, 10), Date(2018, 1, 1)).front.shouldEqual(event); +} + +@("StubEventStore.getEventsBeginningBetween 1 event somwhere before") +@system unittest +{ + import std.datetime.date : Date; + + auto store = new StubEventStore; + auto event = Event("599090de97355141140fc698", Date(2016, 12, 17)); + store.addEvent(event); + + store.getEventsBeginningBetween(Date(2017, 12, 10), Date(2018, 1, 1)).empty.shouldBeTrue; +} + +@("StubEventStore.getEventsBeginningBetween 1 event somwhere after") +@system unittest +{ + import std.datetime.date : Date; + + auto store = new StubEventStore; + auto event = Event("599090de97355141140fc698", Date(2018, 12, 17)); + store.addEvent(event); + + store.getEventsBeginningBetween(Date(2017, 12, 10), Date(2018, 1, 1)).empty.shouldBeTrue; +} + +@("StubEventStore.getEventsBeginningBetween 1 event somewhere before, 1 event somewhere after") +@system unittest +{ + import std.datetime.date : Date; + + auto store = new StubEventStore; + auto event1 = Event("599090de97355141140fc698", Date(2016, 12, 17)); + auto event2 = Event("59cb9ad8fc0ba5751c0df02b", Date(2018, 12, 17)); + store.addEvent(event1); + store.addEvent(event2); + + store.getEventsBeginningBetween(Date(2017, 12, 10), Date(2018, 1, 1)).empty.shouldBeTrue; +} + +@("StubEventStore.getEventsBeginningBetween 2 events before") +@system unittest +{ + import std.datetime.date : Date; + + auto store = new StubEventStore; + auto event1 = Event("599090de97355141140fc698", Date(2016, 12, 17)); + auto event2 = Event("59cb9ad8fc0ba5751c0df02b", Date(2016, 12, 16)); + store.addEvent(event1); + store.addEvent(event2); + + store.getEventsBeginningBetween(Date(2017, 12, 10), Date(2018, 1, 1)).empty.shouldBeTrue; +} + +@("StubEventStore.getEventsBeginningBetween 2 events after") +@system unittest +{ + import std.datetime.date : Date; + + auto store = new StubEventStore; + auto event1 = Event("599090de97355141140fc698", Date(2018, 12, 17)); + auto event2 = Event("59cb9ad8fc0ba5751c0df02b", Date(2018, 12, 16)); + store.addEvent(event1); + store.addEvent(event2); + + store.getEventsBeginningBetween(Date(2017, 12, 10), Date(2018, 1, 1)).empty.shouldBeTrue; +} + +@("StubEventStore.getEventsBeginningBetween 1 event on begin, 1 event somwhere outside") +@system unittest +{ + import std.datetime.date : Date; + + auto store = new StubEventStore; + auto event1 = Event("599090de97355141140fc698", Date(2017, 12, 10)); + auto event2 = Event("59cb9ad8fc0ba5751c0df02b", Date(2018, 12, 16)); + store.addEvent(event1); + store.addEvent(event2); + + store.getEventsBeginningBetween(Date(2017, 12, 10), Date(2018, 1, 1)) + .array.shouldEqual([event1]); +} + +@("StubEventStore.getEventsBeginningBetween 1 event on end excluded, 1 event somwhere outside") +@system unittest +{ + import std.datetime.date : Date; + + auto store = new StubEventStore; + auto event1 = Event("599090de97355141140fc698", Date(2018, 1, 1)); + auto event2 = Event("59cb9ad8fc0ba5751c0df02b", Date(2018, 12, 16)); + store.addEvent(event1); + store.addEvent(event2); + + store.getEventsBeginningBetween(Date(2017, 12, 10), Date(2018, 1, 1)).empty.shouldBeTrue; +} + +@("StubEventStore.getEventsBeginningBetween 1 event on end included, 1 event somwhere outside") +@system unittest +{ + import std.datetime.date : Date; + + auto store = new StubEventStore; + auto event1 = Event("599090de97355141140fc698", Date(2017, 12, 31)); + auto event2 = Event("59cb9ad8fc0ba5751c0df02b", Date(2018, 12, 16)); + store.addEvent(event1); + store.addEvent(event2); + + store.getEventsBeginningBetween(Date(2017, 12, 10), Date(2018, 1, 1)) + .array.shouldEqual([event1]); +} + +@("StubEventStore.getEventsBeginningBetween 1 event somewhere inside, 1 event somwhere outside") +@system unittest +{ + import std.datetime.date : Date; + + auto store = new StubEventStore; + auto event1 = Event("599090de97355141140fc698", Date(2017, 12, 17)); + auto event2 = Event("59cb9ad8fc0ba5751c0df02b", Date(2018, 12, 16)); + store.addEvent(event1); + store.addEvent(event2); + + store.getEventsBeginningBetween(Date(2017, 12, 10), Date(2018, 1, 1)) + .array.shouldEqual([event1]); +} + +@("StubEventStore.getEventsBeginningBetween 1 event somewhere inside, 1 event on begin") +@system unittest +{ + import std.datetime.date : Date; + import std.exception : assumeUnique; + + auto store = new StubEventStore; + immutable event1 = Event("599090de97355141140fc698", Date(2017, 12, 17)); + immutable event2 = Event("59cb9ad8fc0ba5751c0df02b", Date(2017, 12, 10)); + store.addEvent(event1); + store.addEvent(event2); + + immutable events = assumeUnique(store.getEventsBeginningBetween(Date(2017, + 12, 10), Date(2018, 1, 1)).array); + + event1.shouldBeIn(events); + event2.shouldBeIn(events); + events.length.shouldEqual(2); +} + +@("StubEventStore.getEventsBeginningBetween 1 event somewhere inside, 1 event on end excluded") +@system unittest +{ + import std.datetime.date : Date; + import std.exception : assumeUnique; + + auto store = new StubEventStore; + immutable event1 = Event("599090de97355141140fc698", Date(2017, 12, 17)); + immutable event2 = Event("59cb9ad8fc0ba5751c0df02b", Date(2018, 1, 1)); + store.addEvent(event1); + store.addEvent(event2); + + immutable events = assumeUnique(store.getEventsBeginningBetween(Date(2017, + 12, 10), Date(2018, 1, 1)).array); + + event1.shouldBeIn(events); + event2.shouldNotBeIn(events); + events.length.shouldEqual(1); +} + +@("StubEventStore.getEventsBeginningBetween 1 event somewhere inside, 1 event on end included") +@system unittest +{ + import std.datetime.date : Date; + import std.exception : assumeUnique; + + auto store = new StubEventStore; + immutable event1 = Event("599090de97355141140fc698", Date(2017, 12, 17)); + immutable event2 = Event("59cb9ad8fc0ba5751c0df02b", Date(2017, 12, 31)); + store.addEvent(event1); + store.addEvent(event2); + + immutable events = assumeUnique(store.getEventsBeginningBetween(Date(2017, + 12, 10), Date(2018, 1, 1)).array); + + event1.shouldBeIn(events); + event2.shouldBeIn(events); + events.length.shouldEqual(2); +} + +@("StubEventStore.getEventsBeginningBetween 2 events somewhere inside") +@system unittest +{ + import std.datetime.date : Date; + import std.exception : assumeUnique; + + auto store = new StubEventStore; + immutable event1 = Event("599090de97355141140fc698", Date(2017, 12, 17)); + immutable event2 = Event("59cb9ad8fc0ba5751c0df02b", Date(2017, 12, 24)); + store.addEvent(event1); + store.addEvent(event2); + + immutable events = assumeUnique(store.getEventsBeginningBetween(Date(2017, + 12, 10), Date(2018, 1, 1)).array); + + event1.shouldBeIn(events); + event2.shouldBeIn(events); + events.length.shouldEqual(2); +} + +@("StubEventStore.removeEvent 1 event") +@system unittest +{ + auto store = new StubEventStore; + immutable event = Event("599090de97355141140fc698"); + store.addEvent(event); + store.getEvent("599090de97355141140fc698").shouldEqual(event); + store.removeEvent(""); + store.getEvent("599090de97355141140fc698").shouldEqual(event); + store.removeEvent("599090de97355141140fc698"); + store.getEvent("599090de97355141140fc698").shouldThrow; +} + +@("StubEventStore.removeEvent 2 events") +@system unittest +{ + auto store = new StubEventStore; + immutable event1 = Event("599090de97355141140fc698"); + immutable event2 = Event("59cb9ad8fc0ba5751c0df02b"); + store.addEvent(event1); + store.addEvent(event2); + + store.getEvent("599090de97355141140fc698").shouldEqual(event1); + store.getEvent("59cb9ad8fc0ba5751c0df02b").shouldEqual(event2); + + store.removeEvent(""); + + store.getEvent("599090de97355141140fc698").shouldEqual(event1); + store.getEvent("59cb9ad8fc0ba5751c0df02b").shouldEqual(event2); + + store.removeEvent("599090de97355141140fc698"); + + store.getEvent("599090de97355141140fc698").shouldThrow; + store.getEvent("59cb9ad8fc0ba5751c0df02b").shouldEqual(event2); + + store.removeEvent("59cb9ad8fc0ba5751c0df02b"); + + store.getEvent("599090de97355141140fc698").shouldThrow; + store.getEvent("59cb9ad8fc0ba5751c0df02b").shouldThrow; +} diff --git a/test/calendarwebapp/testjsonexport.d b/test/calendarwebapp/testjsonexport.d index 5abcf5b..35aa00f 100644 --- a/test/calendarwebapp/testjsonexport.d +++ b/test/calendarwebapp/testjsonexport.d @@ -1,13 +1,21 @@ module test.calendarwebapp.testjsonexport; +import calendarwebapp.event; import calendarwebapp.jsonexport; -import unit_threaded; +import poodinis; + +import std.algorithm; import std.datetime.date : Date; +import std.exception : enforce; +import std.range.interfaces : InputRange, inputRangeObject; + +import unit_threaded; @("calendarwebapp.JSONExporter") @system unittest { - auto exporter = new JSONExporter; - exporter.write.shouldEqual(Date(2018, 2, 1)); + auto container = new shared DependencyContainer(); + container.register!(EventStore, StubEventStore); + container.register!(JSONExporter); }