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

fix: rely on component type instead of its ID when display override config #14545

Merged
merged 6 commits into from
Jan 31, 2025

Conversation

lassopicasso
Copy link
Contributor

@lassopicasso lassopicasso commented Jan 30, 2025

Description

This PR fix the override config for checkbox and multiple select components when parts of the config is not displayed after editing the component's id.

There were some incorrect tests in Summary2Override that passed for reasons unrelated to what was actually being tested. I also removed some redundant tests and refactored others.

Related Issue(s)

Verification

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

Documentation

  • User documentation is updated with a separate linked PR in altinn-studio-docs. (if applicable)

Summary by CodeRabbit

Summary by CodeRabbit

  • Type Updates

    • Introduced new TargetComponentProps type with enhanced component information
    • Renamed TargetProps to TargetPageProps
  • Component Enhancements

    • Updated Summary2OverrideDisplayType to include componentOptions prop
    • Modified Summary2OverrideEntry to utilize new componentOptions prop
  • Utility Function Updates

    • Adjusted getComponentOptions and getPageOptions to return more detailed component information
  • Testing Improvements

    • Added new mock components and streamlined tests for Summary2Override
    • Enhanced test coverage for rendering logic based on component types
    • Introduced new helper functions for improved test maintainability
    • Added support for a multiple select component in testing mocks

Copy link
Contributor

coderabbitai bot commented Jan 30, 2025

📝 Walkthrough

Walkthrough

The pull request introduces changes to the Summary2 component's type definitions and prop handling across multiple files. The modifications primarily focus on renaming the TargetProps type to TargetPageProps and introducing a new TargetComponentProps type that extends the existing type with a type property. The changes update the Summary2OverrideDisplayType component to accept componentOptions as a prop, altering how component types are determined and processed.

Changes

File Change Summary
frontend/packages/ux-editor/src/components/config/componentSpecificContent/Summary2/Override/OverrideFields/Summary2OverrideDisplayType.tsx - Added componentOptions: TargetComponentProps[] to Summary2OverrideDisplayTypeProps interface
- Updated component to use selectedComponentType from componentOptions
frontend/packages/ux-editor/src/components/config/componentSpecificContent/Summary2/Override/Summary2OverrideEntry.tsx - Replaced TargetProps with TargetComponentProps in type imports
- Updated Summary2OverrideDisplayType component usage to include componentOptions prop
frontend/packages/ux-editor/src/components/config/componentSpecificContent/Summary2/Summary2Target/targetUtils.ts - Renamed TargetProps to TargetPageProps
- Added new TargetComponentProps type
- Updated getComponentOptions and getPageOptions return types
frontend/packages/ux-editor/src/components/config/componentSpecificContent/Summary2/Override/Summary2Override.test.tsx - Added mock components and new tests for rendering options
- Consolidated existing tests into a parameterized test
- Updated tests to utilize new mock components and helper functions
frontend/packages/ux-editor/src/testing/layoutMock.ts - Added componentWithMultipleSelectMock for testing
- Updated layoutMock to include the new mock component

Possibly related PRs

Suggested labels

quality/testing, team/studio-domain2

Suggested reviewers

  • Jondyr
  • mlqn

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/ui-editor Area: Related to the designer tool for assembling app UI in Altinn Studio. solution/studio/designer Issues related to the Altinn Studio Designer solution. frontend labels Jan 30, 2025
@lassopicasso lassopicasso changed the title Rely on component type instead of its ID when display override config fix: rely on component type instead of its ID when display override config Jan 30, 2025
@lassopicasso lassopicasso added the skip-manual-testing PRs that do not need to be tested manually label Jan 30, 2025
@lassopicasso lassopicasso marked this pull request as ready for review January 30, 2025 07:42
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/ux-editor/src/components/config/componentSpecificContent/Summary2/Override/OverrideFields/Summary2OverrideDisplayType.tsx (1)

25-27: LGTM! Improved component type checking.

The implementation now correctly relies on the component's type rather than its ID for determining display behavior. This change makes the logic more robust when component IDs change.

-  const checkboxOrMultipleselect =
-    selectedComponentType?.includes(ComponentType.MultipleSelect) ||
-    selectedComponentType?.includes(ComponentType.Checkboxes);
+  const checkboxOrMultipleselect = [
+    ComponentType.MultipleSelect,
+    ComponentType.Checkboxes
+  ].includes(selectedComponentType);

Consider this minor optimization to make the type checking more concise and efficient.

Also applies to: 30-31

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 7578699 and e022534.

