Skip to content

Development: Improve client test coverage #11016

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

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from

Conversation

florian-glombik
Copy link
Contributor

@florian-glombik florian-glombik commented Jun 13, 2025

Checklist

General

Client

Motivation and Context

I lowered the client test thresholds in #10979, as the touched components are well tested, and it would be an imbalanced effort to increase the coverage within those components; I decided to increase the coverage at other places.

So we keep moving towards the 90% coverage goal and do not make steps back there.

Description

Adds several tests for insufficiently covered parts of the client code.

Steps for Testing

Verify that the tests pass in the pipeline

Review Progress

Performance Review

Code Review

  • Code Review 1
  • Code Review 2

Test Coverage

Summary by CodeRabbit

  • Tests
    • Added new and expanded test suites for user passkey settings, doughnut chart component, modeling exercise resolver, EXIF image utilities, canvas resizing utility, and text exercise resolver.
    • Improved coverage for error handling, fallback states, and correct processing of route parameters and image data transformations.

@florian-glombik florian-glombik self-assigned this Jun 13, 2025
@florian-glombik florian-glombik requested review from a team and krusche as code owners June 13, 2025 09:12
@github-project-automation github-project-automation bot moved this to Work In Progress in Artemis Development Jun 13, 2025
@florian-glombik florian-glombik added this to the 8.1.4 milestone Jun 13, 2025
@github-actions github-actions bot added client Pull requests that update TypeScript code. (Added Automatically!) core Pull requests that affect the corresponding module exercise Pull requests that affect the corresponding module modeling Pull requests that affect the corresponding module text Pull requests that affect the corresponding module labels Jun 13, 2025
Copy link
Contributor

coderabbitai bot commented Jun 13, 2025

Walkthrough

This update adds new and reorganized unit tests for several Angular services and utility functions, focusing on error handling, control flow, and correct data processing. The changes include expanded test coverage for credential utilities, passkey management, chart fallback states, image EXIF utilities, canvas resizing, and exercise resolvers.

Changes

Files/Groups Change Summary
.../core/user/settings/passkey-settings/util/credential.util.spec.ts Reorganized and expanded tests for credential utility functions, adding error handling and alert scenarios.
.../exercise/statistics/doughnut-chart/doughnut-chart.component.spec.ts Added a test for fallback chart state when no data is present.
.../modeling/manage/services/modeling-exercise-resolver.service.spec.ts New test suite for ModelingExerciseResolver covering various route parameter scenarios.
.../shared/image-cropper/utils/exif.utils.spec.ts New tests for EXIF utility functions, including browser support and transformation logic.
.../shared/image-cropper/utils/resize.utils.spec.ts New test for resizeCanvas utility ensuring correct resizing and context preservation.
.../text/manage/text-exercise/service/text-exercise-resolver.service.spec.ts New test suite for TextExerciseResolver with tests for different route parameter combinations.

Sequence Diagram(s)

sequenceDiagram
    participant TestSuite
    participant CredentialUtil
    participant WebauthnApiService
    participant AlertService

    TestSuite->>CredentialUtil: getCredentialWithGracefullyHandlingAuthenticatorIssues(credential)
    alt credential is null
        CredentialUtil-->>TestSuite: return null
    else credential.toJSON throws
        CredentialUtil-->>TestSuite: throw InvalidCredentialError
    else
        CredentialUtil-->>TestSuite: return processed credential
    end

    TestSuite->>CredentialUtil: addNewPasskey(user)
    alt user is undefined
        CredentialUtil-->>TestSuite: throw Error
    else
        CredentialUtil->>WebauthnApiService: getRegistrationOptions()
        alt getRegistrationOptions throws
            CredentialUtil-->>TestSuite: propagate error
        else
            CredentialUtil->>window.navigator.credentials: create()
            alt returns null
                CredentialUtil->>AlertService: error()
                CredentialUtil-->>TestSuite: throw Error
            else
                CredentialUtil-->>TestSuite: return new passkey
            end
        end
    end
Loading

Possibly related PRs

  • ls1intum/Artemis#10785: Introduces the credential utility function and error handling logic that is further tested and expanded in this PR.

Suggested labels

tests, client, ready for review

Suggested reviewers

  • krusche
  • jfr2102
  • Auxburger

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

