Dated the demo cons in the Persistence package from the weekend after seeding, and re-dated the ones already seeded.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e0524da525
commit
3a3d2619ad
6 files changed
+77
-32
No files matched your search
@@ -29,7 +29,7 @@ struct CreateCommunity: AsyncMigration {
|
||||
.unique(on: "user_id", "series_slug", "issue")
|
||||
.create()
|
||||
|
||||
for (event, shops) in Seed.events {
|
||||
for (event, shops) in Seed.events(after: .init()) {
|
||||
let record = EventRecord(event)
|
||||
|
||||
try await record.save(on: database)
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import FluentKit
|
||||
import Foundation
|
||||
|
||||
/// Re-dates the demo cons from the first weekend after it runs, for databases seeded when ``CreateCommunity`` used fixed dates.
|
||||
struct RedateEvents: AsyncMigration {
|
||||
|
||||
// MARK: Methods
|
||||
|
||||
func prepare(on database: Database) async throws {
|
||||
for (event, _) in Seed.events(after: .init()) {
|
||||
try await EventRecord.query(on: database)
|
||||
.filter(\.$slug == event.slug)
|
||||
.set(\.$startsOn, to: event.startsOn)
|
||||
.set(\.$endsOn, to: event.endsOn)
|
||||
.update()
|
||||
}
|
||||
}
|
||||
|
||||
func revert(on database: Database) async throws {}
|
||||
|
||||
}
|
||||
@@ -158,29 +158,36 @@ enum Seed {
|
||||
),
|
||||
]
|
||||
|
||||
/// The demo cons, soonest first, each with the slugs of the shops trading there.
|
||||
static let events: [(event: Event, shops: [String])] = [
|
||||
(.init(slug: "dutch-comic-con", name: "Dutch Comic Con", venue: "Jaarbeurs, Utrecht", startsOn: day(2026, 9, 26), endsOn: day(2026, 9, 27)),
|
||||
["kestrel-row-comics", "silverfish-comics", "third-panel-supply"]),
|
||||
(.init(slug: "stripdagen-haarlem", name: "Stripdagen Haarlem", venue: "Grote Markt, Haarlem", startsOn: day(2026, 10, 3), endsOn: day(2026, 10, 4)),
|
||||
["silverfish-comics"]),
|
||||
(.init(slug: "comic-con-amsterdam", name: "Comic Con Amsterdam", venue: "RAI, Amsterdam", startsOn: day(2026, 11, 21), endsOn: day(2026, 11, 22)),
|
||||
["kestrel-row-comics", "inkwell-and-staple"]),
|
||||
(.init(slug: "comic-con-brussels", name: "Comic Con Brussels", venue: "Tour & Taxis, Brussels", startsOn: day(2026, 12, 5), endsOn: day(2026, 12, 6)),
|
||||
["third-panel-supply"]),
|
||||
]
|
||||
/// The demo cons, soonest first, each with the slugs of the shops trading there, dated from the first weekend after `date`.
|
||||
static func events(
|
||||
after date: Date
|
||||
) -> [(event: Event, shops: [String])] {
|
||||
[
|
||||
("dutch-comic-con", "Dutch Comic Con", "Jaarbeurs, Utrecht", 0, ["kestrel-row-comics", "silverfish-comics", "third-panel-supply"]),
|
||||
("stripdagen-haarlem", "Stripdagen Haarlem", "Grote Markt, Haarlem", 1, ["silverfish-comics"]),
|
||||
("comic-con-amsterdam", "Comic Con Amsterdam", "RAI, Amsterdam", 8, ["kestrel-row-comics", "inkwell-and-staple"]),
|
||||
("comic-con-brussels", "Comic Con Brussels", "Tour & Taxis, Brussels", 10, ["third-panel-supply"]),
|
||||
]
|
||||
.map { slug, name, venue, week, shops in
|
||||
let (startsOn, endsOn) = weekend(week, after: date)
|
||||
|
||||
/// Noon on a day in Amsterdam, where the demo cons are dated.
|
||||
static func day(
|
||||
_ year: Int,
|
||||
_ month: Int,
|
||||
_ day: Int
|
||||
) -> Date {
|
||||
return (.init(slug: slug, name: name, venue: venue, startsOn: startsOn, endsOn: endsOn), shops)
|
||||
}
|
||||
}
|
||||
|
||||
/// Noon on the Saturday and Sunday `week` weeks on from the first weekend after `date`, in Amsterdam, where the demo cons are held.
|
||||
static func weekend(
|
||||
_ week: Int,
|
||||
after date: Date
|
||||
) -> (startsOn: Date, endsOn: Date) {
|
||||
var calendar = Calendar(identifier: .gregorian)
|
||||
|
||||
calendar.timeZone = TimeZone(identifier: "Europe/Amsterdam") ?? .gmt
|
||||
|
||||
return calendar.date(from: .init(year: year, month: month, day: day, hour: 12)) ?? .distantPast
|
||||
let saturday = calendar.nextDate(after: date, matching: .init(hour: 12, weekday: 7), matchingPolicy: .nextTime) ?? date
|
||||
let startsOn = calendar.date(byAdding: .weekOfYear, value: week, to: saturday) ?? saturday
|
||||
|
||||
return (startsOn, calendar.date(byAdding: .day, value: 1, to: startsOn) ?? startsOn)
|
||||
}
|
||||
|
||||
/// The runs the demo listings belong to.
|
||||
|
||||
@@ -33,6 +33,7 @@ public struct PrepareDB: Sendable {
|
||||
CreatePasskey(),
|
||||
CreateCollecting(),
|
||||
CreateCommunity(),
|
||||
RedateEvents(),
|
||||
])
|
||||
}
|
||||
|
||||
|
||||
+26
-8
@@ -46,13 +46,13 @@ struct CommunityRepositoryTests {
|
||||
let clock = Clock()
|
||||
let collecting = CollectingRepository(fluent: fluent, now: clock.now)
|
||||
|
||||
// 22 September 2026: every demo con is still to come.
|
||||
clock.advance(by: Seed.day(2026, 9, 22).timeIntervalSince(clock.now()))
|
||||
// The present, which every demo con is seeded after.
|
||||
clock.advance(by: Date().timeIntervalSince(clock.now()))
|
||||
|
||||
let all = try await collecting.upcomingEvents()
|
||||
|
||||
// Sunday 27 September, the con's last day: still on. Two weeks later it is over, and so is Stripdagen.
|
||||
clock.advance(by: 5 * 86_400)
|
||||
// The first con's last day: still on. Two weeks later it is over, and so is Stripdagen.
|
||||
clock.advance(by: try #require(all.first).endsOn.timeIntervalSince(clock.now()))
|
||||
|
||||
let lastDay = try await collecting.upcomingEvents()
|
||||
|
||||
@@ -67,17 +67,35 @@ struct CommunityRepositoryTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
func `dates the demo cons on weekends, from the first one after seeding`() {
|
||||
var calendar = Calendar(identifier: .gregorian)
|
||||
|
||||
calendar.timeZone = TimeZone(identifier: "Europe/Amsterdam") ?? .gmt
|
||||
|
||||
// Monday 21 September 2026: the dates the prototype first shipped with.
|
||||
let days = Seed.events(after: Date(timeIntervalSince1970: 1_790_000_000)).map { entry in
|
||||
[entry.event.startsOn, entry.event.endsOn]
|
||||
.map { calendar.dateComponents([.month, .day, .hour], from: $0) }
|
||||
.map { "\($0.month ?? 0)/\($0.day ?? 0) \($0.hour ?? 0):00" }
|
||||
}
|
||||
|
||||
#expect(days == [
|
||||
["9/26 12:00", "9/27 12:00"],
|
||||
["10/3 12:00", "10/4 12:00"],
|
||||
["11/21 12:00", "11/22 12:00"],
|
||||
["12/5 12:00", "12/6 12:00"],
|
||||
])
|
||||
}
|
||||
|
||||
@Test
|
||||
func `lets a seller pick the events their shop trades at`() async throws {
|
||||
try await withDatabase { fluent in
|
||||
let clock = Clock()
|
||||
let collecting = CollectingRepository(fluent: fluent, now: clock.now)
|
||||
let collecting = CollectingRepository(fluent: fluent)
|
||||
let accounts = AccountRepository(fluent: fluent)
|
||||
let joost = try await accounts.account(email: "joost@kestrelrow.example")
|
||||
let mara = try await accounts.account(email: "mara.v@example.com")
|
||||
|
||||
clock.advance(by: Seed.day(2026, 9, 22).timeIntervalSince(clock.now()))
|
||||
|
||||
try await collecting.setEvents(["stripdagen-haarlem", "comic-con-amsterdam", "no-such-event"], forShopOwnedBy: joost)
|
||||
// An account without a shop changes nothing.
|
||||
try await collecting.setEvents(["dutch-comic-con"], forShopOwnedBy: mara)
|
||||
|
||||
Reference in new issue
Block a user