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: Adds missing tests for the component #3385

Merged
merged 12 commits into from
Dec 24, 2024
Merged

Conversation

bistaastha
Copy link
Contributor

@bistaastha bistaastha commented Dec 20, 2024

Fixes for test coverage.

Summary by CodeRabbit

  • New Features

    • Enhanced task management with the addition of corporate card functionalities.
    • New methods for handling corporate card tasks and enrollment success.
    • Expanded observables to manage payment method availability.
  • Bug Fixes

    • Improved test coverage for corporate card addition and task handling scenarios.
  • Documentation

    • Updated mock data to include new constants for corporate card tasks.
  • Tests

    • Added new test cases to verify behavior related to corporate card functionalities.

Copy link

coderabbitai bot commented Dec 20, 2024

Walkthrough

[In Rajinikanth's stylish swagger]

Superstar style update incoming! We've turbocharged the tasks and corporate card management in our Angular application. The changes are like a mass action sequence - adding new methods, importing powerful services, and creating epic test scenarios that'll make even run configurations bow down! From JUnit configurations to corporate card enrollment, this PR is a full-blown masala movie of code transformation.

Changes

File Change Summary
android/.idea/runConfigurations.xml Updated JUnit configuration producers
src/app/fyle/dashboard/tasks/* Enhanced task management, added corporate card enrollment methods, expanded test coverage
src/app/core/services/tasks.service.ts Added getAddCorporateCardTask() method, updated task retrieval logic
src/app/core/mock-data/task-cta.data.ts Added new taskCtaData11 constant

Sequence Diagram

sequenceDiagram
    participant User
    participant TasksComponent
    participant PopoverController
    participant CorporateCreditCardService

    User->>TasksComponent: Click Add Corporate Card
    TasksComponent->>CorporateCreditCardService: Check Card Eligibility
    CorporateCreditCardService-->>TasksComponent: Return Eligibility
    TasksComponent->>PopoverController: Create Card Addition Popover
    PopoverController-->>User: Display Popover
Loading

Possibly related PRs

Suggested Labels

size/M

Suggested Reviewers

  • arjunaj5
  • Chethan-Fyle
  • Dimple16

Poem

🚀 Code flows like a whisper, tasks take flight
Configurations dance in digital light
Corporate cards join the rhythm so bold
Rajini's style in every method told
Transformation complete, mic drop! ✨

[Throws sunglasses dramatically]


🪧 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 the size/M Medium PR label Dec 20, 2024
Copy link

@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

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between df00248 and 0518a96.

📒 Files selected for processing (5)
  • android/.idea/runConfigurations.xml (1 hunks)
  • src/app/auth/sign-in/sign-in.page.html (1 hunks)
  • src/app/fyle/dashboard/tasks/tasks-2.component.spec.ts (4 hunks)
  • src/app/fyle/dashboard/tasks/tasks.component.setup.spec.ts (1 hunks)
  • src/app/fyle/dashboard/tasks/tasks.component.ts (1 hunks)
🧰 Additional context used
📓 Learnings (1)
src/app/fyle/dashboard/tasks/tasks-2.component.spec.ts (1)
Learnt from: bistaastha
PR: fylein/fyle-mobile-app#3240
File: src/app/fyle/manage-corporate-cards/manage-corporate-cards.page.spec.ts:200-200
Timestamp: 2024-11-12T04:53:12.395Z
Learning: In 'src/app/fyle/manage-corporate-cards/manage-corporate-cards.page.spec.ts', moving 'component.isAddCorporateCardVisible$ = of(true);' to the top-level beforeEach block causes tests to fail, so mock values need to be set in individual tests.
🔇 Additional comments (4)
android/.idea/runConfigurations.xml (1)

6-13: Mind it! These configuration changes are perfectly aligned with our testing mission!

The transformation from Compose preview to JUnit and Kotlin test configurations is exactly what we need for better test coverage. Like a well-choreographed action sequence, each configuration producer serves its purpose:

  • JUnit configurations for different test discovery methods
  • Kotlin-specific test producers for seamless integration
src/app/fyle/dashboard/tasks/tasks.component.setup.spec.ts (1)

73-73: When I add a spy method, I make sure it's well tested!

The addition of clearCache to the spy object is good, but let's verify its test coverage like a true superstar!

✅ Verification successful

Let me broaden the search to catch this elusive method like a true superstar! flips sunglasses


Mind games won't work with me! Let me find those test cases with the precision of a superstar! flips glasses


Mind it! The clearCache method is already well tested, superstar!

I can see with my signature style that the clearCache method is thoroughly tested across multiple components:

  • The method implementation exists in corporate-credit-card-expense.service.ts
  • It's being tested in tasks-2.component.spec.ts within the handleEnrollmentSuccess test case
  • Additional test coverage exists in manage-corporate-cards and card-stats components

When you add a spy method, make sure it's tested - and this one definitely is! The test coverage is as solid as my action sequences! flips sunglasses

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify test coverage for clearCache method

# Search for test cases using clearCache
rg -l "clearCache.*CorporateCreditCardExpenseService" --type ts

# Look for actual method implementation
ast-grep --pattern 'clearCache() {
  $$$
}'

Length of output: 111


Script:

#!/bin/bash
# Let's search with broader patterns to understand the context better, style!

# Find all occurrences of clearCache in spec files
rg "clearCache" --type ts -A 3 -B 3 "spec.ts$"

# Find the service implementation
rg "CorporateCreditCardExpenseService" --type ts -A 5 -B 5

# Find all test files related to this component
fd "tasks.component.*spec.ts$"

Length of output: 75945


Script:

#!/bin/bash
# Let's find those test cases with style, thalaiva!

# Search for test cases using clearCache in tasks component specs
rg "clearCache" "src/app/fyle/dashboard/tasks/tasks.*spec.ts" -B 3 -A 3

# Look for the actual implementation of clearCache in the service
rg "clearCache" "src/app/core/services/corporate-credit-card-expense.service.ts" -B 3 -A 3

# Find test cases that might be using this service method
rg "corporateCreditCardExpenseService.*clearCache" --type ts -A 3 -B 3

Length of output: 9383

src/app/fyle/dashboard/tasks/tasks-2.component.spec.ts (2)

57-59: Mind it! These imports are perfectly placed!

The new imports are essential for testing the corporate card functionality. They bring in the required components and mock data.


Line range hint 208-227: Kabali style test case, I tell you!

The test case is solid, covering:

  • Service mocking for org settings
  • Popover creation verification
  • Component props validation

@@ -7,6 +7,7 @@
height="auto"
onloadedmetadata="this.muted = true"
oncanplay="this.play()"
poster="../../../assets/images/video-default-background.png"
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Listen carefully! The path needs more power, like my punch!

The relative path ../../../assets/images/video-default-background.png is like a weak villain. Let's make it stronger!

Make it absolute for better reliability:

-poster="../../../assets/images/video-default-background.png"
+poster="/assets/images/video-default-background.png"
📝 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
poster="../../../assets/images/video-default-background.png"
poster="/assets/images/video-default-background.png"

Comment on lines +229 to +246
it('handleEnrollmentSuccess(): should handle enrollment success and trigger subsequent actions', fakeAsync(() => {
corporateCreditCardExpenseService.clearCache.and.returnValue(of(null));

const mockPopover = {
present: jasmine.createSpy('present').and.resolveTo(),
onDidDismiss: jasmine.createSpy('onDidDismiss').and.resolveTo(),
};
popoverController.create.and.resolveTo(mockPopover as any);

component.handleEnrollmentSuccess();
tick();

expect(corporateCreditCardExpenseService.clearCache).toHaveBeenCalled();
expect(popoverController.create).toHaveBeenCalledWith({
component: CardAddedComponent,
cssClass: 'pop-up-in-center',
});
expect(mockPopover.present).toHaveBeenCalled();
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Style-u! Let's make this test even more powerful!

While the test covers the basic flow, consider adding these assertions:

  • Verify the popover dismissal handling
  • Add error case scenarios
 it('handleEnrollmentSuccess(): should handle enrollment success and trigger subsequent actions', fakeAsync(() => {
   corporateCreditCardExpenseService.clearCache.and.returnValue(of(null));

   const mockPopover = {
     present: jasmine.createSpy('present').and.resolveTo(),
-    onDidDismiss: jasmine.createSpy('onDidDismiss').and.resolveTo(),
+    onDidDismiss: jasmine.createSpy('onDidDismiss').and.resolveTo({ data: { success: true } }),
   };
   popoverController.create.and.resolveTo(mockPopover as any);

   component.handleEnrollmentSuccess();
   tick();

   expect(corporateCreditCardExpenseService.clearCache).toHaveBeenCalled();
   expect(popoverController.create).toHaveBeenCalledWith({
     component: CardAddedComponent,
     cssClass: 'pop-up-in-center',
   });
   expect(mockPopover.present).toHaveBeenCalled();
+  expect(mockPopover.onDidDismiss).toHaveBeenCalled();
+
+  // Error case
+  corporateCreditCardExpenseService.clearCache.and.returnValue(throwError(() => new Error('Cache clear failed')));
+  component.handleEnrollmentSuccess();
+  tick();
+  expect(mockPopover.present).not.toHaveBeenCalled();
 }));

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +468 to +487
const orgSettings$ = this.orgSettingsService.get();
this.isVisaRTFEnabled$ = orgSettings$.pipe(
map((orgSettings) => orgSettings.visa_enrollment_settings.allowed && orgSettings.visa_enrollment_settings.enabled)
);

this.isMastercardRTFEnabled$ = orgSettings$.pipe(
map(
(orgSettings) =>
orgSettings.mastercard_enrollment_settings.allowed && orgSettings.mastercard_enrollment_settings.enabled
)
);

this.isYodleeEnabled$ = forkJoin([orgSettings$, this.orgUserSettingsService.get()]).pipe(
map(
([orgSettings, orgUserSettings]) =>
orgSettings.bank_data_aggregation_settings.allowed &&
orgSettings.bank_data_aggregation_settings.enabled &&
orgUserSettings.bank_data_aggregation_settings.enabled
)
);
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

🛠️ Refactor suggestion

Mind it! Let's make this code as powerful as Thalaiva!

While the implementation is good, we can enhance it with these improvements:

  1. Add error handling for the observables
  2. Optimize the stream by sharing the orgSettings$ observable
 onAddCorporateCardClick(): void {
-  const orgSettings$ = this.orgSettingsService.get();
+  const orgSettings$ = this.orgSettingsService.get().pipe(
+    shareReplay(1),
+    catchError(err => {
+      console.error('Failed to fetch org settings:', err);
+      return of(null);
+    })
+  );

   this.isVisaRTFEnabled$ = orgSettings$.pipe(
+    filter(settings => !!settings),
     map((orgSettings) => orgSettings.visa_enrollment_settings.allowed && orgSettings.visa_enrollment_settings.enabled)
   );

   this.isMastercardRTFEnabled$ = orgSettings$.pipe(
+    filter(settings => !!settings),
     map(
       (orgSettings) =>
         orgSettings.mastercard_enrollment_settings.allowed && orgSettings.mastercard_enrollment_settings.enabled
     )
   );

   this.isYodleeEnabled$ = forkJoin([orgSettings$, this.orgUserSettingsService.get()]).pipe(
+    catchError(err => {
+      console.error('Failed to fetch settings:', err);
+      return of([null, null]);
+    }),
+    filter(([settings, userSettings]) => !!settings && !!userSettings),
     map(
       ([orgSettings, orgUserSettings]) =>
         orgSettings.bank_data_aggregation_settings.allowed &&
         orgSettings.bank_data_aggregation_settings.enabled &&
         orgUserSettings.bank_data_aggregation_settings.enabled
     )
   );

Why these changes, I tell you:

  1. shareReplay(1) prevents multiple HTTP requests when subscribing to the same observable
  2. Error handling with catchError prevents the app from crashing
  3. filter operator ensures we don't process null settings

Consider implementing a retry mechanism for failed API calls using retryWhen operator.

📝 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
const orgSettings$ = this.orgSettingsService.get();
this.isVisaRTFEnabled$ = orgSettings$.pipe(
map((orgSettings) => orgSettings.visa_enrollment_settings.allowed && orgSettings.visa_enrollment_settings.enabled)
);
this.isMastercardRTFEnabled$ = orgSettings$.pipe(
map(
(orgSettings) =>
orgSettings.mastercard_enrollment_settings.allowed && orgSettings.mastercard_enrollment_settings.enabled
)
);
this.isYodleeEnabled$ = forkJoin([orgSettings$, this.orgUserSettingsService.get()]).pipe(
map(
([orgSettings, orgUserSettings]) =>
orgSettings.bank_data_aggregation_settings.allowed &&
orgSettings.bank_data_aggregation_settings.enabled &&
orgUserSettings.bank_data_aggregation_settings.enabled
)
);
const orgSettings$ = this.orgSettingsService.get().pipe(
shareReplay(1),
catchError(err => {
console.error('Failed to fetch org settings:', err);
return of(null);
})
);
this.isVisaRTFEnabled$ = orgSettings$.pipe(
filter(settings => !!settings),
map((orgSettings) => orgSettings.visa_enrollment_settings.allowed && orgSettings.visa_enrollment_settings.enabled)
);
this.isMastercardRTFEnabled$ = orgSettings$.pipe(
filter(settings => !!settings),
map(
(orgSettings) =>
orgSettings.mastercard_enrollment_settings.allowed && orgSettings.mastercard_enrollment_settings.enabled
)
);
this.isYodleeEnabled$ = forkJoin([orgSettings$, this.orgUserSettingsService.get()]).pipe(
catchError(err => {
console.error('Failed to fetch settings:', err);
return of([null, null]);
}),
filter(([settings, userSettings]) => !!settings && !!userSettings),
map(
([orgSettings, orgUserSettings]) =>
orgSettings.bank_data_aggregation_settings.allowed &&
orgSettings.bank_data_aggregation_settings.enabled &&
orgUserSettings.bank_data_aggregation_settings.enabled
)
);

Copy link

@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

🔭 Outside diff range comments (1)
src/app/fyle/dashboard/tasks/tasks-2.component.spec.ts (1)

Line range hint 208-227: Magizhchi! The test is good, but let's make it legendary!

The test covers the happy path like a well-choreographed action sequence, but we need to handle the villain scenarios too!

Add these test cases to make it blockbuster:

  1. Error handling when service calls fail
  2. Edge case when card enrollment is disabled
  3. Cancellation scenario when user dismisses the popover
it('should handle service error gracefully', () => {
  orgSettingsService.get.and.returnValue(throwError(() => new Error()));
  component.onAddCorporateCardClick();
  expect(popoverController.create).not.toHaveBeenCalled();
});
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between df00248 and 0518a96.

📒 Files selected for processing (5)
  • android/.idea/runConfigurations.xml (1 hunks)
  • src/app/auth/sign-in/sign-in.page.html (1 hunks)
  • src/app/fyle/dashboard/tasks/tasks-2.component.spec.ts (4 hunks)
  • src/app/fyle/dashboard/tasks/tasks.component.setup.spec.ts (1 hunks)
  • src/app/fyle/dashboard/tasks/tasks.component.ts (1 hunks)
🧰 Additional context used
📓 Learnings (1)
src/app/fyle/dashboard/tasks/tasks-2.component.spec.ts (1)
Learnt from: bistaastha
PR: fylein/fyle-mobile-app#3240
File: src/app/fyle/manage-corporate-cards/manage-corporate-cards.page.spec.ts:200-200
Timestamp: 2024-11-12T04:53:12.395Z
Learning: In 'src/app/fyle/manage-corporate-cards/manage-corporate-cards.page.spec.ts', moving 'component.isAddCorporateCardVisible$ = of(true);' to the top-level beforeEach block causes tests to fail, so mock values need to be set in individual tests.
🔇 Additional comments (3)
android/.idea/runConfigurations.xml (1)

6-13: Mind it! These configuration changes are perfectly balanced, like my signature sunglasses!

The addition of JUnit configuration producers to the ignored list is a strategic move to prevent test configuration conflicts. But remember what I always say - "When something comes in your way, don't ask it to move. Ask yourself why you can't move it!"

Let me verify if these changes affect any existing test configurations:

✅ Verification successful

I need to see the complete configuration file and related test configurations to make a solid verification, like checking all angles before performing my signature move! 🕶️


Mind it! Before making my final verdict, I need to see if these configuration changes are in harmony with the test setup, like checking all the pieces before the grand finale! 🕶️


Mind it! These JUnit configuration changes are perfectly safe, like my signature stunts!

The changes in runConfigurations.xml are simply telling Android Studio which test configuration producers to ignore, while our build.gradle shows proper JUnit setup with testImplementation "junit:junit:$junitVersion". The example test files are present and untouched. When you want to make a change, make it with style! 🕶️

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for any existing JUnit configurations that might be affected
find . -type f -name "*.xml" -exec grep -l "junit" {} \;

Length of output: 97


Script:

#!/bin/bash
# Let's check the content of runConfigurations.xml to understand the full context
cat ./android/.idea/runConfigurations.xml

Length of output: 1008


Script:

#!/bin/bash
# Let's also check if there are any other configuration files that might be impacted
fd -e xml -x grep -l "configuration" {} \;

Length of output: 45


Script:

#!/bin/bash
# Check for any test-related files that might be affected
fd -e gradle -e xml -x grep -l "test" {} \;

Length of output: 73


Script:

#!/bin/bash
# Let's check the test configurations in build.gradle
cat ./android/app/build.gradle

Length of output: 1692


Script:

#!/bin/bash
# Let's see if there are any existing JUnit test files
fd -e java -e kt -x grep -l "@Test" {} \;

Length of output: 203

src/app/fyle/dashboard/tasks/tasks.component.setup.spec.ts (1)

73-73: When I do something, I do it in style! This test spy update is perfect!

Adding clearCache to the spy object shows you understand the importance of thorough test coverage. Like I always say, "Testing is not just a process, it's an art!"

Let me check if this method is properly tested:

✅ Verification successful

Let me style-check this method's implementation and test coverage, thalaiva! 🕶️


Mind it! This spy addition is perfectly synchronized with the codebase, like a well-choreographed action sequence!

The clearCache method in the service returns an Observable of void, and the tasks component is using it stylishly before showing the card-added modal. Adding this method to the spy object is absolutely necessary for the test coverage - when I do testing, I do complete testing! 🕶️

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for test coverage of clearCache method
rg -l "clearCache.*\(" --type ts

Length of output: 1175


Script:

#!/bin/bash
# Let's check the implementation of clearCache in corporate-credit-card-expense.service.ts
ast-grep --pattern 'clearCache() {
  $$$
}'

# And check if it's tested in other spec files
rg "clearCache" "src/app/core/services/corporate-credit-card-expense.service.spec.ts"

Length of output: 129


Script:

#!/bin/bash
# Mind it! Let's check the service file with more style
rg -A 5 "clearCache" "src/app/core/services/corporate-credit-card-expense.service.ts"

# And let's see how this method is being used in tasks component
rg -A 5 "clearCache" "src/app/fyle/dashboard/tasks/tasks.component.ts"

Length of output: 765

src/app/fyle/dashboard/tasks/tasks-2.component.spec.ts (1)

118-119: Mind it! Network setup looks perfect!

The network connectivity mocks are set up with style, just like how I handle my stunts - with precision and grace.

@@ -7,6 +7,7 @@
height="auto"
onloadedmetadata="this.muted = true"
oncanplay="this.play()"
poster="../../../assets/images/video-default-background.png"
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Listen carefully! The path to success should be absolute, just like my path to stardom!

The poster attribute is a stylish addition, but the relative path ../../../assets/images/video-default-background.png could break if the component structure changes.

Make it robust like my punch dialogues with this change:

-        poster="../../../assets/images/video-default-background.png"
+        poster="/assets/images/video-default-background.png"
📝 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
poster="../../../assets/images/video-default-background.png"
poster="/assets/images/video-default-background.png"

Comment on lines +229 to +246
it('handleEnrollmentSuccess(): should handle enrollment success and trigger subsequent actions', fakeAsync(() => {
corporateCreditCardExpenseService.clearCache.and.returnValue(of(null));

const mockPopover = {
present: jasmine.createSpy('present').and.resolveTo(),
onDidDismiss: jasmine.createSpy('onDidDismiss').and.resolveTo(),
};
popoverController.create.and.resolveTo(mockPopover as any);

component.handleEnrollmentSuccess();
tick();

expect(corporateCreditCardExpenseService.clearCache).toHaveBeenCalled();
expect(popoverController.create).toHaveBeenCalledWith({
component: CardAddedComponent,
cssClass: 'pop-up-in-center',
});
expect(mockPopover.present).toHaveBeenCalled();
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Style-u! The test is powerful, but needs more punch!

Like how I track my enemies in movies, we should track our user actions in code!

Add tracking verification to make this test complete:

it('handleEnrollmentSuccess(): should track successful enrollment', fakeAsync(() => {
  spyOn(trackingService, 'cardEnrollmentSuccess');
  component.handleEnrollmentSuccess();
  tick();
  expect(trackingService.cardEnrollmentSuccess).toHaveBeenCalled();
}));

Comment on lines +468 to +487
const orgSettings$ = this.orgSettingsService.get();
this.isVisaRTFEnabled$ = orgSettings$.pipe(
map((orgSettings) => orgSettings.visa_enrollment_settings.allowed && orgSettings.visa_enrollment_settings.enabled)
);

this.isMastercardRTFEnabled$ = orgSettings$.pipe(
map(
(orgSettings) =>
orgSettings.mastercard_enrollment_settings.allowed && orgSettings.mastercard_enrollment_settings.enabled
)
);

this.isYodleeEnabled$ = forkJoin([orgSettings$, this.orgUserSettingsService.get()]).pipe(
map(
([orgSettings, orgUserSettings]) =>
orgSettings.bank_data_aggregation_settings.allowed &&
orgSettings.bank_data_aggregation_settings.enabled &&
orgUserSettings.bank_data_aggregation_settings.enabled
)
);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Kabali da! The code needs proper cleanup!

Like how I clean up the streets in my movies, we need to clean up our subscriptions!

Add proper error handling and subscription management:

-    forkJoin([this.isVisaRTFEnabled$, this.isMastercardRTFEnabled$, this.isYodleeEnabled$]).subscribe(
+    forkJoin([this.isVisaRTFEnabled$, this.isMastercardRTFEnabled$, this.isYodleeEnabled$])
+      .pipe(
+        catchError((error) => {
+          this.showToastMessage('Failed to load card settings', 'failure');
+          return EMPTY;
+        }),
+        takeUntil(this.destroy$)
+      )
+      .subscribe(

Don't forget to:

  1. Add private destroy$ = new Subject<void>(); as class property
  2. Implement ngOnDestroy to call this.destroy$.next(); this.destroy$.complete();

Committable suggestion skipped: line range outside the PR's diff.

<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
Copy link
Contributor

Choose a reason for hiding this comment

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

lets remove these lines if you are not making any native changes

@bistaastha bistaastha changed the base branch from FYLE-cc-card-task to master December 23, 2024 07:50
@github-actions github-actions bot added size/L Large PR and removed size/M Medium PR labels Dec 23, 2024
Copy link

@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: 9

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e636a7c and 83d9fa8.

📒 Files selected for processing (5)
  • src/app/core/services/tasks.service.spec.ts (3 hunks)
  • src/app/core/services/tasks.service.ts (6 hunks)
  • src/app/fyle/dashboard/tasks/tasks-1.component.spec.ts (6 hunks)
  • src/app/fyle/dashboard/tasks/tasks-2.component.spec.ts (5 hunks)
  • src/app/fyle/dashboard/tasks/tasks.component.ts (7 hunks)
🧰 Additional context used
📓 Learnings (1)
src/app/fyle/dashboard/tasks/tasks-2.component.spec.ts (1)
Learnt from: bistaastha
PR: fylein/fyle-mobile-app#3240
File: src/app/fyle/manage-corporate-cards/manage-corporate-cards.page.spec.ts:200-200
Timestamp: 2024-11-12T04:53:12.395Z
Learning: In 'src/app/fyle/manage-corporate-cards/manage-corporate-cards.page.spec.ts', moving 'component.isAddCorporateCardVisible$ = of(true);' to the top-level beforeEach block causes tests to fail, so mock values need to be set in individual tests.
🔇 Additional comments (21)
src/app/fyle/dashboard/tasks/tasks-2.component.spec.ts (4)

2-2: Magizhchi! The import looks correct.
All good here, Thala! The use of PopoverController from '@ionic/angular' is well-suited for testing popovers.


51-59: All set with these imports.
Great additions, my friend. These new references (e.g., AddCorporateCardComponent, CardAddedComponent) align well with the updated tests.


83-86: No problem with the popoverController spy.
This spy object initialization is neat and helps ensure we’re testing popover interactions effectively.


110-119: Solid injection.
Injecting PopoverController for the test suite is cleanly done, and integration with the test bed is straightforward.

src/app/core/services/tasks.service.ts (4)

323-323: New addCorporateCard addition is neat.
Incorporating getAddCorporateCardTask into forkJoin is a solid approach to unify tasks.


336-336: Properly mapped addCorporateCard.
No issues spotted here, Thala. The new addition merges seamlessly with existing tasks.


347-348: Comprehensive totalTaskCount.
Adding setCommuteDetails and addCorporateCard to the count ensures an accurate tally of tasks.


372-373: The chain of tasks is unstoppable!
Chaining addCorporateCard with other tasks is well-placed. No concerns.

src/app/core/services/tasks.service.spec.ts (3)

44-44: New corporate card mocks imported.
No friction here. Mocks look ready for their cameo in the test.


432-444: Test coverage for getAddCorporateCardTask with no enrolled cards.
Perfect scenario test, my friend. Ensures the function returns a valid task.


446-453: Test coverage for getAddCorporateCardTask with enrolled cards.
This is a neat negative scenario ensuring an empty array is returned. Paired well with the previous test.

src/app/fyle/dashboard/tasks/tasks-1.component.spec.ts (5)

35-35: taskCtaData11 introduction is smooth.
This new CTA helps test addCorporateCard tasks. Nicely done.


45-46: Adding OrgSettingsService references looks correct.
No issues: the new imports mesh well with the rest of the test suite.


66-66: Introducing the orgSettingsService spy.
All good. This spy will help in verifying any org settings logic.


341-341: Spying on onAddCorporateCardClick.
One step closer to verifying card popover interactions.


483-499: Rockstar test for addCorporateCard CTA.
Ensures onAddCorporateCardClick is called. That’s how you verify real user flows, my friend.

src/app/fyle/dashboard/tasks/tasks.component.ts (5)

5-5: Importing RefresherEventDetail is good.
This improves clarity on the typed event structure. Well done.


75-80: Visually see your new Observables.
You’re introducing isVisaRTFEnabled$, isMastercardRTFEnabled$, and isYodleeEnabled$. This separation is clean.


99-103: Constructor injection spree!
Adding orgUserSettingsService, orgService, popoverController, and creditCardExpenseService is fully cohesive.


396-410: handleEventsWithoutTaskConfig
Such a function decouples the event logic gracefully. Good layering.


421-428: Mighty calls to handle both config and non-config events.
This pattern is flexible and maintainable. Good to see them in action.

Comment on lines +208 to +228
it('onAddCorporateCardClick(): should open card popover', () => {
orgSettingsService.get.and.returnValue(of(orgSettingsPendingRestrictions));
orgUserSettingsService.get.and.returnValue(of(orgUserSettingsData));
const addCardPopoverSpy = jasmine.createSpyObj('HTMLIonPopoverElement', ['present', 'onDidDismiss']);
addCardPopoverSpy.present.and.resolveTo();
addCardPopoverSpy.onDidDismiss.and.resolveTo({ success: true });
popoverController.create.and.resolveTo(addCardPopoverSpy);
spyOn(component, 'handleEnrollmentSuccess');

fixture.detectChanges();
component.onAddCorporateCardClick();
expect(popoverController.create).toHaveBeenCalledOnceWith({
component: AddCorporateCardComponent,
cssClass: 'fy-dialog-popover',
componentProps: {
isVisaRTFEnabled: true,
isMastercardRTFEnabled: true,
isYodleeEnabled: true,
},
});
});
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Aiyoo! Consider adding negative path coverage.
The test ensures the popover is presented on success. Testing an error scenario or a dismissed popover would strengthen the suite further.

Comment on lines +230 to +248
it('handleEnrollmentSuccess(): should handle enrollment success and trigger subsequent actions', fakeAsync(() => {
corporateCreditCardExpenseService.clearCache.and.returnValue(of(null));

const mockPopover = {
present: jasmine.createSpy('present').and.resolveTo(),
onDidDismiss: jasmine.createSpy('onDidDismiss').and.resolveTo(),
};
popoverController.create.and.resolveTo(mockPopover as any);

component.handleEnrollmentSuccess();
tick();

expect(corporateCreditCardExpenseService.clearCache).toHaveBeenCalled();
expect(popoverController.create).toHaveBeenCalledWith({
component: CardAddedComponent,
cssClass: 'pop-up-in-center',
});
expect(mockPopover.present).toHaveBeenCalled();
}));
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Looks stylish!
Your test for handleEnrollmentSuccess covers the happy path well. However, consider verifying what happens if clearCache or popover creation fails, to cover edge cases.

Comment on lines +536 to +552
getAddCorporateCardTask(): Observable<DashboardTask[]> {
return forkJoin([this.orgSettingsService.get(), this.corporateCreditCardExpenseService.getCorporateCards()]).pipe(
map(([orgSettings, cards]) => {
const isRtfEnabled =
(orgSettings.visa_enrollment_settings.allowed && orgSettings.visa_enrollment_settings.enabled) ||
(orgSettings.mastercard_enrollment_settings.allowed && orgSettings.mastercard_enrollment_settings.enabled);
const isCCCEnabled =
orgSettings.corporate_credit_card_settings.allowed && orgSettings.corporate_credit_card_settings.enabled;
const rtfCards = cards.filter((card) => card.is_visa_enrolled || card.is_mastercard_enrolled);
if (isRtfEnabled && isCCCEnabled && rtfCards.length === 0) {
return this.mapAddCorporateCardTask();
} else {
return [] as DashboardTask[];
}
})
);
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Superstar feature: getAddCorporateCardTask.
• Nicely checks orgSettings and card statuses.
• Potential improvement: handle errors from orgSettings or the corporate card call to avoid silent failures.

Comment on lines +587 to +603
mapAddCorporateCardTask(): DashboardTask[] {
const task = [
{
hideAmount: true,
header: 'Add Corporate Card',
subheader: 'Add your corporate card to track expenses.',
icon: TaskIcon.CARD,
ctas: [
{
content: 'Add Card',
event: TASKEVENT.addCorporateCard,
},
],
},
];
return task;
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

mapAddCorporateCardTask is a star cameo.
The structure is consistent with other tasks. Perhaps add a quick test to confirm each CTA property is correct.

Comment on lines +94 to +97
orgSettingsService.get.and.returnValue(of(orgSettingsPendingRestrictions));
component.isVisaRTFEnabled$ = of(true);
component.isMastercardRTFEnabled$ = of(true);
component.isYodleeEnabled$ = of(true);
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Simulating RTF and Yodlee flags.
Ensuring the test environment sets these flags to true is straightforward. Consider adding an additional test for false flags to be thorough.

Comment on lines +40 to +43
import { CorporateCreditCardExpenseService } from 'src/app/core/services/corporate-credit-card-expense.service';
import { OrgUserSettingsService } from 'src/app/core/services/org-user-settings.service';
import { AddCorporateCardComponent } from '../../manage-corporate-cards/add-corporate-card/add-corporate-card.component';
import { CardAddedComponent } from '../../manage-corporate-cards/card-added/card-added.component';
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

New imports for corporate card flow.
The additions align with your popover approach. Keep an eye on error handling if popover fails to load.

Comment on lines +377 to +394
handleEventsWithTaskConfig(taskCta: TaskCta, task: DashboardTask): void {
switch (taskCta.event) {
case TASKEVENT.expensesAddToReport:
this.onExpensesToReportTaskClick();
break;
case TASKEVENT.openDraftReports:
this.onOpenDraftReportsTaskClick(taskCta, task);
break;
case TASKEVENT.openSentBackReport:
this.onSentBackReportTaskClick(taskCta, task);
break;
case TASKEVENT.reviewExpenses:
this.onReviewExpensesTaskClick();
break;
case TASKEVENT.openTeamReport:
this.onTeamReportsTaskClick(taskCta, task);
break;
case TASKEVENT.openPotentialDuplicates:
this.onPotentialDuplicatesTaskClick();
break;
case TASKEVENT.openSentBackAdvance:
this.onSentBackAdvanceTaskClick(taskCta, task);
break;
default:
break;
}
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

handleEventsWithTaskConfig
A separate switch handling distinct events is well-organized. Consider including fallback logging if an event is not recognized.

Comment on lines +455 to +465
handleEnrollmentSuccess(): void {
this.corporateCreditCardExpenseService.clearCache().subscribe(async () => {
const cardAddedModal = await this.popoverController.create({
component: CardAddedComponent,
cssClass: 'pop-up-in-center',
});

await cardAddedModal.present();
await cardAddedModal.onDidDismiss();
});
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Kabali da! handleEnrollmentSuccess is unstoppable.
• Properly calls clearCache.
• Popover flow is nice.
• For a robust approach, handle error callbacks from clearCache.

Comment on lines +467 to +509
onAddCorporateCardClick(): void {
const orgSettings$ = this.orgSettingsService.get();
this.isVisaRTFEnabled$ = orgSettings$.pipe(
map((orgSettings) => orgSettings.visa_enrollment_settings.allowed && orgSettings.visa_enrollment_settings.enabled)
);

this.isMastercardRTFEnabled$ = orgSettings$.pipe(
map(
(orgSettings) =>
orgSettings.mastercard_enrollment_settings.allowed && orgSettings.mastercard_enrollment_settings.enabled
)
);

this.isYodleeEnabled$ = forkJoin([orgSettings$, this.orgUserSettingsService.get()]).pipe(
map(
([orgSettings, orgUserSettings]) =>
orgSettings.bank_data_aggregation_settings.allowed &&
orgSettings.bank_data_aggregation_settings.enabled &&
orgUserSettings.bank_data_aggregation_settings.enabled
)
);
forkJoin([this.isVisaRTFEnabled$, this.isMastercardRTFEnabled$, this.isYodleeEnabled$]).subscribe(
async ([isVisaRTFEnabled, isMastercardRTFEnabled, isYodleeEnabled]) => {
const addCorporateCardPopover = await this.popoverController.create({
component: AddCorporateCardComponent,
cssClass: 'fy-dialog-popover',
componentProps: {
isVisaRTFEnabled,
isMastercardRTFEnabled,
isYodleeEnabled,
},
});

await addCorporateCardPopover.present();
const popoverResponse = (await addCorporateCardPopover.onDidDismiss()) as { success: boolean };

if (popoverResponse.success) {
this.handleEnrollmentSuccess();
}
}
);
}

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

A full-blown function for onAddCorporateCardClick.
• Thorough approach, reading org settings, user settings, and then presenting the popover.
• Consider adding error handling for each subscription to gracefully handle failures.

Copy link

Unit Test Coverage % values
Statements 96% ( 19365 / 20171 )
Branches 91.11% ( 10690 / 11733 )
Functions 94.3% ( 5762 / 6110 )
Lines 96.04% ( 18492 / 19254 )

@bistaastha bistaastha merged commit c0c9b52 into master Dec 24, 2024
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
size/L Large PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants