Skip to content

Usability: Render IDE Preferences only once the saved IDE has loaded#13133

Open
az108 wants to merge 1 commit into
developfrom
bugfix/usability/ide-preferences-selection-flash
Open

Usability: Render IDE Preferences only once the saved IDE has loaded#13133
az108 wants to merge 1 commit into
developfrom
bugfix/usability/ide-preferences-selection-flash

Conversation

@az108

@az108 az108 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Summary

When opening Settings → IDE Preferences, the selected-IDE highlight briefly appeared on VS Code and then jumped to the actually saved IDE once the data finished loading (only noticeable when the saved IDE was not VS Code). The component seeded a hardcoded VS Code default and loaded the predefined IDE list and the saved preferences asynchronously, so the wrong selection was rendered until those loads completed. This PR waits for both loads and only then renders the IDE button rows, so the correct selection is shown from the start.

Checklist

General

Client

Motivation and Context

Closes #13127.

Rendering a placeholder selection and then jumping to the real one looks like a glitch and is briefly misleading about which IDE is configured.

Description

  • IdeSettingsComponent.ngOnInit now loads the predefined IDEs (loadPredefinedIdes) and the saved preferences (loadIdePreferences) together via Promise.all, then sets all state at once and finally clears an isLoading flag. Previously these were two independent async paths that updated the view separately.
  • The template now shows a small spinner while isLoading() is true and only renders the IDE button rows afterwards, so the correct selection is displayed from the first paint (no VS Code flash / jump).
  • Updated the existing init test to await ngOnInit() and assert isLoading transitions true → false.

Steps for Testing

Prerequisites:

  • A user account
  1. Open Settings → IDE Preferences and set the default IDE to something other than VS Code (e.g. IntelliJ), then save.
  2. Navigate away and open IDE Preferences again.
  3. Confirm the saved IDE is shown as selected immediately, with no VS Code flash / jump (a brief spinner may appear while loading).
  4. Confirm adding/removing a programming language and changing an IDE still works.

Screenshots

To be added.

Summary by CodeRabbit

  • New Features

    • The IDE preferences screen now shows a loading spinner while preferences are being loaded.
    • Existing preference options appear only after the page finishes initializing, reducing flicker and partial content.
  • Bug Fixes

    • Improved the reliability of the IDE preferences page so saved languages and available options load together.
    • Ensured the default language entry is always available when preferences are displayed.

The IDE Preferences page seeded a VS Code default and loaded the predefined
IDEs and saved preferences asynchronously, so when the saved IDE was not
VS Code the selection first showed VS Code and then jumped. Load both in
parallel and gate the IDE button rows behind a loading state so the correct
selection renders from the start.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@az108 az108 requested a review from krusche as a code owner July 5, 2026 10:28
@github-project-automation github-project-automation Bot moved this to Work In Progress in Artemis Development Jul 5, 2026
@github-actions github-actions Bot added client Pull requests that update TypeScript code. (Added Automatically!) account Pull requests that affect the corresponding module labels Jul 5, 2026
@az108 az108 temporarily deployed to playwright-e2e-tests July 5, 2026 10:34 — with GitHub Actions Inactive
@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

IdeSettingsComponent now tracks an isLoading signal, converting ngOnInit to an async method that loads predefined IDEs and saved preferences concurrently via Promise.all, setting isLoading false in a finally block. The template conditionally shows a spinner while loading; tests updated accordingly.

Changes

IDE Preferences Loading State

Layer / File(s) Summary
Component async init and loading signal
src/main/webapp/app/account/user/settings/ide-preferences/ide-settings.component.ts
Adds isLoading signal and faSpinner field, imports firstValueFrom, converts ngOnInit to async loading predefined IDEs and preferences via Promise.all, ensures EMPTY language maps to first predefined IDE, and sets isLoading false in finally.
Template spinner conditional rendering
src/main/webapp/app/account/user/settings/ide-preferences/ide-settings.component.html
Wraps existing list-group UI in @else, showing a spinner via @if (isLoading()) while data loads.
Test coverage for loading lifecycle
src/main/webapp/app/account/user/settings/ide-preferences/ide-settings.component.spec.ts
Updates initialization test to assert isLoading() is true before ngOnInit, awaits async ngOnInit, and asserts isLoading() is false after both loads resolve.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested labels: tests

Suggested reviewers: Claudia-Anthropica

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main UX change: delaying IDE Preferences rendering until the saved IDE loads.
Linked Issues check ✅ Passed The changes address the reported VS Code flash by loading data together and showing a spinner until initialization finishes.
Out of Scope Changes check ✅ Passed The PR stays focused on the IDE Preferences loading-state fix and its test update, with no unrelated changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bugfix/usability/ide-preferences-selection-flash

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/main/webapp/app/account/user/settings/ide-preferences/ide-settings.component.spec.ts (1)

68-69: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding a failure-path test.