📒 Files selected for processing (3)
  • frontend/packages/ux-editor/src/components/config/componentSpecificContent/Summary2/Override/OverrideFields/Summary2OverrideDisplayType.tsx (1 hunks)
  • frontend/packages/ux-editor/src/components/config/componentSpecificContent/Summary2/Override/Summary2OverrideEntry.tsx (2 hunks)
  • frontend/packages/ux-editor/src/components/config/componentSpecificContent/Summary2/Summary2Target/targetUtils.ts (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Build environment and run e2e test
🔇 Additional comments (7)
frontend/packages/ux-editor/src/components/config/componentSpecificContent/Summary2/Summary2Target/targetUtils.ts (3)

32-35: LGTM! Clear separation of page and component types.

The introduction of separate TargetPageProps and TargetComponentProps types provides a clear distinction between page and component references, with components explicitly including their type information.

Also applies to: 37-39


66-66: LGTM! Component type is now included in options.

The getComponentOptions function now includes the component type in its return value, which is crucial for the new type-based display logic.

Also applies to: 76-76


Line range hint 80-86: LGTM! Consistent type usage for page options.

The getPageOptions function now correctly uses the renamed TargetPageProps type, maintaining consistency with the new type system.

frontend/packages/ux-editor/src/components/config/componentSpecificContent/Summary2/Override/Summary2OverrideEntry.tsx (2)

20-20: LGTM! Updated type imports and props.

The component now correctly uses TargetComponentProps type for component options, ensuring type information is available.

Also applies to: 26-26


79-83: LGTM! Component options properly passed to child.

The Summary2OverrideDisplayType component now receives the necessary component options for type-based display logic.

frontend/packages/ux-editor/src/components/config/componentSpecificContent/Summary2/Override/OverrideFields/Summary2OverrideDisplayType.tsx (2)

11-11: LGTM! Added necessary type imports and props.

The component correctly imports and uses TargetComponentProps type for the new componentOptions prop.

Also applies to: 15-15


37-41: LGTM! Handler maintains functionality.

The handleCustomTypeChange function maintains its functionality while working with the new type-based approach.

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/ux-editor/src/components/config/componentSpecificContent/Summary2/Override/Summary2Override.test.tsx (2)

155-182: Consider consolidating duplicate test logic.

The tests for overriding display type for multiple select and checkbox components contain similar logic. Consider using it.each to reduce duplication, similar to how you've done it in the earlier test.

-  it('should be able to override display type when component type is multiple select', async () => {
-    const user = userEvent.setup();
-    render({ overrides: [{ componentId: multipleSelectId }] });
-
-    await user.click(overrideCollapsedButton(1));
-    const optionStringType = screen.getByRole('option', {
-      name: textMock('ux_editor.component_properties.summary.override.display_type.string'),
-    });
-    await user.selectOptions(overrideTypeSelect(), optionStringType);
-
-    expect(defaultProps.onChange).toHaveBeenCalledWith(
-      expect.arrayContaining([{ componentId: multipleSelectId, displayType: 'string' }]),
-    );
-  });
-
-  it('should be able to override display type when component type is checkbox', async () => {
-    const user = userEvent.setup();
-    render({ overrides: [{ componentId: checkBoxId }] });
-    await user.click(overrideCollapsedButton(1));
-    const optionStringType = screen.getByRole('option', {
-      name: textMock('ux_editor.component_properties.summary.override.display_type.string'),
-    });
-    await user.selectOptions(overrideTypeSelect(), optionStringType);
-
-    expect(defaultProps.onChange).toHaveBeenCalledWith(
-      expect.arrayContaining([{ componentId: checkBoxId, displayType: 'string' }]),
-    );
-  });
+  it.each([
+    ['multiple select', multipleSelectId],
+    ['checkbox', checkBoxId],
+  ])('should be able to override display type when component type is %s', async (_, componentId) => {
+    const user = userEvent.setup();
+    render({ overrides: [{ componentId }] });
+
+    await user.click(overrideCollapsedButton(1));
+    const optionStringType = screen.getByRole('option', {
+      name: textMock('ux_editor.component_properties.summary.override.display_type.string'),
+    });
+    await user.selectOptions(overrideTypeSelect(), optionStringType);
+
+    expect(defaultProps.onChange).toHaveBeenCalledWith(
+      expect.arrayContaining([{ componentId, displayType: 'string' }]),
+    );
+  });

270-277: Enhance error reporting in the helper function.

The renderedTypeOptions function could provide better feedback when assertions fail. Consider returning an object with both the result and any missing options.

 const renderedTypeOptions = () => {
   const expectedOptions = ['list', 'string', 'not_set'].map((type) =>
     textMock(`ux_editor.component_properties.summary.override.display_type.${type}`),
   );

   const renderedOptions = screen.getAllByRole('option').map((option) => option.textContent);
-  return expectedOptions.every((option) => renderedOptions.includes(option));
+  const missingOptions = expectedOptions.filter((option) => !renderedOptions.includes(option));
+  return {
+    isComplete: missingOptions.length === 0,
+    missingOptions,
+    toString: () => missingOptions.length === 0 ? 'All options present' : `Missing options: ${missingOptions.join(', ')}`,
+  };
 };
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e022534 and 13cb6fa.

📒 Files selected for processing (2)
  • frontend/packages/ux-editor/src/components/config/componentSpecificContent/Summary2/Override/Summary2Override.test.tsx (10 hunks)
  • frontend/packages/ux-editor/src/testing/layoutMock.ts (2 hunks)
🔇 Additional comments (2)
frontend/packages/ux-editor/src/testing/layoutMock.ts (1)

56-64: LGTM! Well-structured mock data.

The new multiple select mock component follows the established patterns and maintains consistency with other mock components in the file.

Also applies to: 84-84

frontend/packages/ux-editor/src/components/config/componentSpecificContent/Summary2/Override/Summary2Override.test.tsx (1)

46-57: LGTM! Great use of parameterized testing.

The use of it.each reduces code duplication and makes the tests more maintainable.

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/ux-editor/src/components/config/componentSpecificContent/Summary2/Override/Summary2Override.test.tsx (1)

152-179: Consider consolidating duplicate tests using parameterized testing.

The tests for multiple select and checkbox display type override are nearly identical. Consider refactoring them using it.each similar to the type options test to reduce code duplication.

-  it('should be able to override display type when component type is multiple select', async () => {
-    const user = userEvent.setup();
-    render({ overrides: [{ componentId: multipleSelectId }] });
-
-    await user.click(overrideCollapsedButton(1));
-    const optionStringType = screen.getByRole('option', {
-      name: textMock('ux_editor.component_properties.summary.override.display_type.string'),
-    });
-    await user.selectOptions(overrideTypeSelect(), optionStringType);
-
-    expect(defaultProps.onChange).toHaveBeenCalledWith(
-      expect.arrayContaining([{ componentId: multipleSelectId, displayType: 'string' }]),
-    );
-  });
-
-  it('should be able to override display type when component type is checkbox', async () => {
-    const user = userEvent.setup();
-    render({ overrides: [{ componentId: checkBoxId }] });
-    await user.click(overrideCollapsedButton(1));
-    const optionStringType = screen.getByRole('option', {
-      name: textMock('ux_editor.component_properties.summary.override.display_type.string'),
-    });
-    await user.selectOptions(overrideTypeSelect(), optionStringType);
-
-    expect(defaultProps.onChange).toHaveBeenCalledWith(
-      expect.arrayContaining([{ componentId: checkBoxId, displayType: 'string' }]),
-    );
-  });
+  it.each([
+    ['multiple select', multipleSelectId],
+    ['checkbox', checkBoxId],
+  ])('should be able to override display type when component type is %s', async (_, componentId) => {
+    const user = userEvent.setup();
+    render({ overrides: [{ componentId }] });
+
+    await user.click(overrideCollapsedButton(1));
+    const optionStringType = screen.getByRole('option', {
+      name: textMock('ux_editor.component_properties.summary.override.display_type.string'),
+    });
+    await user.selectOptions(overrideTypeSelect(), optionStringType);
+
+    expect(defaultProps.onChange).toHaveBeenCalledWith(
+      expect.arrayContaining([{ componentId, displayType: 'string' }]),
+    );
+  });
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 13cb6fa and 6fbbd46.

📒 Files selected for processing (1)
  • frontend/packages/ux-editor/src/components/config/componentSpecificContent/Summary2/Override/Summary2Override.test.tsx (10 hunks)
⏰ 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 (4)
frontend/packages/ux-editor/src/components/config/componentSpecificContent/Summary2/Override/Summary2Override.test.tsx (4)

11-12: LGTM! Clear mock component setup.

The mock components and their corresponding ID constants are well-organized and properly imported.

Also applies to: 20-21


46-55: Well-structured parameterized test!

Good use of it.each to test type options rendering for both component types, reducing code duplication while maintaining clear test cases.


Line range hint 57-65: LGTM! Good negative test case.

Properly verifies that type selector is not rendered for unsupported component types using appropriate query methods.


262-274: LGTM! Well-structured helper functions.

The helper functions are focused, well-named, and use appropriate testing library queries. The renderedTypeOptions function provides a clean way to verify all expected options.

Copy link

codecov bot commented Jan 30, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 95.71%. Comparing base (36eb57a) to head (ab99a0f).
Report is 6 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main   #14545   +/-   ##
=======================================
  Coverage   95.71%   95.71%           
=======================================
  Files        1904     1904           
  Lines       24801    24803    +2     
  Branches     2840     2840           
=======================================
+ Hits        23738    23740    +2     
  Misses        802      802           
  Partials      261      261           

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

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 (4)
frontend/packages/ux-editor/src/components/config/componentSpecificContent/Summary2/Override/Summary2Override.test.tsx (4)

Line range hint 64-72: Consider enhancing the negative test case.

While the test correctly verifies that the type selector doesn't appear for unsupported components, consider:

  • Using a more descriptive component ID (e.g., textComponentId) instead of component1IdMock
  • Adding more component types to verify (e.g., textfield, radio, etc.)

79-79: Consider extracting test constants and helper functions.

The repeated use of overrideCollapsedButton(1) across multiple tests suggests an opportunity for improvement:

  • Extract the override index as a named constant (e.g., FIRST_OVERRIDE_INDEX = 1)
  • Create a helper function that combines common operations (e.g., expandFirstOverride())

Example:

const FIRST_OVERRIDE_INDEX = 1;
const expandOverride = async (index: number) => {
  await userEvent.click(overrideCollapsedButton(index));
};

Also applies to: 94-94, 110-110, 128-128, 145-145


159-185: Consider parameterizing display type override tests.

The tests for checkbox and multiple select components have similar structure. Consider:

  • Using it.each to test both component types
  • Testing all available display types, not just 'string'
  • Extracting the option selection logic into a helper function

Example:

it.each([
  { componentId: checkBoxId, type: 'checkbox' },
  { componentId: multipleSelectId, type: 'multipleSelect' }
])('should override display type for $type component', async ({ componentId }) => {
  const user = userEvent.setup();
  render({ overrides: [{ componentId }] });
  
  await user.click(overrideCollapsedButton(1));
  
  for (const displayType of ['string', 'list']) {
    const option = screen.getByRole('option', {
      name: textMock(`ux_editor.component_properties.summary.override.display_type.${displayType}`),
    });
    await user.selectOptions(overrideTypeSelect(), option);
    
    expect(defaultProps.onChange).toHaveBeenCalledWith(
      expect.arrayContaining([{ componentId, displayType }]),
    );
  }
});

269-281: Consider making helper functions more flexible.

The helper functions are well-structured, but renderedTypeOptions could be improved:

  • Accept expected types as a parameter instead of hardcoding them
  • Return the actual options for more detailed assertions
  • Add JSDoc comments to document the purpose and usage

Example:

/**
 * Verifies that the rendered type options match the expected options.
 * @param expectedTypes - Array of expected type keys (e.g., ['list', 'string'])
 * @returns Object containing actual options and a match result
 */
const getRenderedTypeOptions = (expectedTypes: string[] = ['list', 'string', 'not_set']) => {
  const expectedOptions = expectedTypes.map((type) =>
    textMock(`ux_editor.component_properties.summary.override.display_type.${type}`)
  );
  const renderedOptions = screen.getAllByRole('option').map((option) => option.textContent);
  
  return {
    renderedOptions,
    allExpectedOptionsPresent: expectedOptions.every((option) => renderedOptions.includes(option))
  };
};
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 6fbbd46 and ab99a0f.

📒 Files selected for processing (2)
  • frontend/packages/ux-editor/src/components/config/componentSpecificContent/Summary2/Override/Summary2Override.test.tsx (11 hunks)
  • frontend/packages/ux-editor/src/testing/layoutMock.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/packages/ux-editor/src/testing/layoutMock.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 (3)
frontend/packages/ux-editor/src/components/config/componentSpecificContent/Summary2/Override/Summary2Override.test.tsx (3)

11-28: LGTM! Clean test data setup.

The mock setup is well-structured and follows good testing practices by reusing and extending existing mock objects.


53-62: Great use of parameterized testing!

The use of it.each reduces code duplication and makes the test cases more maintainable. This approach makes it easy to add more component types in the future.


291-291: LGTM! Necessary update to support new tests.

The render function is correctly updated to use the new layout mock with multiple select component.

Copy link
Contributor

@mlqn mlqn left a comment

Choose a reason for hiding this comment

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

💯

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/ui-editor Area: Related to the designer tool for assembling app UI in Altinn Studio. frontend skip-manual-testing PRs that do not need to be tested manually solution/studio/designer Issues related to the Altinn Studio Designer solution.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bug: Checkbox overrides rely on ID (update to use component type)
2 participants