diff --git a/packages/ilios-common/addon/components/course/rollover.js b/packages/ilios-common/addon/components/course/rollover.js
index b37eec1aad..3592d2a030 100644
--- a/packages/ilios-common/addon/components/course/rollover.js
+++ b/packages/ilios-common/addon/components/course/rollover.js
@@ -26,10 +26,15 @@ export default class CourseRolloverComponent extends Component {
constructor() {
super(...arguments);
- const currentYear = DateTime.now().year;
+ let { month, year } = DateTime.now();
+ year--; // start with the previous year
+ if (month < 7) {
+ // before July 1st (start of a new academic year) show the year before
+ year--;
+ }
this.years = [];
for (let i = 0; i < 6; i++) {
- this.years.push(currentYear + i);
+ this.years.push(year + i);
}
}
diff --git a/packages/test-app/tests/integration/components/course/rollover-test.js b/packages/test-app/tests/integration/components/course/rollover-test.js
index 795d364d71..d0dc6317e7 100644
--- a/packages/test-app/tests/integration/components/course/rollover-test.js
+++ b/packages/test-app/tests/integration/components/course/rollover-test.js
@@ -8,11 +8,26 @@ import { hbs } from 'ember-cli-htmlbars';
import { DateTime } from 'luxon';
import { setupMirage } from 'test-app/tests/test-support/mirage';
import queryString from 'query-string';
+import { freezeDateAt, unfreezeDate } from 'ilios-common';
module('Integration | Component | course/rollover', function (hooks) {
setupRenderingTest(hooks);
setupMirage(hooks);
+ hooks.afterEach(() => {
+ unfreezeDate();
+ });
+
+ const earliestRolloverYear = (jsDate) => {
+ let { month, year } = DateTime.fromJSDate(jsDate);
+ year--; // start with the previous year
+ if (month < 7) {
+ // before July 1st (start of a new academic year) show the year before
+ year--;
+ }
+ return year;
+ };
+
test('it renders', async function (assert) {
const school = this.server.create('school');
const course = this.server.create('course', {
@@ -24,12 +39,12 @@ module('Integration | Component | course/rollover', function (hooks) {
await render(hbs``);
- const currentYear = DateTime.now().year;
+ const firstYear = earliestRolloverYear(new Date());
const yearSelect = '.year-select select';
const title = '.title input';
for (let i = 0; i < 6; i++) {
- assert.dom(`${yearSelect} option:nth-of-type(${i + 1})`).hasText(`${currentYear + i}`);
+ assert.dom(`${yearSelect} option:nth-of-type(${i + 1})`).hasText(`${firstYear + i}`);
}
assert.dom(title).exists({ count: 1 });
assert.strictEqual(find(title).value.trim(), course.title);
@@ -53,12 +68,12 @@ module('Integration | Component | course/rollover', function (hooks) {
await render(hbs``);
- const currentYear = DateTime.now().year;
+ const firstYear = earliestRolloverYear(new Date());
const yearSelect = '.year-select select';
for (let i = 0; i < 6; i++) {
assert
.dom(`${yearSelect} option:nth-of-type(${i + 1})`)
- .hasText(`${currentYear + i} - ${currentYear + i + 1}`);
+ .hasText(`${firstYear + i} - ${firstYear + i + 1}`);
}
});
@@ -74,10 +89,10 @@ module('Integration | Component | course/rollover', function (hooks) {
this.set('course', courseModel);
this.server.post(`/api/courses/${course.id}/rollover`, function (schema, request) {
- const currentYear = DateTime.now().year;
+ const firstYear = earliestRolloverYear(new Date());
const data = queryString.parse(request.requestBody);
assert.ok('year' in data);
- assert.strictEqual(parseInt(data.year, 10), currentYear);
+ assert.strictEqual(parseInt(data.year, 10), firstYear);
assert.strictEqual(data.newCourseTitle, course.title);
assert.ok('newStartDate' in data);
return this.serialize(
@@ -163,24 +178,24 @@ module('Integration | Component | course/rollover', function (hooks) {
test('disable years when title already exists', async function (assert) {
const title = 'to be rolled';
- const currentYear = DateTime.now().year;
+ const firstYear = earliestRolloverYear(new Date());
const school = this.server.create('school');
const course = this.server.create('course', {
title,
school,
- year: currentYear - 1,
+ year: firstYear - 1,
});
this.server.create('course', {
id: 2,
school,
title,
- year: currentYear,
+ year: firstYear,
});
this.server.create('course', {
id: 3,
school,
title,
- year: currentYear + 2,
+ year: firstYear + 2,
});
const courseModel = await this.owner.lookup('service:store').findRecord('course', course.id);
@@ -510,4 +525,116 @@ module('Integration | Component | course/rollover', function (hooks) {
await click(firstCohort);
await click('.done');
});
+
+ test('dates are correct in December', async function (assert) {
+ const december11th2024 = DateTime.fromObject({
+ year: 2024,
+ month: 12,
+ day: 11,
+ hour: 8,
+ });
+ freezeDateAt(december11th2024.toJSDate());
+ const school = this.server.create('school');
+ const course = this.server.create('course', {
+ title: 'old course',
+ school,
+ });
+ const courseModel = await this.owner.lookup('service:store').findRecord('course', course.id);
+ this.set('course', courseModel);
+
+ await render(hbs``);
+
+ const yearSelect = '.year-select select';
+ const title = '.title input';
+
+ const years = [2023, 2024, 2025, 2026, 2027, 2028];
+ years.forEach((year, i) => {
+ assert.dom(`${yearSelect} option:nth-of-type(${i + 1})`).hasText(year.toString());
+ });
+ assert.strictEqual(find(title).value.trim(), course.title);
+ });
+
+ test('dates are correct in January', async function (assert) {
+ const january1st2025 = DateTime.fromObject({
+ year: 2025,
+ month: 1,
+ day: 1,
+ hour: 8,
+ });
+ freezeDateAt(january1st2025.toJSDate());
+ const school = this.server.create('school');
+ const course = this.server.create('course', {
+ title: 'old course',
+ school,
+ });
+ const courseModel = await this.owner.lookup('service:store').findRecord('course', course.id);
+ this.set('course', courseModel);
+
+ await render(hbs``);
+
+ const yearSelect = '.year-select select';
+ const title = '.title input';
+
+ const years = [2023, 2024, 2025, 2026, 2027, 2028];
+ years.forEach((year, i) => {
+ assert.dom(`${yearSelect} option:nth-of-type(${i + 1})`).hasText(year.toString());
+ });
+ assert.strictEqual(find(title).value.trim(), course.title);
+ });
+
+ test('dates are correct in June', async function (assert) {
+ const june30th2025 = DateTime.fromObject({
+ year: 2025,
+ month: 6,
+ day: 30,
+ hour: 8,
+ });
+ freezeDateAt(june30th2025.toJSDate());
+ const school = this.server.create('school');
+ const course = this.server.create('course', {
+ title: 'old course',
+ school,
+ });
+ const courseModel = await this.owner.lookup('service:store').findRecord('course', course.id);
+ this.set('course', courseModel);
+
+ await render(hbs``);
+
+ const yearSelect = '.year-select select';
+ const title = '.title input';
+
+ const years = [2023, 2024, 2025, 2026, 2027, 2028];
+ years.forEach((year, i) => {
+ assert.dom(`${yearSelect} option:nth-of-type(${i + 1})`).hasText(year.toString());
+ });
+ assert.strictEqual(find(title).value.trim(), course.title);
+ });
+
+ test('dates are correct in July', async function (assert) {
+ const july1st2025 = DateTime.fromObject({
+ year: 2025,
+ month: 7,
+ day: 1,
+ hour: 8,
+ });
+ freezeDateAt(july1st2025.toJSDate());
+ const school = this.server.create('school');
+ const course = this.server.create('course', {
+ title: 'old course',
+ school,
+ });
+ const courseModel = await this.owner.lookup('service:store').findRecord('course', course.id);
+ this.set('course', courseModel);
+
+ await render(hbs``);
+
+ const yearSelect = '.year-select select';
+ const title = '.title input';
+
+ const years = [2024, 2025, 2026, 2027, 2028, 2029];
+ years.forEach((year, i) => {
+ assert.dom(`${yearSelect} option:nth-of-type(${i + 1})`).hasText(year.toString());
+ });
+ assert.strictEqual(find(title).value.trim(), course.title);
+ });
});