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

test: Create tool for mocking event listeners #14415

Merged
merged 9 commits into from
Jan 16, 2025
Merged

Conversation

TomasEng
Copy link
Contributor

@TomasEng TomasEng commented Jan 14, 2025

Description

This pull request adds a tool for mocking event listeners in tests. It provides methods for storing and triggering custom event listeners. It is made specifically to mock the event listeners of the BPMN modeler tool, but it is quite generic and may also be used for other use cases if necessary.

Background

The tests of the useBpmnEditor hook are cumbersome to read and contain a lot of mocks that rely strictly on implementation details, so I am trying to clean that up. The mock of the bpmn-js/lib/Modeler package is necessary because it uses tools that are not supported by JSDOM, but the current mock does not mimic event listeners correctly.

How to use

In the test suite, the modeler tool may be mocked like this:

jest.mock('bpmn-js/lib/Modeler', () => jest.fn().mockImplementation(bpmnModelerImplementation));

function bpmnModelerImplementation() {
  return {
    on: (eventName: string, callback: Function) => {
      return eventListeners.add(eventName, callback);
    },
    off: (eventName: string, callback: Function) => {
      return eventListeners.remove(eventName, callback);
    },
    ...restOfTheMock
  };
}

const eventListeners = new EventListeners();

This code creates an event listener instance and applies its add and remove methods to the corresponding methods of the BPMN modeler object.

We may now use the triggerEvent method to simulate triggering events and the clear method to clear the event listeners between each test:

describe('useBpmnEditor', () => {
  beforeEach(() => {
    jest.clearAllMocks();
    eventListeners.clear();
  });

  it('Calls saveBpmn with correct data when the "commandStack.changed" event is triggered', async () => {
    const saveBpmn = jest.fn();
    await setup({ bpmnApiContextProps: { saveBpmn } });
    eventListeners.triggerEvent('commandStack.changed');
    await waitFor(expect(saveBpmn).toHaveBeenCalled);
    expect(saveBpmn).toHaveBeenCalledTimes(1);
    expect(saveBpmn).toHaveBeenCalledWith(xml, null);
  });
});

Note

This pull request does not implement the actual usage of the tool. That will be done in a future pull request.

Related Issue

