Skip to content

Commit

Permalink
Merge pull request #2374 from instructure/release/student-7.2.0-260
Browse files Browse the repository at this point in the history
Release Student 7.2.0 (260)
  • Loading branch information
hermannakos authored Mar 18, 2024
2 parents bd6ec42 + 6407308 commit b07d64f
Show file tree
Hide file tree
Showing 342 changed files with 19,796 additions and 2,973 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<intent-filter android:autoVerify="true">
<data android:scheme="https" />
<data android:scheme="http" />
<data android:host="*.instructure.com" />
Expand Down
7 changes: 5 additions & 2 deletions apps/flutter_parent/lib/screens/courses/courses_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,14 @@ class _CoursesScreenState extends State<CoursesScreen> {
// If there is no current grade, return 'No grade'
// Otherwise, we have a grade, so check if we have the actual grade string
// or a score
var formattedScore = (grade.currentScore() != null && !(course.settings?.restrictQuantitativeData ?? false))
? format.format(grade.currentScore()! / 100)
: '';
var text = grade.noCurrentGrade()
? L10n(context).noGrade
: grade.currentGrade()?.isNotEmpty == true
? grade.currentGrade()!
: format.format(grade.currentScore()! / 100);
? "${grade.currentGrade()}${formattedScore.isNotEmpty ? ' $formattedScore' : ''}"
: formattedScore;

return Text(
text,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,22 +255,25 @@ class _CourseGradeHeader extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(L10n(context).courseTotalGradeLabel, style: textTheme.bodyMedium),
Text(_courseGrade(context, grade), style: textTheme.bodyMedium, key: Key("total_grade")),
Text(_courseGrade(context, grade, model.courseSettings?.restrictQuantitativeData ?? false), style: textTheme.bodyMedium, key: Key("total_grade")),
],
),
);
}

