Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically select next weekday in homework dialog. #1136

Merged
merged 1 commit into from
Oct 27, 2023
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
15 changes: 14 additions & 1 deletion app/lib/homework/homework_dialog/homework_dialog_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
import 'package:analytics/analytics.dart';
import 'package:bloc/bloc.dart';
import 'package:bloc_presentation/bloc_presentation.dart';
import 'package:clock/clock.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:common_domain_models/common_domain_models.dart';
import 'package:date/date.dart';
import 'package:date/weekday.dart';
import 'package:equatable/equatable.dart';
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
import 'package:files_basics/files_models.dart';
Expand Down Expand Up @@ -372,6 +374,7 @@ class HomeworkDialogBloc extends Bloc<HomeworkDialogEvent, HomeworkDialogState>
final Analytics analytics;
final MarkdownAnalytics markdownAnalytics;
final NextLessonCalculator nextLessonCalculator;
final Clock _clock;
HomeworkDto? _initialHomework;
late final IList<CloudFile> _initialAttachments;
late final bool isEditing;
Expand Down Expand Up @@ -402,8 +405,10 @@ class HomeworkDialogBloc extends Bloc<HomeworkDialogEvent, HomeworkDialogState>
required this.nextLessonCalculator,
required this.analytics,
required this.markdownAnalytics,
Clock? clock,
HomeworkId? homeworkId,
}) : super(homeworkId != null
}) : _clock = clock ?? const Clock(),
super(homeworkId != null
? LoadingHomework(homeworkId, isEditing: true)
: emptyCreateHomeworkDialogState) {
isEditing = homeworkId != null;
Expand Down Expand Up @@ -574,6 +579,14 @@ class HomeworkDialogBloc extends Bloc<HomeworkDialogEvent, HomeworkDialogState>
await nextLessonCalculator.tryCalculateNextLesson(course.id);
if (nextLesson != null) {
add(DueDateChanged(nextLesson));
} else {
final today = _clock.now().toDate();
final daysUntilNextSchoolday = switch (today.weekDayEnum) {
WeekDay.friday => 3, // Monday
WeekDay.saturday => 2, // Monday
_ => 1 // Tomorrow
};
add(DueDateChanged(today.addDays(daysUntilNextSchoolday)));
}
},
);
Expand Down
66 changes: 40 additions & 26 deletions app/test/homework/homework_dialog_bloc_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'dart:io';
import 'dart:typed_data';

import 'package:analytics/analytics.dart';
import 'package:clock/clock.dart';
import 'package:common_domain_models/common_domain_models.dart';
import 'package:date/date.dart';
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
Expand All @@ -21,7 +22,6 @@ import 'package:mockito/mockito.dart';
import 'package:rxdart/rxdart.dart';
import 'package:sharezone/homework/homework_dialog/homework_dialog_bloc.dart';
import 'package:sharezone/markdown/markdown_analytics.dart';
import 'package:sharezone/util/next_lesson_calculator/next_lesson_calculator.dart';
import 'package:time/time.dart';

import '../analytics/analytics_test.dart';
Expand All @@ -44,9 +44,10 @@ void main() {
analytics = Analytics(analyticsBackend);
});

HomeworkDialogBloc createBlocForNewHomeworkDialog() {
HomeworkDialogBloc createBlocForNewHomeworkDialog({Clock? clock}) {
return HomeworkDialogBloc(
api: homeworkDialogApi,
clock: clock,
nextLessonCalculator: nextLessonCalculator,
analytics: analytics,
markdownAnalytics: MarkdownAnalytics(analytics),
Expand All @@ -69,6 +70,43 @@ void main() {
homeworkDialogApi.addCourseForTesting(course);
}

test('If no next lesson date is found the next weekday will be taken',
() async {
Future<void> testNextLessonDate(
String currentDate, String expectedLessonDate) async {
// The course does not have any lessons in the timetable, so we fallback
// to automatically using the next schoolday. We currently assume that
// all users have schooldays from Monday to Friday. We also don't take
// holidays into account.
nextLessonCalculator.dateToReturn = null;
final testClock = Clock.fixed(Date.parse(currentDate).toDateTime);
addCourse(courseWith(id: 'foo'));
final bloc = createBlocForNewHomeworkDialog(clock: testClock);

bloc.add(CourseChanged(CourseId('foo')));
await pumpEventQueue();

final state = bloc.state as Ready;
expect(state.dueDate.$1, Date.parse(expectedLessonDate));
}

// | Current date | Next lesson date |
// Friday Monday
await testNextLessonDate('2023-10-06', '2023-10-09');
// Saturday Monday
await testNextLessonDate('2023-10-07', '2023-10-09');
// Sunday Monday
await testNextLessonDate('2023-10-08', '2023-10-09');
// Monday Tuesday
await testNextLessonDate('2023-10-09', '2023-10-10');
// Tuesday Wednesday
await testNextLessonDate('2023-10-10', '2023-10-11');
// Wednesday Thursday
await testNextLessonDate('2023-10-11', '2023-10-12');
// Thursday Friday
await testNextLessonDate('2023-10-12', '2023-10-13');
});

test(
'Shows error if title is not filled out when creating a new homework and Save is called',
() async {
Expand Down Expand Up @@ -212,30 +250,6 @@ void main() {
.firstWhere((element) => element.dueDate.$1 != null);
expect(state.dueDate.$1, nextLessonDate);
});
test(
'leaves due date as not selected if null is returned by $NextLessonCalculator',
() async {
final bloc = createBlocForNewHomeworkDialog();
addCourse(courseWith(
id: 'foo_course',
));

bloc.add(CourseChanged(CourseId('foo_course')));

nextLessonCalculator.dateToReturn = null;
await bloc.stream
.whereType<Ready>()
.firstWhere((element) => element.course is CourseChosen);

// Make sure that we wait for the due date to be set (might be delayed,
// after the course is set and returned by the view)
await pumpEventQueue(times: 100);
await Future.delayed(Duration.zero);
await pumpEventQueue(times: 100);

final state = bloc.state as Ready;
expect(state.dueDate.$1, null);
});
test('Returns empty dialog when called for creating a new homework', () {
final bloc = createBlocForNewHomeworkDialog();
expect(bloc.state, emptyCreateHomeworkDialogState);
Expand Down
6 changes: 6 additions & 0 deletions lib/date/lib/src/date.dart
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ class Date {
}
}

extension DateTimeToDate on DateTime {
Date toDate() {
return Date.fromDateTime(this);
}
}

class DateParser {
final Date _date;

Expand Down
Loading