No test verifies isLoading resets to false (via the finally block) when either load rejects. Given the missing catch in the component, such a test would surface the unhandled-rejection behavior directly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/webapp/app/account/user/settings/ide-preferences/ide-settings.component.spec.ts`
around lines 68 - 69, Add a failure-path spec for the IDE settings component
that verifies ide preferences loading clears isLoading back to false when either
async load rejects. Use the existing ide-settings.component.spec.ts setup and
the component’s isLoading state, and exercise the load path so the finally
behavior is covered even without a catch, surfacing the rejection handling issue
directly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/main/webapp/app/account/user/settings/ide-preferences/ide-settings.component.ts`:
- Around line 60-62: The ProgrammingLanguage.EMPTY fallback in
ide-settings.component.ts can be seeded with undefined when predefinedIdes is
empty. Update the initialization around programmingLanguageToIdeMap and
ProgrammingLanguage.EMPTY to first check that predefinedIdes has at least one
entry before calling set, and otherwise skip the fallback or handle the empty
state explicitly.

---

Nitpick comments:
In
`@src/main/webapp/app/account/user/settings/ide-preferences/ide-settings.component.spec.ts`:
- Around line 68-69: Add a failure-path spec for the IDE settings component that
verifies ide preferences loading clears isLoading back to false when either
async load rejects. Use the existing ide-settings.component.spec.ts setup and
the component’s isLoading state, and exercise the load path so the finally
behavior is covered even without a catch, surfacing the rejection handling issue
directly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 986bcdc4-56a9-4742-b6e7-4ed0348858eb

📥 Commits

Reviewing files that changed from the base of the PR and between 1cc9fac and 57d241e.

📒 Files selected for processing (3)
  • src/main/webapp/app/account/user/settings/ide-preferences/ide-settings.component.html
  • src/main/webapp/app/account/user/settings/ide-preferences/ide-settings.component.spec.ts
  • src/main/webapp/app/account/user/settings/ide-preferences/ide-settings.component.ts