String _courseGrade(BuildContext context, CourseGrade grade) {
String _courseGrade(BuildContext context, CourseGrade grade, bool restrictQuantitativeData) {
final format = NumberFormat.percentPattern();
format.maximumFractionDigits = 2;

if (grade.noCurrentGrade()) {
return L10n(context).noGrade;
} else {
var formattedScore = (grade.currentScore() != null && restrictQuantitativeData == false)
? format.format(grade.currentScore()! / 100)
: '';
return grade.currentGrade()?.isNotEmpty == true
? grade.currentGrade()!
: format.format(grade.currentScore()! / 100); // format multiplies by 100 for percentages
? "${grade.currentGrade()}${formattedScore.isNotEmpty ? ' $formattedScore' : ''}"
: formattedScore;
}
}
}
Expand Down Expand Up @@ -375,7 +378,7 @@ class _AssignmentRow extends StatelessWidget {

final submission = assignment.submission(studentId);

final restrictQuantitativeData = course?.settings?.restrictQuantitativeData ?? false;
final restrictQuantitativeData = course.settings?.restrictQuantitativeData ?? false;

if (submission?.excused ?? false) {
text = restrictQuantitativeData
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,30 @@ void main() {
expect(find.text(grade), findsOneWidget);
});

testWidgetsWithAccessibilityChecks('from current grade and score', (tester) async {
final grade = 'Big fat F';
final score = 15.15;
final groups = [
_mockAssignmentGroup(assignments: [_mockAssignment()])
];
final enrollment = Enrollment((b) => b
..enrollmentState = 'active'
..grades = _mockGrade(currentScore: score, currentGrade: grade));
final model = CourseDetailsModel(_student, _courseId);
model.course = _mockCourse();
when(interactor.loadAssignmentGroups(_courseId, _studentId, null)).thenAnswer((_) async => groups);
when(interactor.loadGradingPeriods(_courseId)).thenAnswer((_) async =>
GradingPeriodResponse((b) => b..gradingPeriods = BuiltList.of(<GradingPeriod>[]).toBuilder()));
when(interactor.loadEnrollmentsForGradingPeriod(_courseId, _studentId, null))
.thenAnswer((_) async => [enrollment]);

await tester.pumpWidget(_testableWidget(model));
await tester.pump(); // Build the widget
await tester.pump(); // Let the future finish

expect(find.text("$grade $score%"), findsOneWidget);
});

testWidgetsWithAccessibilityChecks('is not shown when locked', (tester) async {
final groups = [
_mockAssignmentGroup(assignments: [_mockAssignment()])
Expand Down Expand Up @@ -497,6 +521,31 @@ void main() {
expect(find.text(grade), findsOneWidget);
});

testWidgetsWithAccessibilityChecks('only grade is shown when restricted', (tester) async {
final grade = 'Big fat F';
final score = 15.15;
final groups = [
_mockAssignmentGroup(assignments: [_mockAssignment()])
];
final enrollment = Enrollment((b) => b
..enrollmentState = 'active'
..grades = _mockGrade(currentScore: score, currentGrade: grade));
final model = CourseDetailsModel(_student, _courseId);
model.course = _mockCourse();
model.courseSettings = CourseSettings((b) => b..restrictQuantitativeData = true);
when(interactor.loadAssignmentGroups(_courseId, _studentId, null)).thenAnswer((_) async => groups);
when(interactor.loadGradingPeriods(_courseId))
.thenAnswer((_) async => GradingPeriodResponse((b) => b..gradingPeriods = BuiltList.of(<GradingPeriod>[]).toBuilder()));
when(interactor.loadEnrollmentsForGradingPeriod(_courseId, _studentId, null)).thenAnswer((_) async => [enrollment]);

await tester.pumpWidget(_testableWidget(model));
await tester.pump(); // Build the widget
await tester.pump(); // Let the future finish

// Verify that we are showing the course grade when restricted
expect(find.text(grade), findsOneWidget);
});

testWidgetsWithAccessibilityChecks('is shown when looking at a grading period', (tester) async {
final groups = [
_mockAssignmentGroup(assignments: [_mockAssignment()])
Expand Down Expand Up @@ -780,7 +829,7 @@ Course _mockCourse() {
GradeBuilder _mockGrade({double? currentScore, double? finalScore, String? currentGrade, String? finalGrade}) {
return GradeBuilder()
..htmlUrl = ''
..currentScore = currentScore ?? 0
..currentScore = currentScore
..finalScore = finalScore ?? 0
..currentGrade = currentGrade ?? ''
..finalGrade = finalGrade ?? '';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ import 'package:provider/provider.dart';
import '../../utils/accessibility_utils.dart';
import '../../utils/platform_config.dart';
import '../../utils/test_app.dart';
import '../../utils/test_helpers/mock_helpers.dart';
import '../../utils/test_helpers/mock_helpers.mocks.dart';

void main() {
Expand Down Expand Up @@ -174,6 +173,48 @@ void main() {
expect(gradeWidget, findsNWidgets(courses.length));
});

testWidgetsWithAccessibilityChecks('shows grade and score if there is a current grade and score', (tester) async {
var student = _mockStudent('1');
var courses = List.generate(
1,
(idx) => _mockCourse(
idx.toString(),
enrollments: ListBuilder<Enrollment>(
[_mockEnrollment(idx.toString(), userId: student.id, computedCurrentGrade: 'A', computedCurrentScore: 75)],
),
),
);

_setupLocator(_MockedCoursesInteractor(courses: courses));

await tester.pumpWidget(_testableMaterialWidget());
await tester.pumpAndSettle();

final gradeWidget = find.text('A 75%');
expect(gradeWidget, findsNWidgets(courses.length));
});

testWidgetsWithAccessibilityChecks('shows grade only if there is a current grade and score and restricted', (tester) async {
var student = _mockStudent('1');
var courses = List.generate(
1,
(idx) => _mockCourse(
idx.toString(),
enrollments: ListBuilder<Enrollment>(
[_mockEnrollment(idx.toString(), userId: student.id, computedCurrentGrade: 'A', computedCurrentScore: 75)],
),
).rebuild((b) => b..settings = (b.settings..restrictQuantitativeData = true)),
);

_setupLocator(_MockedCoursesInteractor(courses: courses));

await tester.pumpWidget(_testableMaterialWidget());
await tester.pumpAndSettle();

final gradeWidget = find.text('A');
expect(gradeWidget, findsNWidgets(courses.length));
});

testWidgetsWithAccessibilityChecks('shows score if there is a grade but no grade string', (tester) async {
var student = _mockStudent('1');
var courses = List.generate(
Expand Down
17 changes: 15 additions & 2 deletions apps/settings.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
pluginManagement {
buildscript {
repositories {
mavenCentral()
maven {
url = uri("https://storage.googleapis.com/r8-releases/raw")
}
}
dependencies {
classpath("com.android.tools:r8:8.2.47")
}
}
}

/* Top-level project modules */
include ':student'
include ':teacher'

/* Flutter embed modules */
setBinding(new Binding([gradle: this]))

Expand Down Expand Up @@ -36,4 +49,4 @@ project(':pandautils').projectDir = new File(rootProject.projectDir, '/../libs/p
project(':rceditor').projectDir = new File(rootProject.projectDir, '/../libs/rceditor')
project(':recyclerview').projectDir = new File(rootProject.projectDir, '/../libs/recyclerview')
project(':pandares').projectDir = new File(rootProject.projectDir, '/../libs/pandares')
project(':DocumentScanner').projectDir = new File(rootProject.projectDir, '/../libs/DocumentScanner')
project(':DocumentScanner').projectDir = new File(rootProject.projectDir, '/../libs/DocumentScanner')
15 changes: 13 additions & 2 deletions apps/student/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ android {
applicationId "com.instructure.candroid"
minSdkVersion Versions.MIN_SDK
targetSdkVersion Versions.TARGET_SDK
versionCode = 259
versionName = '7.1.0'
versionCode = 260
versionName = '7.2.0'

vectorDrawables.useSupportLibrary = true
multiDexEnabled = true
Expand Down Expand Up @@ -128,6 +128,14 @@ android {
}
}

debugMinify {
initWith debug
debuggable false
minifyEnabled true
shrinkResources true
matchingFallbacks = ['debug']
}

release {
signingConfig signingConfigs.release
debuggable false
Expand Down Expand Up @@ -240,6 +248,7 @@ android {
hilt {
enableTransformForLocalTests = true
enableAggregatingTask = false
enableExperimentalClasspathAggregation = true
}
}

Expand Down Expand Up @@ -350,6 +359,8 @@ dependencies {
implementation Libs.ROOM_COROUTINES

testImplementation Libs.HAMCREST

androidTestImplementation Libs.COMPOSE_UI_TEST
}

// Comment out this line if the reporting logic starts going wonky.
Expand Down
4 changes: 2 additions & 2 deletions apps/student/flank.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
gcloud:
project: delta-essence-114723
# Use the next two lines to run locally
# app: ./build/outputs/apk/qa/debug/student-qa-debug.apk
# test: ./build/outputs/apk/androidTest/qa/debug/student-qa-debug-androidTest.apk
# app: ./build/intermediates/apk/qa/debug/student-qa-debug.apk
# test: ./build/intermediates/apk/androidTest/qa/debug/student-qa-debug-androidTest.apk
app: ./apps/student/build/outputs/apk/qa/debug/student-qa-debug.apk
test: ./apps/student/build/outputs/apk/androidTest/qa/debug/student-qa-debug-androidTest.apk
results-bucket: android-student
Expand Down
6 changes: 3 additions & 3 deletions apps/student/flank_coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ gcloud:
directories-to-pull:
- /sdcard/
test-targets:
- notAnnotation com.instructure.canvas.espresso.E2E, com.instructure.canvas.espresso.Stub
- notAnnotation com.instructure.canvas.espresso.E2E, com.instructure.canvas.espresso.OfflineE2E, com.instructure.canvas.espresso.Stub, com.instructure.canvas.espresso.StubCoverage
device:
- model: NexusLowRes
version: 26
- model: Pixel2.arm
version: 29
locale: en_US
orientation: portrait

Expand Down
8 changes: 4 additions & 4 deletions apps/student/flank_e2e_coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ gcloud:
directories-to-pull:
- /sdcard/
test-targets:
- annotation com.instructure.canvas.espresso.E2E
- notAnnotation com.instructure.canvas.espresso.Stub
- annotation com.instructure.canvas.espresso.E2E, com.instructure.canvas.espresso.OfflineE2E
- notAnnotation com.instructure.canvas.espresso.Stub, com.instructure.canvas.espresso.StubCoverage
device:
- model: Nexus6P
version: 26
- model: Pixel2.arm
version: 29
locale: en_US
orientation: portrait

Expand Down
2 changes: 1 addition & 1 deletion apps/student/flank_e2e_offline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ gcloud:
orientation: portrait

flank:
testShards: 1
testShards: 10
testRuns: 1

Loading

0 comments on commit b07d64f

Please sign in to comment.