npm error Exit handler never called!
npm error This is an error with npm itself. Please report this error at:
npm error https://github.com/npm/cli/issues
npm error A complete log of this run can be found in: /.npm/_logs/2025-06-13T09_14_35_636Z-debug-0.log

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate Unit Tests
  • Create PR with Unit Tests
  • Commit Unit Tests in branch chore/development/improve-client-coverage
  • Post Copyable Unit Tests in Comment

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai auto-generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

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 (3)
src/main/webapp/app/exercise/statistics/doughnut-chart/doughnut-chart.component.spec.ts (1)

52-61: Explicitly set test pre-conditions to keep it future-proof

The test currently depends on the component’s default contentType (and other defaults) remaining unchanged. If someone later alters those defaults, this test might fail for reasons unrelated to the fallback logic you actually want to check.
Adding the explicit setup makes the intention crystal-clear and decouples the test from implementation details.

@@
-    it('should use fallback value when currentAbsolute is undefined and stats are not received', () => {
-        component.currentAbsolute = undefined;
-        component.receivedStats = false;
-        component.ngOnChanges();
+    it('should use fallback value when currentAbsolute is undefined and stats are not received', () => {
+        component.contentType = DoughnutChartType.AVERAGE_EXERCISE_SCORE; // ensure deterministic context
+        component.currentAbsolute = undefined;
+        component.currentPercentage = undefined;                          // align both value sources
+        component.receivedStats = false;
+        component.ngOnChanges();

This small tweak strengthens the test’s resilience without changing its semantics.

src/main/webapp/app/text/manage/text-exercise/service/text-exercise-resolver.service.spec.ts (1)

21-27: Redundant HTTP providers clutter the testing module

provideHttpClientTesting() already supplies HttpClient. Injecting provideHttpClient() in addition is unnecessary and can mask mis-configurations if one of them changes.
Remove provideHttpClient() for a leaner and less error-prone setup.

src/main/webapp/app/modeling/manage/services/modeling-exercise-resolver.service.spec.ts (1)

22-28: Duplicate HTTP providers

Same comment as for the TextExercise resolver spec – provideHttpClient() is redundant when provideHttpClientTesting() is present.

- provideHttpClient(),
  provideHttpClientTesting(),
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 724251e and 758d7bb.

📒 Files selected for processing (6)
  • src/main/webapp/app/core/user/settings/passkey-settings/util/credential.util.spec.ts (1 hunks)
  • src/main/webapp/app/exercise/statistics/doughnut-chart/doughnut-chart.component.spec.ts (1 hunks)
  • src/main/webapp/app/modeling/manage/services/modeling-exercise-resolver.service.spec.ts (1 hunks)
  • src/main/webapp/app/shared/image-cropper/utils/exif.utils.spec.ts (1 hunks)
  • src/main/webapp/app/shared/image-cropper/utils/resize.utils.spec.ts (1 hunks)
  • src/main/webapp/app/text/manage/text-exercise/service/text-exercise-resolver.service.spec.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`src/main/webapp/**/*.ts`: angular_style:https://angular.io/guide/styleguide;methods_in_html:false;lazy_loading:true;code_reuse:true;tests:meaningful;types:PascalCase;enums:PascalC...

src/main/webapp/**/*.ts: angular_style:https://angular.io/guide/styleguide;methods_in_html:false;lazy_loading:true;code_reuse:true;tests:meaningful;types:PascalCase;enums:PascalCase;funcs:camelCase;props:camelCase;no_priv_prefix:true;strings:single_quotes;localize:true;btns:functionality;links:navigation;icons_text:newline;labels:associate;code_style:arrow_funcs,curly_braces,open_braces_same_line,indent_4;memory_leak_prevention:true;routes:naming_schema;chart_framework:ngx-charts;responsive_layout:true

  • src/main/webapp/app/shared/image-cropper/utils/exif.utils.spec.ts
  • src/main/webapp/app/shared/image-cropper/utils/resize.utils.spec.ts
  • src/main/webapp/app/exercise/statistics/doughnut-chart/doughnut-chart.component.spec.ts
  • src/main/webapp/app/core/user/settings/passkey-settings/util/credential.util.spec.ts
  • src/main/webapp/app/text/manage/text-exercise/service/text-exercise-resolver.service.spec.ts
  • src/main/webapp/app/modeling/manage/services/modeling-exercise-resolver.service.spec.ts
🧬 Code Graph Analysis (1)
src/main/webapp/app/modeling/manage/services/modeling-exercise-resolver.service.spec.ts (1)
src/main/webapp/app/core/course/shared/entities/course.model.ts (1)
  • Course (59-180)
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Build and Push Docker Image / Build Docker Image for ls1intum/artemis
  • GitHub Check: Build and Push Docker Image / Build Docker Image for ls1intum/artemis
  • GitHub Check: Build .war artifact
  • GitHub Check: Analyse
  • GitHub Check: client-style
  • GitHub Check: client-tests-selected
  • GitHub Check: client-tests
  • GitHub Check: server-tests
  • GitHub Check: server-style
  • GitHub Check: Mend Security Check
🔇 Additional comments (2)
src/main/webapp/app/shared/image-cropper/utils/resize.utils.spec.ts (1)

27-33:

✅ Verification successful

Canvas context is assumed to exist – will fail in plain JSDOM environments

expect(context).not.toBeNull(); requires that HTMLCanvasElement#getContext('2d') returns a working mock.
In the default Jest + JSDOM setup this call returns null unless jest-canvas-mock (or a similar stub) is installed and imported in the Jest setup file.
Without that dependency the assertion will always fail on CI.

Consider adding the mock explicitly or replace the expectation with a defensive check that only runs when a context is available.


I’ll verify whether jest-canvas-mock (or a similar stub) is configured in the repo’s Jest setup:


🏁 Script executed:

#!/bin/bash
# Search for jest-canvas-mock references in code/dependencies
rg "jest-canvas-mock" .

# Check Jest config for setupFiles or setupFilesAfterEnv entries
rg "setupFiles" -n .
rg "setupFilesAfterEnv" -n .

Length of output: 845


jest-canvas-mock is already configured in Jest setup

I verified that:

  • jest-canvas-mock is listed in package.json and imported in src/test/javascript/spec/jest-test-setup.ts
  • That setup file is included under setupFilesAfterEnv in jest.config.js

The 2D canvas context will be mocked correctly, so the existing expect(context).not.toBeNull() check will pass on CI. No changes required.

src/main/webapp/app/shared/image-cropper/utils/exif.utils.spec.ts (1)

17-18:

❓ Verification inconclusive

Mocking window.Image via jest.spyOn is brittle

window.Image is a constructor function but can be non-configurable in JSDOM. jest.spyOn(window, 'Image') may therefore throw or silently fail, leaving the real constructor in place and breaking the test.

A safer pattern:

- jest.spyOn(window, 'Image').mockImplementation(() => mockImage);
+ const OriginalImage = window.Image;
+ Object.defineProperty(window, 'Image', { writable: true, value: jest.fn(() => mockImage) });
+ // …after the test
+ Object.defineProperty(window, 'Image', { writable: true, value: OriginalImage });

or move this logic to a shared Jest setup file.

Also applies to: 34-35


🏁 Script executed:

#!/bin/bash
# Search for usages of jest.spyOn on window.Image in the repository
grep -R "jest\.spyOn(window, 'Image')" -n .

Length of output: 347


Verify window.Image Configurability Before Mocking

Please confirm whether window.Image is configurable in your Jest/JSDOM environment. If it’s non-configurable, jest.spyOn(window, 'Image') can fail or be a no-op.

• File: src/main/webapp/app/shared/image-cropper/utils/exif.utils.spec.ts
– Lines 17–18
– Lines 34–35

Suggested pattern when window.Image is non-configurable:

- jest.spyOn(window, 'Image').mockImplementation(() => mockImage);
+ // Capture original constructor
+ const OriginalImage = window.Image;
+ // Override with a writable mock
+ Object.defineProperty(window, 'Image', {
+   writable: true,
+   configurable: true,
+   value: jest.fn(() => mockImage),
+ });
+ // …run your test…
+ // Restore original constructor
+ Object.defineProperty(window, 'Image', {
+   writable: true,
+   configurable: true,
+   value: OriginalImage,
+ });

Alternatively, centralize this setup/teardown in a shared Jest setup file.

@github-project-automation github-project-automation bot moved this from Work In Progress to Ready For Review in Artemis Development Jun 13, 2025
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ✅Skipped ⚠️FailedTime ⏱
End-to-End (E2E) Test Report201 ran198 passed3 skipped0 failed58m 2s 355ms
TestResultTime ⏱
No test annotations available

@florian-glombik florian-glombik modified the milestones: 8.1.4, 8.2.0 Jun 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
client Pull requests that update TypeScript code. (Added Automatically!) core Pull requests that affect the corresponding module exercise Pull requests that affect the corresponding module modeling Pull requests that affect the corresponding module text Pull requests that affect the corresponding module
Projects
Status: Ready For Review
Development

Successfully merging this pull request may close these issues.

1 participant