Skip to content

Release Teacher 2.4.0 (88)#3513

Merged
kristofnemere merged 4 commits intomasterfrom
release/teacher
Feb 6, 2026
Merged

Release Teacher 2.4.0 (88)#3513
kristofnemere merged 4 commits intomasterfrom
release/teacher

Conversation

@kristofnemere
Copy link
Contributor

No description provided.

@github-actions
Copy link

github-actions bot commented Feb 6, 2026

🧪 Unit Test Results


📊 Summary

  • Total Tests: 0
  • Failed: 0
  • Skipped: 0
  • Status: ⚠️ No test results found

Last updated: Fri, 06 Feb 2026 07:37:18 GMT

Copy link

@claude claude bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

This PR adds LTI routing improvements and excludes certain E2E tests from release builds. Overall the changes look reasonable, but there are some concerns to address.

Issues Found

  • Debug logging in production code (RouteMatcher.kt:332) - Remove or conditionally compile debug log statement
  • Duplicated sessionless_launch logic (RouteMatcher.kt:491 and LtiLaunchFragment.kt:180) - Extract to shared utility for consistency
  • Fragile URL string matching (LtiLaunchViewModel.kt:125) - Use proper URL parsing instead of substring matching for session_token detection
  • Missing error logging (RouteMatcher.kt:506) - Add logging when falling back to handleWebViewUrl for debugging
  • Potential null safety issue (RouteMatcher.kt:496-506) - Consider early return when contextId cannot be determined

Positive Aspects

✅ Good addition of @ReleaseExclude annotation to prevent problematic E2E tests from running in release builds
✅ Version bump is properly applied (versionCode 88, versionName 2.4.0)
✅ The LTI routing logic follows a clear separation of concerns
✅ The sessionless_launch URL handling prevents infinite routing loops, which is a good defensive practice

Recommendations

  1. Add test coverage: The new LTI routing logic in handleLtiRoute() needs unit tests, especially for edge cases (missing context, invalid URLs, etc.)
  2. Document the sessionless_launch behavior: Add comments explaining why these URLs are special and need to be excluded from internal routing
  3. Consider URL parsing utilities: Replace string contains checks with proper URL parsing (e.g., using Uri.parse() and checking query parameters)
  4. Review logging strategy: Ensure debug logs are either removed or wrapped in build config checks for production

The core functionality looks solid, but addressing the code quality and maintainability issues will help prevent future bugs.

@@ -329,6 +330,7 @@ object RouteMatcher : BaseRouteMatcher() {

fun route(activity: FragmentActivity, route: Route?) {
val uri = route?.uri
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider removing this debug logging statement before merging to production. Debug logs with detailed routing information can clutter logs and potentially expose sensitive information in production builds.

return
}

// Don't intercept sessionless_launch URLs - they're already being handled by an existing LtiLaunchFragment
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says "Don't intercept sessionless_launch URLs" but this check might be too broad. Consider whether this should be more specific (e.g., checking for the full path pattern rather than just substring matching). Also, this logic appears duplicated in LtiLaunchFragment.kt:180 - consider extracting to a shared utility function to maintain consistency.

Comment on lines +496 to +506

val contextId = route.paramsHash[RouterParams.COURSE_ID]?.toLongOrNull()
?: route.paramsHash[RouterParams.GROUP_ID]?.toLongOrNull()

val canvasContext: CanvasContext? = when (route.getContextType()) {
CanvasContext.Type.COURSE -> contextId?.let { Course(id = it) }
CanvasContext.Type.GROUP -> contextId?.let { Group(id = it) }
else -> null
}

if (canvasContext != null) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a potential null safety issue here. If contextId is null and both conditions fail, the function continues to check canvasContext != null, which will always be null in that case. Consider early return or better error handling when the context cannot be determined. Also, consider logging when falling back to handleWebViewUrl so debugging is easier.

private fun launchLti(url: String) {
viewModelScope.launch {
val authenticatedUrl = repository.authenticateUrl(url)
val authenticatedUrl = if (url.contains("session_token")) url else repository.authenticateUrl(url)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This conditional authentication logic could be problematic. The check if (url.contains("session_token")) is a simple substring match which could produce false positives. Consider:

  1. Using a more robust URL parsing approach (checking query parameters specifically)
  2. Adding a comment explaining why URLs with session_token should skip authentication
  3. Adding test coverage for this behavior to prevent regressions

Comment on lines 179 to +181
private fun canRouteInternally(url: String) =
webViewRouter.canRouteInternally(url) && ltiUrl?.substringBefore("?") != url.substringBefore("?")
webViewRouter.canRouteInternally(url)
&& ltiUrl?.substringBefore("?") != url.substringBefore("?")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same sessionless_launch check as in RouteMatcher.kt:491. This duplication suggests these classes are making routing decisions independently. Consider:

  1. Extracting the sessionless_launch detection to a shared utility
  2. Documenting why sessionless_launch URLs need special handling
  3. Ensuring both checks remain synchronized if the logic needs to change

@github-actions
Copy link

github-actions bot commented Feb 6, 2026

📊 Code Coverage Report

✅ Student

  • PR Coverage: 43.27%
  • Master Coverage: 43.27%
  • Delta: +0.00%

⚠️ Teacher

  • PR Coverage: 25.38%
  • Master Coverage: 25.47%
  • Delta: -0.09%

✅ Pandautils

  • PR Coverage: 23.01%
  • Master Coverage: 23.01%
  • Delta: +0.00%

📈 Overall Average

  • PR Coverage: 30.55%
  • Master Coverage: 30.58%
  • Delta: -0.03%

@kristofnemere kristofnemere merged commit 83ad09c into master Feb 6, 2026
35 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants