Skip to content

Commit

Permalink
Correct Rollover Year Options
Browse files Browse the repository at this point in the history
Courses can always be rolled over into the previous, current, and
several future years.

The academic year doesn't map to the calendar year, so we always need to
ensure we're starting at the right place otherwise the current year will
disappear in January.

From January through the end of June we need to back up even further
because the previous academic year is now two years behind the current
calendar year.
  • Loading branch information
jrjohnson committed Jan 30, 2025
1 parent 5e3edef commit 492a89e
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 12 deletions.
9 changes: 7 additions & 2 deletions packages/ilios-common/addon/components/course/rollover.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
147 changes: 137 additions & 10 deletions packages/test-app/tests/integration/components/course/rollover-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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', {
Expand All @@ -24,12 +39,12 @@ module('Integration | Component | course/rollover', function (hooks) {

await render(hbs`<Course::Rollover @course={{this.course}} />`);

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);
Expand All @@ -53,12 +68,12 @@ module('Integration | Component | course/rollover', function (hooks) {

await render(hbs`<Course::Rollover @course={{this.course}} />`);

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}`);
}
});

Expand All @@ -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(
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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`<Course::Rollover @course={{this.course}} />`);

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`<Course::Rollover @course={{this.course}} />`);

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`<Course::Rollover @course={{this.course}} />`);

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`<Course::Rollover @course={{this.course}} />`);

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);
});
});

0 comments on commit 492a89e

Please sign in to comment.