Comment on lines 60 to 62
if (!programmingLanguageToIdeMap.has(ProgrammingLanguage.EMPTY)) {
programmingLanguageToIdeMap.set(ProgrammingLanguage.EMPTY, this.PREDEFINED_IDE()[0]);
programmingLanguageToIdeMap.set(ProgrammingLanguage.EMPTY, predefinedIdes[0]);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Guard against an empty predefinedIdes array.

If the backend ever returns an empty list, predefinedIdes[0] is undefined, silently seeding ProgrammingLanguage.EMPTY with an invalid IDE entry.

🛡️ Proposed guard
-            if (!programmingLanguageToIdeMap.has(ProgrammingLanguage.EMPTY)) {
+            if (!programmingLanguageToIdeMap.has(ProgrammingLanguage.EMPTY) && predefinedIdes.length > 0) {
                 programmingLanguageToIdeMap.set(ProgrammingLanguage.EMPTY, predefinedIdes[0]);
             }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!programmingLanguageToIdeMap.has(ProgrammingLanguage.EMPTY)) {
programmingLanguageToIdeMap.set(ProgrammingLanguage.EMPTY, this.PREDEFINED_IDE()[0]);
programmingLanguageToIdeMap.set(ProgrammingLanguage.EMPTY, predefinedIdes[0]);
}
if (!programmingLanguageToIdeMap.has(ProgrammingLanguage.EMPTY) && predefinedIdes.length > 0) {
programmingLanguageToIdeMap.set(ProgrammingLanguage.EMPTY, predefinedIdes[0]);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/webapp/app/account/user/settings/ide-preferences/ide-settings.component.ts`
around lines 60 - 62, The ProgrammingLanguage.EMPTY fallback in
ide-settings.component.ts can be seeded with undefined when predefinedIdes is
empty. Update the initialization around programmingLanguageToIdeMap and
ProgrammingLanguage.EMPTY to first check that predefinedIdes has at least one
entry before calling set, and otherwise skip the fallback or handle the empty
state explicitly.

@github-project-automation github-project-automation Bot moved this from Work In Progress to Ready For Review in Artemis Development Jul 5, 2026
@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown

End-to-End Test Results

Phase Status Details
Phase 1 (Relevant) ❌ Failed
TestsPassedSkippedFailed ❌️Time ⏱
Phase 1: E2E Test Report21 ran0 passed0 skipped21 failed14m 28s
Phase 2 (Remaining) ⏭ Skipped (no remaining tests)
❌ Failed Tests (Phase 1)
  • Login page tests › Logs in via the UI (2m 29s)
  • Login page tests › Logs in programmatically and logs out via the UI (2m 21s)
  • Login page tests › Displays error messages on wrong password (2m 29s)
  • Login page tests › Fails to access protected resource without login (2m 28s)
  • Login page tests › Verify footer content (24s)
  • Logout tests › Logs out after confirmation of dialog for unsaved changes on exercise mode (1m 43s)
  • Logout tests › Stays logged in after dismissal of dialog for unsaved changes on exercise mode (1m 43s)
  • Passkey › registers a passkey via the setup modal and displays it in user settings (2m 6s)
  • Passkey › renames a passkey in user settings (2m 0s)
  • Passkey › deletes a passkey in user settings (2m 0s)
  • Passkey › logs in with a registered passkey (2m 0s)
  • Passkey › conditional mediation login succeeds with a registered passkey (2m 0s)
  • Passkey › cannot login with a passkey after it was deleted (2m 1s)
  • Passkey reminder modal is not displayed on re-login after remind me in 30 days was chosen (2m 28s)
  • Check artemis system health › Checks continuous integration server health (13s)
  • Check artemis system health › Checks db health (13s)
  • Check artemis system health › Checks hazelcast health (13s)
  • Check artemis system health › Checks ping health (13s)
  • Check artemis system health › Checks readiness state health (13s)
  • Check artemis system health › Checks websocket broker health (13s)
  • Check artemis system health › Checks websocket connection health (2m 36s)

Flakiness Scores for Failed Tests

Test Flakiness Score Default Branch Failure Rate Combined Failure Rate
e2e/Login.spec.ts#Login page tests › Logs in via the UI 0% 0.6% 0.3%
e2e/Login.spec.ts#Login page tests › Logs in programmatically and logs out via the UI 0% 0.4% 0.2%
e2e/Login.spec.ts#Login page tests › Displays error messages on wrong password 0% 0.4% 0.2%
e2e/Login.spec.ts#Login page tests › Fails to access protected resource without login 68.27160493827161% 1.2% 0.4%
e2e/Login.spec.ts#Login page tests › Verify footer content 0% 0.3% 0.2%
e2e/Logout.spec.ts#Logout tests › Logs out after confirmation of dialog for unsaved changes on exercise mode 68.4045584045584% 1.1% 0.6%
e2e/Logout.spec.ts#Logout tests › Stays logged in after dismissal of dialog for unsaved changes on exercise mode 68.4045584045584% 1.1% 0.6%
e2e/Passkey.spec.ts#Passkey › registers a passkey via the setup modal and displays it in user settings 86.44078285758489% 7.5% 5.0%
e2e/Passkey.spec.ts#Passkey › renames a passkey in user settings 90.31484489827493% 5.4% 3.6%
e2e/Passkey.spec.ts#Passkey › deletes a passkey in user settings 90.31484489827493% 5.4% 3.6%
e2e/Passkey.spec.ts#Passkey › logs in with a registered passkey 88.37781387792991% 6.5% 4.3%
e2e/Passkey.spec.ts#Passkey › conditional mediation login succeeds with a registered passkey 68.4090909090909% 1.1% 0.7%
e2e/Passkey.spec.ts#Passkey › cannot login with a passkey after it was deleted 88.37781387792991% 6.5% 4.3%
e2e/PasskeyReminderPersistence.spec.ts#Passkey reminder modal is not displayed on re-login after remind me in 30 days was chosen 88.37781387792991% 6.5% 4.3%
e2e/SystemHealth.spec.ts#Check artemis system health › Checks continuous integration server health 0% 0.3% 0.4%
e2e/SystemHealth.spec.ts#Check artemis system health › Checks db health 0% 0.2% 0.4%
e2e/SystemHealth.spec.ts#Check artemis system health › Checks hazelcast health 0% 0.3% 0.4%
e2e/SystemHealth.spec.ts#Check artemis system health › Checks ping health 0% 0.2% 0.4%
e2e/SystemHealth.spec.ts#Check artemis system health › Checks readiness state health 0% 0.3% 0.4%
e2e/SystemHealth.spec.ts#Check artemis system health › Checks websocket broker health 0% 0.2% 0.4%
e2e/SystemHealth.spec.ts#Check artemis system health › Checks websocket connection health 0% 0.3% 0.8%

Test Strategy: Two-phase execution

  • Phase 1: e2e/Login.spec.ts e2e/Logout.spec.ts e2e/Passkey.spec.ts e2e/PasskeyReminderPersistence.spec.ts e2e/SystemHealth.spec.ts
  • Phase 2: e2e/admin/ e2e/atlas/ e2e/course/ e2e/exam/ExamAssessment.spec.ts e2e/exam/ExamChecklists.spec.ts e2e/exam/ExamCreationDeletion.spec.ts e2e/exam/ExamDateVerification.spec.ts e2e/exam/ExamManagement.spec.ts e2e/exam/ExamParticipation.spec.ts e2e/exam/ExamResults.spec.ts e2e/exam/ExamTestRun.spec.ts e2e/exam/test-exam/ e2e/exercise/ExerciseImport.spec.ts e2e/exercise/file-upload/ e2e/exercise/modeling/ e2e/exercise/programming/ e2e/exercise/quiz-exercise/ e2e/exercise/text/ e2e/iris/ e2e/lecture/ e2e/shared/

Overall: ❌ E2E tests failed

🔗 Workflow Run · 📊 Test Report Phase 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

account Pull requests that affect the corresponding module client Pull requests that update TypeScript code. (Added Automatically!)

Projects

Status: Ready For Review

Development

Successfully merging this pull request may close these issues.

Usability: IDE Preferences selection flashes on VS Code before jumping to the saved IDE

1 participant