Verification

  • Your code builds clean without any errors or warnings
  • Relevant automated test added (if you find this hard, leave it and we'll help out)

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced EventListeners class for managing event listeners.
    • Added methods to add, remove, trigger, and clear event listeners.
  • Tests

    • Created a comprehensive unit test suite for the EventListeners class.
    • Verified the functionality of methods for adding, removing, triggering, and clearing event listeners, including handling multiple listeners and parameter passing.

Copy link
Contributor

coderabbitai bot commented Jan 14, 2025

📝 Walkthrough

Walkthrough

The pull request introduces a new EventListeners class within the process editor package, which manages event listeners using a Map to associate event names with callback functions. The class includes methods for adding, removing, triggering, and clearing listeners. Additionally, a comprehensive suite of unit tests has been implemented to validate the functionality of these methods, ensuring that listeners operate correctly in various scenarios.

Changes

File Change Summary
frontend/packages/process-editor/test/EventListeners.ts Added new EventListeners class with methods for managing event listeners, including triggerEvent(), add(), remove(), clear(), and several private methods for internal management.
frontend/packages/process-editor/test/EventListeners.test.ts Added comprehensive unit tests for the EventListeners class, covering methods add, remove, triggerEvent, and clear, including various scenarios for listener management.

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c55e49f and 1dd9efb.

📒 Files selected for processing (1)
  • frontend/packages/process-editor/test/EventListeners.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/packages/process-editor/test/EventListeners.test.ts
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Build environment and run e2e test
  • GitHub Check: Typechecking and linting
  • GitHub Check: CodeQL
  • GitHub Check: Testing

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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. (Beta)
  • @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 anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

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.

@github-actions github-actions bot added area/process Area: Related to app process (e.g. signing, receipt, fill inn, payment, etc). solution/studio/designer Issues related to the Altinn Studio Designer solution. frontend labels Jan 14, 2025
Copy link

codecov bot commented Jan 14, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 95.65%. Comparing base (601280e) to head (d37f052).
Report is 4 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #14415   +/-   ##
=======================================
  Coverage   95.65%   95.65%           
=======================================
  Files        1885     1886    +1     
  Lines       24495    24516   +21     
  Branches     2812     2816    +4     
=======================================
+ Hits        23431    23452   +21     
  Misses        804      804           
  Partials      260      260           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@TomasEng TomasEng marked this pull request as ready for review January 14, 2025 09:51
@TomasEng TomasEng added quality/testing Tests that are missing, needs to be created or could be improved. skip-releasenotes Issues that do not make sense to list in our release notes team/studio-domain1 team/studio-core skip-manual-testing PRs that do not need to be tested manually skip-documentation Issues where updating documentation is not relevant labels Jan 14, 2025
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: 3

🧹 Nitpick comments (3)
frontend/packages/process-editor/test/EventListeners.ts (1)

31-41: Add error handling for invalid inputs.

The remove method silently ignores attempts to remove non-existent listeners. Consider adding validation and error handling:

   remove(eventName: string, callback: Function): void {
     if (this.has(eventName)) {
+      const currentList = this.get(eventName);
+      if (!currentList.includes(callback)) {
+        console.warn(
+          `Attempted to remove non-existent listener for event "${eventName}"`
+        );
+        return;
+      }
       this.removeListener(eventName, callback);
     }
   }
🧰 Tools
🪛 Biome (1.9.4)

[error] 31-31: Don't use 'Function' as a type.

Prefer explicitly define the function shape. This type accepts any function-like value, which can be a common source of bugs.

(lint/complexity/noBannedTypes)


[error] 37-37: Don't use 'Function' as a type.

Prefer explicitly define the function shape. This type accepts any function-like value, which can be a common source of bugs.

(lint/complexity/noBannedTypes)


[error] 39-39: Don't use 'Function' as a type.

Prefer explicitly define the function shape. This type accepts any function-like value, which can be a common source of bugs.

(lint/complexity/noBannedTypes)

frontend/packages/process-editor/test/EventListeners.test.ts (2)

3-45: Add tests for edge cases and error handling.

The test suite is comprehensive for happy paths but could benefit from additional test cases:

  1. Test removing a non-existent listener
  2. Test memory leak scenarios (add/remove many listeners)
  3. Test type safety with the proposed generic implementation

Example test case:

it('Warns when removing non-existent listener', () => {
  const eventListeners = new EventListeners();
  const fun = jest.fn();
  const eventName = 'event';
  
  const consoleSpy = jest.spyOn(console, 'warn');
  eventListeners.remove(eventName, fun);
  
  expect(consoleSpy).toHaveBeenCalledWith(
    'Attempted to remove non-existent listener for event "event"'
  );
});

81-140: Improve test organization with shared setup.

Consider extracting common setup code into beforeEach blocks to reduce duplication:

describe('triggerEvent', () => {
  let eventListeners: EventListeners;
  let mockFn: jest.Mock;
  
  beforeEach(() => {
    eventListeners = new EventListeners();
    mockFn = jest.fn();
  });
  
  // ... existing tests using eventListeners and mockFn
});
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a514966 and 2dfefe6.

📒 Files selected for processing (2)
  • frontend/packages/process-editor/test/EventListeners.test.ts (1 hunks)
  • frontend/packages/process-editor/test/EventListeners.ts (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
frontend/packages/process-editor/test/EventListeners.ts

[error] 56-56: The function should not return a value because its return type is void.

The function is here:

'void' signals the absence of value. The returned value is likely to be ignored by the caller.

(lint/correctness/noVoidTypeReturn)


[error] 4-4: Don't use 'Function' as a type.

Prefer explicitly define the function shape. This type accepts any function-like value, which can be a common source of bugs.

(lint/complexity/noBannedTypes)


[error] 7-7: Don't use 'Function' as a type.

Prefer explicitly define the function shape. This type accepts any function-like value, which can be a common source of bugs.

(lint/complexity/noBannedTypes)


[error] 17-17: Don't use 'Function' as a type.

Prefer explicitly define the function shape. This type accepts any function-like value, which can be a common source of bugs.

(lint/complexity/noBannedTypes)


[error] 22-22: Don't use 'Function' as a type.

Prefer explicitly define the function shape. This type accepts any function-like value, which can be a common source of bugs.

(lint/complexity/noBannedTypes)


[error] 27-27: Don't use 'Function' as a type.

Prefer explicitly define the function shape. This type accepts any function-like value, which can be a common source of bugs.

(lint/complexity/noBannedTypes)


[error] 31-31: Don't use 'Function' as a type.

Prefer explicitly define the function shape. This type accepts any function-like value, which can be a common source of bugs.

(lint/complexity/noBannedTypes)


[error] 37-37: Don't use 'Function' as a type.

Prefer explicitly define the function shape. This type accepts any function-like value, which can be a common source of bugs.

(lint/complexity/noBannedTypes)


[error] 39-39: Don't use 'Function' as a type.

Prefer explicitly define the function shape. This type accepts any function-like value, which can be a common source of bugs.

(lint/complexity/noBannedTypes)


[error] 47-47: Don't use 'Function' as a type.

Prefer explicitly define the function shape. This type accepts any function-like value, which can be a common source of bugs.

(lint/complexity/noBannedTypes)


[error] 51-51: Don't use 'Function' as a type.

Prefer explicitly define the function shape. This type accepts any function-like value, which can be a common source of bugs.

(lint/complexity/noBannedTypes)


[error] 51-51: Don't use 'Function' as a type.

Prefer explicitly define the function shape. This type accepts any function-like value, which can be a common source of bugs.

(lint/complexity/noBannedTypes)

frontend/packages/process-editor/test/EventListeners.ts Outdated Show resolved Hide resolved
frontend/packages/process-editor/test/EventListeners.ts Outdated Show resolved Hide resolved
frontend/packages/process-editor/test/EventListeners.ts Outdated Show resolved Hide resolved
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)
frontend/packages/process-editor/test/EventListeners.ts (3)

3-6: Consider making the inner array type more specific.

The current type allows mixing different event handler types in the array. Consider using Array<EventMap[K]> to ensure type consistency within each event's handlers.

 type ListenerMap<EventMap extends Record<string, (...args: any[]) => void>> = Map<
   keyof EventMap,
-  Array<EventMap[keyof EventMap]>
+  Array<EventMap[K]>
 >;

15-23: Consider adding error handling for non-existent events.

The triggerEvent method silently ignores non-existent events. Consider adding an optional parameter to control error handling behavior.

 triggerEvent<Key extends keyof EventMap>(
   eventName: Key,
+  options?: { throwOnMissing?: boolean },
   ...params: Parameters<EventMap[Key]>
 ): void {
   if (this.has(eventName)) {
     const functions = this.get(eventName);
     functions.forEach((fun) => fun(...params));
+  } else if (options?.throwOnMissing) {
+    throw new Error(`No listeners registered for event: ${String(eventName)}`);
   }
 }

25-28: Add duplicate check to prevent multiple identical listeners.

The add method doesn't check for duplicate listeners, which could lead to the same callback being executed multiple times.

 add<Key extends keyof EventMap>(eventName: Key, callback: EventMap[Key]): void {
+  if (this.functionExists(eventName, callback)) return;
   if (this.has(eventName)) this.addListenerToCurrentList<Key>(eventName, callback);
   else this.createNewListenerList<Key>(eventName, [callback]);
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2dfefe6 and 5800e39.

📒 Files selected for processing (2)
  • frontend/packages/process-editor/test/EventListeners.test.ts (1 hunks)
  • frontend/packages/process-editor/test/EventListeners.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/packages/process-editor/test/EventListeners.test.ts
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Build environment and run e2e test
  • GitHub Check: CodeQL
  • GitHub Check: Testing
🔇 Additional comments (2)
frontend/packages/process-editor/test/EventListeners.ts (2)

8-13: Well-structured class declaration with proper type safety!

The class is well-designed with:

  • Generic type constraints for type safety
  • Readonly modifier to prevent accidental list reassignment
  • Clean constructor initialization

1-87: Excellent implementation of the event listener system!

The implementation is well-structured with:

  • Strong type safety through generics
  • Clear separation of concerns
  • Good error handling
  • Clean and maintainable code organization

This aligns perfectly with the PR objective of creating a tool for mocking event listeners in tests.

frontend/packages/process-editor/test/EventListeners.ts Outdated Show resolved Hide resolved
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: 0

🧹 Nitpick comments (5)
frontend/packages/process-editor/test/EventListeners.ts (5)

3-6: Consider constraining event parameter types.

Good use of generics and type alias. Consider tightening the constraint on event parameters:

-type ListenerMap<EventMap extends Record<string, (...args: any[]) => void>> = Map<
+type ListenerMap<EventMap extends Record<string, (...args: unknown[]) => void>> = Map<
   keyof EventMap,
   Array<EventMap[keyof EventMap]>
 >;

25-43: Consider simplifying the event addition logic.

The current implementation splits the logic into multiple methods, which adds unnecessary complexity.

   add<Key extends keyof EventMap>(eventName: Key, callback: EventMap[Key]): void {
-    if (this.has(eventName)) this.addListenerToCurrentList<Key>(eventName, callback);
-    else this.createNewListenerList<Key>(eventName, [callback]);
+    const currentListeners = this.get<Key>(eventName) ?? [];
+    this.set<Key>(eventName, [...currentListeners, callback]);
   }
-
-  private addListenerToCurrentList<Key extends keyof EventMap>(
-    eventName: Key,
-    callback: EventMap[Key],
-  ): void {
-    const currentListeners = this.get<Key>(eventName);
-    this.set<Key>(eventName, [...currentListeners, callback]);
-  }
-
-  private createNewListenerList<Key extends keyof EventMap>(
-    eventName: Key,
-    callbacks: EventMap[Key][],
-  ): void {
-    this.set<Key>(eventName, callbacks);
-  }

47-49: Simplify error message construction.

The toString() call is unnecessary as template literals automatically convert values to strings.

     throw new Error(
-      `The provided callback function does not exist on the ${eventName.toString()} listener.`,
+      `The provided callback function does not exist on the ${eventName} listener.`,
     );

45-67: Consider combining function existence check with removal.

The current implementation checks for existence twice (in functionExists and get).

   remove<Key extends keyof EventMap>(eventName: Key, callback: EventMap[Key]): void {
-    if (!this.functionExists<Key>(eventName, callback))
+    const currentList = this.get<Key>(eventName);
+    if (!currentList?.includes(callback))
       throw new Error(
         `The provided callback function does not exist on the ${eventName} listener.`,
       );
-    this.removeListener<Key>(eventName, callback);
+    this.set<Key>(eventName, ArrayUtils.removeItemByValue(currentList, callback));
   }

77-82: Simplify set method signature.

The method doesn't need to return the Map instance since it's not used.

   private set<Key extends keyof EventMap>(
     eventName: Key,
     callbacks: EventMap[Key][],
-  ): ListenerMap<EventMap> {
-    return this.list.set(eventName, callbacks);
+  ): void {
+    this.list.set(eventName, callbacks);
   }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5800e39 and ce76077.

📒 Files selected for processing (1)
  • frontend/packages/process-editor/test/EventListeners.ts (1 hunks)
🧰 Additional context used
📓 Learnings (1)
frontend/packages/process-editor/test/EventListeners.ts (1)
Learnt from: TomasEng
PR: Altinn/altinn-studio#14415
File: frontend/packages/process-editor/test/EventListeners.ts:73-75
Timestamp: 2025-01-14T12:03:39.929Z
Learning: In the EventListeners class, the `get` method is only called after verifying key existence with `has`, making undefined checks unnecessary and the type assertion safe.
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Build environment and run e2e test
  • GitHub Check: Typechecking and linting
  • GitHub Check: Testing
  • GitHub Check: CodeQL
🔇 Additional comments (2)
frontend/packages/process-editor/test/EventListeners.ts (2)

15-23: Well-implemented event triggering logic!

The implementation shows excellent type safety and proper parameter handling.


1-87: Overall excellent implementation!

The EventListeners class provides a robust, type-safe implementation for managing event listeners. The code is well-structured, properly encapsulated, and includes appropriate error handling. While there are some minor opportunities for refinement, the implementation is solid and suitable for its intended use in testing.

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: 0

🧹 Nitpick comments (2)
frontend/packages/process-editor/test/EventListeners.ts (2)

45-51: Consider improving error message formatting.

The error message uses string concatenation with type assertion. Consider using template literals for better readability.

-        `The provided callback function does not exist on the ${eventName as string} listener.`,
+        `The provided callback function does not exist on the '${String(eventName)}' listener.`,

77-82: Consider removing unnecessary return.

The set method returns the Map instance which isn't used. Consider making it void.

   private set<Key extends keyof EventMap>(
     eventName: Key,
     callbacks: EventMap[Key][],
-  ): ListenerMap<EventMap> {
-    return this.list.set(eventName, callbacks);
+  ): void {
+    this.list.set(eventName, callbacks);
   }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ce76077 and f249c8b.

📒 Files selected for processing (1)
  • frontend/packages/process-editor/test/EventListeners.ts (1 hunks)
🧰 Additional context used
📓 Learnings (1)
frontend/packages/process-editor/test/EventListeners.ts (1)
Learnt from: TomasEng
PR: Altinn/altinn-studio#14415
File: frontend/packages/process-editor/test/EventListeners.ts:73-75
Timestamp: 2025-01-14T12:03:39.929Z
Learning: In the EventListeners class, the `get` method is only called after verifying key existence with `has`, making undefined checks unnecessary and the type assertion safe.
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Build environment and run e2e test
  • GitHub Check: CodeQL
  • GitHub Check: Testing
🔇 Additional comments (5)
frontend/packages/process-editor/test/EventListeners.ts (5)

1-7: LGTM! Well-structured type definitions.

The generic type ListenerMap provides a robust and type-safe foundation for the event listener implementation.


8-13: LGTM! Type-safe class implementation.

The generic class declaration with proper type constraints and minimal constructor is well-implemented.


15-23: LGTM! Well-implemented event triggering.

The method correctly handles type safety and ensures events exist before triggering.


25-28: LGTM! Clean branching logic.

The method efficiently handles both new and existing event listeners.


1-87: Verify test coverage for edge cases.

The implementation aligns well with the PR objectives for mocking event listeners. Consider adding tests for the following scenarios to ensure robust mocking:

  1. Removing the last listener for an event
  2. Adding duplicate listeners
  3. Concurrent event triggering

Would you like me to help generate these test cases?

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: 0

🧹 Nitpick comments (1)
frontend/packages/process-editor/test/EventListeners.ts (1)

25-28: Consider consistent error handling across methods.

The remove method throws an error for non-existent listeners while add silently creates new lists. Consider making the error handling behavior consistent across these methods. Options:

  1. Make add throw an error for invalid event names (matching remove's strictness)
  2. Make remove silently ignore non-existent listeners (matching add's flexibility)

The choice depends on your error handling philosophy:

  • Option 1 provides stronger guarantees but requires more error handling by callers
  • Option 2 is more flexible but might hide programming errors

Also applies to: 45-51

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f249c8b and d8da6c5.

📒 Files selected for processing (1)
  • frontend/packages/process-editor/test/EventListeners.ts (1 hunks)
🧰 Additional context used
📓 Learnings (1)
frontend/packages/process-editor/test/EventListeners.ts (1)
Learnt from: TomasEng
PR: Altinn/altinn-studio#14415
File: frontend/packages/process-editor/test/EventListeners.ts:73-75
Timestamp: 2025-01-14T12:03:39.929Z
Learning: In the EventListeners class, the `get` method is only called after verifying key existence with `has`, making undefined checks unnecessary and the type assertion safe.
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Build environment and run e2e test
  • GitHub Check: Testing
  • GitHub Check: CodeQL
🔇 Additional comments (6)
frontend/packages/process-editor/test/EventListeners.ts (6)

1-6: Well-structured type definitions!

The ListenerMap type definition provides excellent type safety through generic constraints and proper typing of the event listener map.


8-13: Clean class setup with proper encapsulation!

The class is well-structured with appropriate generic constraints and readonly protection for the internal list.


15-23: Type-safe event triggering implementation!

The triggerEvent method provides excellent type safety through generic constraints while maintaining runtime safety with existence checks.


25-28: Clean and efficient listener addition logic!

The add method handles both cases (existing and new listeners) elegantly with proper type safety.


45-51: Robust error handling in remove implementation!

The remove method properly validates listener existence before removal and provides a descriptive error message.


81-83: Simple and effective clear implementation!

The clear method efficiently removes all listeners.

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: 0

🧹 Nitpick comments (1)
frontend/packages/process-editor/test/EventListeners.ts (1)

45-54: Consider adding JSDoc comments for better documentation.

The error handling is good, but adding JSDoc comments would help users understand:

  • The expected parameters
  • When and why errors might be thrown
  • Example usage
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d8da6c5 and c55e49f.

📒 Files selected for processing (1)
  • frontend/packages/process-editor/test/EventListeners.ts (1 hunks)
🧰 Additional context used
📓 Learnings (1)
frontend/packages/process-editor/test/EventListeners.ts (1)
Learnt from: TomasEng
PR: Altinn/altinn-studio#14415
File: frontend/packages/process-editor/test/EventListeners.ts:73-75
Timestamp: 2025-01-14T12:03:39.929Z
Learning: In the EventListeners class, the `get` method is only called after verifying key existence with `has`, making undefined checks unnecessary and the type assertion safe.
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Build environment and run e2e test
  • GitHub Check: Testing
  • GitHub Check: CodeQL
  • GitHub Check: Typechecking and linting
🔇 Additional comments (4)
frontend/packages/process-editor/test/EventListeners.ts (4)

1-6: Well-structured type definitions with proper type safety!

The ListenerMap type effectively uses generics to ensure type safety while maintaining flexibility. The use of unknown[] for function parameters is a good practice as it's safer than any[].


8-13: Clean class setup with proper immutability!

Good practices observed:

  • Generic type parameter with appropriate constraints
  • Readonly list property prevents accidental mutations
  • Minimal constructor that properly initializes the map

15-23: Consider adding error handling for invalid parameters.

While the method is well-implemented, consider adding parameter validation to handle edge cases:

  • Null/undefined event name
  • Invalid parameter types that don't match the event signature

30-73: Well-structured private methods with proper encapsulation!

The private helper methods are well-organized and maintain good separation of concerns. The type assertion in the get method is safe as it's only called after verifying existence with has.

@standeren standeren self-assigned this Jan 15, 2025
Copy link
Contributor

@standeren standeren left a comment

Choose a reason for hiding this comment

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

Nice! 👏
Not much to comment on this, except from some suggestions regarding the tests.

@standeren standeren assigned TomasEng and unassigned standeren Jan 15, 2025
@TomasEng TomasEng requested a review from standeren January 15, 2025 15:23
@TomasEng TomasEng assigned standeren and unassigned TomasEng Jan 15, 2025
@standeren standeren merged commit 246474d into main Jan 16, 2025
11 checks passed
@standeren standeren deleted the event-listeners-mock branch January 16, 2025 12:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/process Area: Related to app process (e.g. signing, receipt, fill inn, payment, etc). frontend quality/testing Tests that are missing, needs to be created or could be improved. skip-documentation Issues where updating documentation is not relevant skip-manual-testing PRs that do not need to be tested manually skip-releasenotes Issues that do not make sense to list in our release notes solution/studio/designer Issues related to the Altinn Studio Designer solution. team/studio-core team/studio-domain1
Projects
Status: ✅ Done
Development

Successfully merging this pull request may close these issues.

2 participants