Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: CI

on:
push:
pull_request:

jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
- run: npm ci
- run: npm run build
- run: npm test
76 changes: 42 additions & 34 deletions __tests__/CronJob_tests.res
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
open Jest
open Expect

beforeEach(() => Jest.useFakeTimers())
beforeEach(() => Jest.useFakeTimers(~implementation=#legacy, ()))
afterEach(() => {
RescriptJestDateMock.clear()
Jest.clearAllTimers()
Expand All @@ -17,16 +17,16 @@ describe("creating of CronJob", () => {
let jobHasTicked = ref(false)
let onTick = _ => jobHasTicked := true

RescriptJestDateMock.advanceTo(Js.Date.fromString(pastDate))
RescriptJestDateMock.advanceTo(Date.fromString(pastDate))

let job = RescriptCron.CronJob.make(#JsDate(Js.Date.fromString(futureDate)), onTick, ())
let job = RescriptCron.CronJob.make(#JsDate(Date.fromString(futureDate)), onTick, ())

RescriptCron.start(job)

RescriptJestDateMock.advanceTo(Js.Date.fromString(postFutureDate))
RescriptJestDateMock.advanceTo(Date.fromString(postFutureDate))
Jest.runAllTimers()

expect(jobHasTicked.contents) -> toEqual(true)
expect(jobHasTicked.contents)->toEqual(true)
})

test("creating a CronJob with onComplete option", () => {
Expand All @@ -36,14 +36,19 @@ describe("creating of CronJob", () => {
let onTick = _ => jobHasTicked := true
let onComplete = _ => jobHasCompleted := true

RescriptJestDateMock.advanceTo(Js.Date.fromString(pastDate))
RescriptJestDateMock.advanceTo(Date.fromString(pastDate))

let job = RescriptCron.CronJob.make(#JsDate(Js.Date.fromString(futureDate)), onTick, ~onComplete, ())
let job = RescriptCron.CronJob.make(
#JsDate(Date.fromString(futureDate)),
onTick,
~onComplete,
(),
)

RescriptCron.start(job)
RescriptCron.stop(job)

expect(jobHasCompleted.contents) -> toEqual(true)
expect(jobHasCompleted.contents)->toEqual(true)
})

test("creating a CronJob with onTick and onComplete as param", () => {
Expand All @@ -56,44 +61,49 @@ describe("creating of CronJob", () => {
}
let onComplete = _ => jobHasCompleted := true

RescriptJestDateMock.advanceTo(Js.Date.fromString(pastDate))
RescriptJestDateMock.advanceTo(Date.fromString(pastDate))

let job = RescriptCron.CronJob.make(#JsDate(Js.Date.fromString(futureDate)), onTick, ~onComplete, ())
let job = RescriptCron.CronJob.make(
#JsDate(Date.fromString(futureDate)),
onTick,
~onComplete,
(),
)

RescriptCron.start(job)

RescriptJestDateMock.advanceTo(Js.Date.fromString(postFutureDate))
RescriptJestDateMock.advanceTo(Date.fromString(postFutureDate))
Jest.runAllTimers()

expect(jobHasTicked.contents && jobHasCompleted.contents) -> toEqual(true)
expect(jobHasTicked.contents && jobHasCompleted.contents)->toEqual(true)
})

test("creating a CronJob and not starting will not trigger onTick", () => {
let jobHasTicked = ref(false)
let onTick = _ => jobHasTicked := true

RescriptJestDateMock.advanceTo(Js.Date.fromString(pastDate))
RescriptJestDateMock.advanceTo(Date.fromString(pastDate))

let _ = RescriptCron.CronJob.make(#JsDate(Js.Date.fromString(futureDate)), onTick, ())
let _ = RescriptCron.CronJob.make(#JsDate(Date.fromString(futureDate)), onTick, ())

RescriptJestDateMock.advanceTo(Js.Date.fromString(postFutureDate))
RescriptJestDateMock.advanceTo(Date.fromString(postFutureDate))
Jest.runAllTimers()

expect(jobHasTicked.contents) -> toEqual(false)
expect(jobHasTicked.contents)->toEqual(false)
})

test("creating a CronJob with automatic start of the job", () => {
let jobHasTicked = ref(false)
let onTick = _ => jobHasTicked := true

RescriptJestDateMock.advanceTo(Js.Date.fromString(pastDate))
RescriptJestDateMock.advanceTo(Date.fromString(pastDate))

let _ = RescriptCron.CronJob.make(#JsDate(Js.Date.fromString(futureDate)), onTick, ~start=true, ())
let _ = RescriptCron.CronJob.make(#JsDate(Date.fromString(futureDate)), onTick, ~start=true, ())

RescriptJestDateMock.advanceTo(Js.Date.fromString(postFutureDate))
RescriptJestDateMock.advanceTo(Date.fromString(postFutureDate))
Jest.runAllTimers()

expect(jobHasTicked.contents) -> toEqual(true)
expect(jobHasTicked.contents)->toEqual(true)
})
})

Expand All @@ -105,19 +115,19 @@ describe("changing CronJobs", () => {
let onTick = _ => jobHasTicked := true
let callback = _ => callbackHasTicked := true

RescriptJestDateMock.advanceTo(Js.Date.fromString(pastDate))
RescriptJestDateMock.advanceTo(Date.fromString(pastDate))

let job = RescriptCron.CronJob.make(#JsDate(Js.Date.fromString(futureDate)), onTick, ())
let job = RescriptCron.CronJob.make(#JsDate(Date.fromString(futureDate)), onTick, ())

RescriptCron.start(job)

// Adding a callback in addition to the onTick parameter
RescriptCron.addCallback(job, callback)

RescriptJestDateMock.advanceTo(Js.Date.fromString(postFutureDate))
RescriptJestDateMock.advanceTo(Date.fromString(postFutureDate))
Jest.runAllTimers()

expect(jobHasTicked.contents && callbackHasTicked.contents) -> toEqual(true)
expect(jobHasTicked.contents && callbackHasTicked.contents)->toEqual(true)
})

test("fire all callbacks for a CronJob (without timer expiring)", () => {
Expand All @@ -129,9 +139,9 @@ describe("changing CronJobs", () => {
let callback1 = _ => callbackHasTicked1 := true
let callback2 = _ => callbackHasTicked2 := true

RescriptJestDateMock.advanceTo(Js.Date.fromString(pastDate))
RescriptJestDateMock.advanceTo(Date.fromString(pastDate))

let job = RescriptCron.CronJob.make(#JsDate(Js.Date.fromString(futureDate)), onTick, ())
let job = RescriptCron.CronJob.make(#JsDate(Date.fromString(futureDate)), onTick, ())

RescriptCron.start(job)

Expand All @@ -143,28 +153,26 @@ describe("changing CronJobs", () => {

expect(
jobHasTicked.contents && (callbackHasTicked1.contents && callbackHasTicked2.contents),
) -> toEqual(true)
)->toEqual(true)
})

test("changing time of CronJob with setTime and a CronTime", () => {
let onTick = _ => ()

RescriptJestDateMock.advanceTo(Js.Date.fromString("2010-01-01T12:00:00.000Z"))
RescriptJestDateMock.advanceTo(Date.fromString("2010-01-01T12:00:00.000Z"))

let job = RescriptCron.CronJob.make(#JsDate(Js.Date.fromString(futureDate)), onTick, ())
let job = RescriptCron.CronJob.make(#JsDate(Date.fromString(futureDate)), onTick, ())

// every January 20th twelve o'clock
let time = RescriptCron.CronTime.make(#CronString("0 0 12 20 jan *"), ())

let nextAssumedTick =
MomentRe.momentDefaultFormat("2010-01-01T12:00:00.000Z")
|> MomentRe.Moment.setDate(20)
|> MomentRe.Moment.setHour(12)
LuxonDateTime.fromISO("2010-01-01T12:00:00.000Z")->LuxonDateTime.set({day: 20, hour: 12})

RescriptCron.setTime(job, time)

let nextTick = RescriptCron.nextMomentDates(job)->Array.get(0)
let nextTick = RescriptCron.nextDateTimes(job)->Array.getUnsafe(0)

expect(MomentRe.Moment.toJSON(nextTick)) -> toEqual(MomentRe.Moment.toJSON(nextAssumedTick))
expect(LuxonDateTime.toMillis(nextTick))->toEqual(LuxonDateTime.toMillis(nextAssumedTick))
})
})
31 changes: 17 additions & 14 deletions __tests__/CronSyntax_tests.res
Original file line number Diff line number Diff line change
Expand Up @@ -7,53 +7,56 @@ afterEach(() => clear())

describe("functions for just dealing with crontab syntax", () => {
test("sendAt with cron syntax at minute 10", () => {
let aDate = Js.Date.fromString("2018-05-27T12:00:00Z")
let aDate = Date.fromString("2018-05-27T12:00:00Z")
advanceTo(aDate)

let aMomentTenMinutesLater =
Js.Date.setMinutes(aDate, 10.0) |> Js.Date.fromFloat |> MomentRe.momentWithDate
let aMomentTenMinutesLater = LuxonDateTime.fromJSDate(aDate)->LuxonDateTime.set({minute: 10})

// At minute 10
let nextSchedule = RescriptCron.sendAt(#CronString("* 10 * * * *"))

expect(MomentRe.Moment.isSame(nextSchedule, aMomentTenMinutesLater)) -> toBe(true)
expect(LuxonDateTime.toMillis(nextSchedule))->toEqual(
LuxonDateTime.toMillis(aMomentTenMinutesLater),
)
})

test("sendAt with cron syntax at hour 10", () => {
let aDate = Js.Date.fromString("2018-05-27T12:00:00Z")
let aDate = Date.fromString("2018-05-27T12:00:00Z")
advanceTo(aDate)

// Every 10 hours
let nextSchedule = RescriptCron.sendAt(#CronString("* */10 * * *"))

let aMomentWithNext10Hour = MomentRe.momentWithDate(aDate) |> MomentRe.Moment.setHour(20)
let aMomentWithNext10Hour = LuxonDateTime.fromJSDate(aDate)->LuxonDateTime.set({hour: 20})

expect(MomentRe.Moment.isSame(nextSchedule, aMomentWithNext10Hour)) -> toBe(true)
expect(LuxonDateTime.toMillis(nextSchedule))->toEqual(
LuxonDateTime.toMillis(aMomentWithNext10Hour),
)
})

test("sendAt with Js.date instead of cron syntax", () => {
let aDate = Js.Date.fromString("2010-01-27T12:12:00Z")
let aDate = Date.fromString("2010-01-27T12:12:00Z")
advanceTo(aDate)

let futureDate = "2040-05-27T12:00:00.000Z"

// Future Js.Date
let nextSchedule = RescriptCron.sendAt(#JsDate(Js.Date.fromString(futureDate)))
let nextSchedule = RescriptCron.sendAt(#JsDate(Date.fromString(futureDate)))

expect(nextSchedule |> MomentRe.Moment.toDate |> Js.Date.toISOString) -> toBe(futureDate)
expect(Date.toISOString(LuxonDateTime.toJSDate(nextSchedule)))->toBe(futureDate)
})

test("timeout", () => {
let aDate = Js.Date.fromString("2018-05-27T12:00:00Z")
let aDate = Date.fromString("2018-05-27T12:00:00Z")
advanceTo(aDate)

// Every 10 hours
let msToNextFire = RescriptCron.timeout(#CronString("* */10 * * *"))

let aMomentWithNext10Hour = MomentRe.momentWithDate(aDate) |> MomentRe.Moment.setHour(20)
let aMomentWithNext10Hour = LuxonDateTime.fromJSDate(aDate)->LuxonDateTime.set({hour: 20})

let msDiff = MomentRe.diff(aMomentWithNext10Hour, MomentRe.momentNow(), #milliseconds)
let msDiff = LuxonDateTime.diffMilliseconds(aMomentWithNext10Hour, LuxonDateTime.now())

expect(msToNextFire) -> toEqual(msDiff)
expect(msToNextFire)->toEqual(msDiff)
})
})
3 changes: 3 additions & 0 deletions __tests__/RescriptJestDateMock.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@module("jest-date-mock") external advanceBy: int => unit = "advanceBy"
@module("jest-date-mock") external advanceTo: Date.t => unit = "advanceTo"
@module("jest-date-mock") external clear: unit => unit = "clear"
Loading
Loading