def test_course_api02_ok_without_timezone(model): """No timezone is OK in API 0.3+ if explicit TZ offset is always given""" add_test_course( model, 'courses/test', { 'title': 'Test course', 'default_time': { 'start': '18:00', 'end': '20:00' }, 'sessions': [ { 'title': 'A precisely specified session', 'slug': 'specified-session', 'time': { 'start': '2019-01-01 18:00:00+0100', 'end': '2019-01-01 20:00+0100', } }, ], }, version=(0, 3), ) course = model.courses['courses/test'] assert course.timezone is None assert course.sessions['specified-session'].date is None tzinfo = datetime.timezone(datetime.timedelta(hours=1)) assert course.sessions['specified-session'].time == { 'start': datetime.datetime(2019, 1, 1, 18, 0, tzinfo=tzinfo), 'end': datetime.datetime(2019, 1, 1, 20, 0, tzinfo=tzinfo), }
def test_course_with_no_default_time(model, assert_model_dump): add_test_course(model, 'courses/without-default-time', { 'title': 'Test course without scheduled times', 'sessions': SESSIONS, }) course = model.courses['courses/without-default-time'] assert course.default_time is None session = course.sessions['normal-session'] assert session.date == datetime.date(2000, 1, 1) assert session.time is None session = course.sessions['afterparty'] assert session.date == datetime.date(2000, 1, 1) assert session.time == { 'start': datetime.datetime(2000, 1, 1, 22, tzinfo=TZINFO), 'end': datetime.datetime(2000, 1, 1, 23, tzinfo=TZINFO), } session = course.sessions['self-study'] assert session.date == None assert session.time == None session = course.sessions['morning-meditation'] assert session.date == None assert session.time == None assert_model_dump(course, 'session-times/without-default-time')
def test_course_api02_ok_without_timezone(model): """No timezone is OK in API 0.3+ if there's not time info""" add_test_course( model, 'courses/test', { 'title': 'Test course', 'default_time': { 'start': '18:00:00', 'end': '20:00' }, 'sessions': [ { 'title': 'A self-study session', 'slug': 'undated-session', }, ], }, version=(0, 3), ) course = model.courses['courses/test'] assert course.timezone is None assert course.sessions['undated-session'].date is None assert course.sessions['undated-session'].time is None
def test_invalid_default_time(model, key): with pytest.raises((jsonschema.ValidationError, ValueError)): add_test_course( model, 'courses/invalid', { 'title': 'Bad course', 'default_time': BAD_TIMES[key], 'sessions': [], })
def test_add_course_from_data(): model = models.Root() add_test_course(model, 'courses/minimal', { 'title': 'A minimal course', 'sessions': [], }) assert sorted(model.courses) == ['courses/minimal'] assert model.courses['courses/minimal'].title == 'A minimal course' assert model.courses['courses/minimal'].slug == 'courses/minimal'
def test_nonexisting_derives(model): """Test that nonexisting derives fails quietly""" add_test_course(model, 'courses/bad-derives', { 'title': 'A course derived from nothing', 'sessions': [], 'derives': 'nonexisting' }) course = model.courses['courses/bad-derives'] assert course.derives == 'nonexisting' assert course.base_course is None
def test_derives(model): """Test that derives and base_course is set correctly""" add_test_course(model, 'courses/base', { 'title': 'A base course', 'sessions': [], }) add_test_course(model, 'courses/derived', { 'title': 'A derived course', 'sessions': [], 'derives': 'base' }) base = model.courses['courses/base'] derived = model.courses['courses/derived'] assert derived.derives == 'base' assert derived.base_course is base
def test_course_without_dates(model, assert_model_dump): add_test_course( model, 'courses/without-dates', { 'title': 'A plain vanilla course', 'sessions': [ { 'title': 'A normal session', 'slug': 'normal-session', }, ], }) course = model.courses['courses/without-dates'] assert course.default_time is None session = course.sessions['normal-session'] assert session.date is None assert session.time is None assert_model_dump(course, 'session-times/without-dates')
def test_run_with_default_times(model, assert_model_dump): add_test_course( model, 'courses/with-default-times', { 'title': 'Test course with default times', 'default_time': { 'start': '19:00', 'end': '21:00' }, 'sessions': SESSIONS, }) course = model.courses['courses/with-default-times'] assert course.default_time == { 'start': datetime.time(19, 00, tzinfo=TZINFO), 'end': datetime.time(21, 00, tzinfo=TZINFO), } session = course.sessions['normal-session'] assert session.date == datetime.date(2000, 1, 1) assert session.time == { 'start': datetime.datetime(2000, 1, 1, 19, tzinfo=TZINFO), 'end': datetime.datetime(2000, 1, 1, 21, tzinfo=TZINFO), } session = course.sessions['afterparty'] assert session.date == datetime.date(2000, 1, 1) assert session.time == { 'start': datetime.datetime(2000, 1, 1, 22, tzinfo=TZINFO), 'end': datetime.datetime(2000, 1, 1, 23, tzinfo=TZINFO), } session = course.sessions['self-study'] assert session.date == None assert session.time == None session = course.sessions['morning-meditation'] assert session.date == None assert session.time == None assert_model_dump(course, 'session-times/with-default-times')
def test_course_api02_fails_without_timezone(model): """Time without a timezone is not allowed in API 0.3+""" with pytest.raises(ValueError): add_test_course( model, 'courses/test', { 'title': 'Test course', 'default_time': { 'start': '18:00', 'end': '20:00' }, 'sessions': [ { 'title': 'A session with a date', 'slug': 'dated-session', 'date': '2019-01-01', }, ], }, version=(0, 3), )
def test_run_years(model): assert model.run_years == {} # Add a self-study course. It should not appear in run_years. add_test_course(model, 'courses/minimal', { 'title': 'A minimal course', 'sessions': [], }) assert model.run_years == {} assert sorted(model.courses) == ['courses/minimal'] assert sorted(model.self_study_courses) == ['courses/minimal'] course_minimal = model.courses['courses/minimal'] assert course_minimal.start_date == None assert course_minimal.end_date == None # Add a course with a single session. It should appear in its run_year. add_test_course( model, '2019/single-session', { 'title': 'A course with a single session', 'sessions': [ { 'title': 'One session', 'slug': 'foo', 'date': '2019-01-05', 'materials': [], }, ], }) assert sorted(model.courses) == ['2019/single-session', 'courses/minimal'] assert sorted(model.self_study_courses) == ['courses/minimal'] course_2019 = model.courses['2019/single-session'] assert course_2019.start_date.year == 2019 assert course_2019.end_date.year == 2019 assert sorted(model.run_years) == [2019] assert model.run_years[2019] == {'2019/single-session': course_2019} # Add a course spanning 3 years. Should appear in all run_years it spans. # (Even if there are no sessions that year.) add_test_course( model, '2017/multi-year', { 'title': 'A course with sessions in years 2017 and 2019', 'sessions': [ { 'title': 'First session, 2017', 'slug': 'one', 'date': '2017-01-05', 'materials': [], }, { 'title': 'Last session, 2019', 'slug': 'two', 'date': '2019-01-05', 'materials': [], }, ], }) assert sorted(model.courses) == [ '2017/multi-year', '2019/single-session', 'courses/minimal', ] assert sorted(model.self_study_courses) == ['courses/minimal'] course_2017 = model.courses['2017/multi-year'] assert course_2017.start_date.year == 2017 assert course_2017.end_date.year == 2019 assert sorted(model.run_years) == [2017, 2018, 2019] for year in 2017, 2018: assert model.run_years[year] == {'2017/multi-year': course_2017} assert model.run_years[2019] == { '2017/multi-year': course_2017, '2019/single-session': course_2019, } assert_yaml_dump(models.dump(model), 'run-years/root.yml') for year, run_year in model.run_years.items(): assert_yaml_dump(models.dump(run_year), f'run-years/{year}.yml')
def empty_course(model): add_test_course(model, 'courses/minimal', { 'title': 'A minimal course', 'sessions': [], }) return model.courses['courses/minimal']