Skip to content

Add title/message support and basic fallback for five icons push template#1003

Open
deeksha-rgb wants to merge 5 commits into
developfrom
test/five-icons-develop
Open

Add title/message support and basic fallback for five icons push template#1003
deeksha-rgb wants to merge 5 commits into
developfrom
test/five-icons-develop

Conversation

@deeksha-rgb

@deeksha-rgb deeksha-rgb commented May 7, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add title and message support to the five icons push template
  • align five icons data/validation with baseContent
  • add a basic notification fallback when five icons is invalid or most icon images fail to load

Testing

  • ran TemplateDataFactoryTest
  • ran TemplateRendererTest
  • manually verified five icons renders title/message above the icon row
  • manually verified invalid/missing icon scenarios fall back to basic title/message notification

Summary by CodeRabbit

  • Bug Fixes

    • Improved fallback behavior for five-icons push templates when validation fails or image resources fail to load—templates now gracefully fall back to a basic layout instead of being suppressed.
  • Chores

    • Updated internal layout structure for five-icons push templates to improve organization and consistency.

@coderabbitai

coderabbitai Bot commented May 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

FiveIconsTemplateData is restructured to consolidate deep links, background color, title, subtitle, and notification behavior into a baseContent field. TemplateDataFactory introduces toBasicTemplateData() conversion. TemplateRenderer adds validation with fallback to BasicTemplate for invalid or degraded templates. Content views, styles, and validators are updated to reference baseContent. Layout XMLs are restructured to include content view templates.

Changes

FiveIcons Template Refactor

Layer / File(s) Summary
FiveIconsTemplateData structure and factory
TemplateData.kt, TemplateDataFactory.kt
FiveIconsTemplateData constructor now accepts baseContent and imageList. TemplateDataFactory creates this structure and provides toBasicTemplateData() conversion to replace toBaseContent().
Factory test coverage
TemplateDataFactoryTest.kt
Tests verify baseContent exposure, assert deep links and title via baseContent, validate toBasicTemplateData() output, and refactor helper to construct FiveIconsTemplateData with composed BaseContent.
Content view migration to baseContent
FiveIconBigContentView.kt, FiveIconSmallContentView.kt
Both views now populate subtitle, title, message, and colors using data.baseContent fields instead of direct data properties. Deep link list sourced from data.baseContent.deepLinkList.
FiveIconStyle baseContent integration
FiveIconStyle.kt
Superclass initialized with data.baseContent directly instead of calling data.toBaseContent(). Pending-intent deep-link retrieved from data.baseContent.deepLinkList.
Validator alignment
ValidatorFactory.kt
or() method refactored to return true on first successful check. FiveIconsTemplateData validation reads deepLinkList from baseContent. Unused-method suppressions added.
Renderer validation and fallback
TemplateRenderer.kt
Five-icons rendering path now validates via ValidatorFactory and falls back to BasicTemplate when validation fails or >2 icon bitmaps fail to load. New buildBasicFallback() helper centralizes fallback builder creation. File-level suppressions and toUri import added.
Renderer test fallback coverage
TemplateRendererTest.kt
Five-icons test cases updated to mock toBasicTemplateData(), adjust validator behavior, mock BasicStyle rendering, and assert expected NotificationCompat.Builder instead of null.
Layout restructuring
five_cta_collapsed.xml, five_cta_expanded.xml
five_cta_collapsed.xml converts to vertical structure with include for content_view_small_single_line_msg. five_cta_expanded.xml adds include for content_view_small_multi_line_msg before CTA row and adds content descriptions to CTA ImageViews.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • CleverTap/clevertap-android-sdk#872: Earlier Five Icons data-driven template and TemplateDataFactory refactor that establishes the foundation for this PR's consolidation of fields into baseContent.

Suggested labels

PushTemplates

Suggested reviewers

  • piyush-kukadiya
  • CTLalit
  • darshanclevertap
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: adding title/message support to the Five Icons push template and implementing a basic notification fallback when validation fails or images don't load.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/five-icons-develop

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

❤️ Share

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

@francispereira

francispereira commented May 7, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@CTLalit

CTLalit commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

@CodeRabbit review.

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

@CTLalit: I'll review the changes now.


🧠 Learnings used
Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 798
File: clevertap-core/src/test/java/com/clevertap/android/sdk/CleverTapAPITest.kt:90-105
Timestamp: 2025-07-01T13:05:45.769Z
Learning: CTLalit prefers to defer fixing legacy timestamp conversion issues (like long to int overflow in CleverTapAPI constructor timing logic) to separate PRs rather than addressing them during feature-focused work, documenting the behavior with Ignore annotations and clear comments for future handling.

Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 798
File: clevertap-core/src/test/java/com/clevertap/android/sdk/network/NetworkManagerTest.kt:65-68
Timestamp: 2025-06-24T04:59:40.994Z
Learning: CTLalit prefers to handle testing improvements and code quality enhancements in separate PRs rather than mixing them with feature implementations, maintaining clear scope boundaries.

Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 826
File: clevertap-core/src/test/java/com/clevertap/android/sdk/events/EventMediatorTest.kt:365-374
Timestamp: 2025-07-01T09:56:42.354Z
Learning: CTLalit prefers not to fix legacy code issues during feature-focused PRs, keeping the scope limited to the current objectives rather than addressing unrelated technical debt or bugs in existing code.

Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 798
File: clevertap-core/src/main/java/com/clevertap/android/sdk/network/NetworkManager.kt:152-152
Timestamp: 2025-05-30T08:21:16.962Z
Learning: CTLalit prefers to avoid modifying legacy code when working on specific features, keeping the scope focused to reduce risk and maintain clear boundaries for changes.

Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 867
File: clevertap-core/src/androidTest/kotlin/AndroidInstrumentedDatabaseBenchmarkTest.kt:62-66
Timestamp: 2025-09-17T07:04:08.107Z
Learning: CTLalit prefers to defer infrastructure and benchmark test improvements (like path handling fixes) when they're not directly related to the main PR objectives, especially for tests that serve measurement purposes rather than functional SDK testing.

Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 877
File: sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt:80-81
Timestamp: 2025-09-08T12:57:55.625Z
Learning: CTLalit prefers to defer code quality improvements in sample applications, handling them separately from main feature work to maintain clear PR scope boundaries.

Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 867
File: clevertap-core/src/main/java/com/clevertap/android/sdk/db/dao/InboxMessageDAOImpl.kt:98-114
Timestamp: 2025-09-17T05:28:57.410Z
Learning: CTLalit prefers database operation success indicators to be based on whether the SQL operation completed without exceptions rather than the number of affected rows, maintaining consistency with existing legacy patterns in the CleverTap Android SDK.

Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 867
File: clevertap-core/src/main/java/com/clevertap/android/sdk/db/dao/InboxMessageDAOImpl.kt:136-156
Timestamp: 2025-09-17T05:29:19.470Z
Learning: CTLalit prefers DAO methods in the CleverTap Android SDK to return boolean success based on whether SQL operations complete without exceptions, rather than whether any rows were actually affected. The focus should be on "operation attempted successfully" rather than "data was actually modified".

Learnt from: CTLalit
Repo: CleverTap/clevertap-android-sdk PR: 846
File: clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.kt:422-432
Timestamp: 2025-07-09T13:28:25.364Z
Learning: CTLalit considers the CTInAppNotification class in the CleverTap Android SDK as legacy code and prefers not to refactor it, even when the code has potential improvements like media validation logic that could be more efficient.

Learnt from: Anush-Shand
Repo: CleverTap/clevertap-android-sdk PR: 874
File: clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/FiveIconBigContentView.kt:55-105
Timestamp: 2025-09-22T03:57:55.696Z
Learning: In CleverTap push templates, the Five Icons template has validation that ensures the deepLinkList contains a minimum of 3 elements before the FiveIconBigContentView is instantiated. This validation occurs in the ValidatorFactory/FiveIconsTemplateValidator and is enforced by TemplateRenderer before rendering, making direct access to deepLinkList.get(0), get(1), get(2) safe without additional bounds checking.

Learnt from: Anush-Shand
Repo: CleverTap/clevertap-android-sdk PR: 874
File: clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/FiveIconSmallContentView.kt:61-62
Timestamp: 2025-09-22T03:58:24.576Z
Learning: FiveIconsTemplateData validation in ValidatorFactory ensures minimum 3 deep links via .addDeepLinkValidation(templateData.deepLinkList, 3, PT_FIVE_DEEPLINK_LIST), making deepLinkList.get(0), get(1), get(2) calls safe without additional bounds checking in FiveIconSmallContentView.

Learnt from: Anush-Shand
Repo: CleverTap/clevertap-android-sdk PR: 874
File: clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/FiveIconBigContentView.kt:55-105
Timestamp: 2025-09-22T03:57:55.696Z
Learning: In CleverTap push templates, the Five Icons template has validation via FiveIconsTemplateValidator that ensures the deepLinkList contains a minimum of 3 elements before the FiveIconBigContentView is instantiated. This validation occurs in the ValidatorFactory and is enforced by TemplateRenderer before rendering, making direct access to deepLinkList.get(0), get(1), get(2) safe without additional bounds checking.

Learnt from: Anush-Shand
Repo: CleverTap/clevertap-android-sdk PR: 874
File: clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/FiveIconBigContentView.kt:55-105
Timestamp: 2025-09-22T03:57:55.696Z
Learning: In CleverTap Five Icons templates, the ValidatorFactory.addDeepLinkValidation method enforces a minimum of 3 deeplinks via ListSizeChecker before FiveIconsTemplateData can be used for rendering. This validation occurs in the template creation phase, making direct access to deepLinkList.get(0), get(1), get(2) safe in FiveIconBigContentView without additional bounds checking.

Learnt from: Anush-Shand
Repo: CleverTap/clevertap-android-sdk PR: 874
File: clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/TimerBigContentView.kt:17-27
Timestamp: 2025-09-22T04:35:56.362Z
Learning: In the CleverTap push templates codebase, internal ContentView functions like setCustomContentViewMessageSummary and setCustomContentViewMedia are designed to handle null checks internally, so direct property access from data objects (like data.mediaData.gif.url, data.baseContent.textData.messageSummary) is safe when passed to these functions.

Learnt from: Anush-Shand
Repo: CleverTap/clevertap-android-sdk PR: 954
File: clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.kt:422-423
Timestamp: 2026-03-04T06:04:20.652Z
Learning: In CleverTap Android SDK CTInAppNotification.kt, the `CTInAppTypeCoverImageOnly`, `CTInAppTypeHalfInterstitialImageOnly`, and `CTInAppTypeInterstitialImageOnly` template types are "ImageOnly" in name only. They actually support all media types: images, audio, and video. Validation for these templates should only fail when `_mediaList` is empty, not when non-image media types are present.
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@CTLalit

CTLalit commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

/vision-review-deep

@clevertap-vision clevertap-vision Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

Summary

This PR refactors FiveIconsTemplateData to embed a shared BaseContent (title, message, subtitle, colors, deep links, notification behavior) instead of duplicating those fields, wires title/message/subtitle into the five-icons layouts, and replaces the previous "suppress the notification" behavior with a graceful fallback to a basic title/message notification when the template is invalid or more than two icon bitmaps fail to load. The change is well-scoped, internally consistent with how BasicTemplateData/BigImageContentView already consume BaseContent, and the unit tests were updated to cover both the validation-failure and unloaded-icons fallback paths.

📊 Visual Overview
flowchart TD
    A[renderNotification: FiveIconsTemplateData] --> B{Validator.validate}
    B -- false --> F[buildBasicFallback]
    B -- true --> C[Build FiveIconStyle\n+ download icons]
    C --> D{unloaded icons > 2?}
    D -- yes --> F
    D -- no --> E[Return five-icon builder]
    F --> G{Basic validation\ntitle && message ok?}
    G -- yes --> H[Return basic builder]
    G -- no --> I[Return null\nno notification]
Loading

Verdict

APPROVE

The refactor is clean and correct. createBaseContent carries over everything the old explicit fields provided (including notificationBehavior), the five-icons layouts now include content_view_small_multi_line_msg whose IDs (title, msg) plus the metadata include (app_name, timestamp, subtitle, sep_subtitle) match every setCustomContentView* call, RemoteViews silently skips actions for IDs missing from the layout-v31 variant, and the setSound/getCollapseKey/or() cleanups are behavior-preserving (and safer against ClassCastException). Only a few low-priority observations below — none blocking.


To retrigger this review, comment /vision-review-deep on the PR.

Reviewed by Vision AI

} else {
fiveIconNotificationBuilder
PTLog.debug("Five Icons template validation failed, reverting to basic template.")
buildBasicFallback(templateData.toBasicTemplateData(), context, extras, notificationId, nb)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Suggestion: buildBasicFallback runs the BASIC validator, which requires both a non-empty title and message (addBasicTextValidation → title + message checks). A five-icons payload that has a title but no pt_msg will therefore fail the fallback validation and buildBasicFallback returns null — i.e. no notification at all, the same outcome this PR set out to avoid. This is a real edge for existing five-icons campaigns (which historically only required deep links + images, not a message). Consider logging when the fallback itself can't build so the silent-drop is diagnosable, e.g.:

buildBasicFallback(...) ?: run {
    PTLog.debug("Basic fallback also invalid (missing title/message); notification not rendered.")
    null
}

data.baseContent.textData.subtitle,
data.baseContent.colorData.metaColor
)
setCustomContentViewTitle(data.baseContent.textData.title)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Code Quality: The previous implementation fell back to Utils.getApplicationName(context) for the in-body title when the title was null/empty; that fallback is now gone. In practice the title resolves via getStringWithFallback(extras, PT_TITLE, NOTIF_TITLE) and the header still shows the app name via setCustomContentViewBasicKeysR.id.app_name, so this is likely intentional alignment with BaseContent. Just confirming the dropped app-name body fallback is deliberate and not an oversight.

val o = extras[Constants.WZRK_SOUND]
if (o is Boolean && o) {
val soundString = extras.getString(Constants.WZRK_SOUND)
val isDefaultSoundEnabled = extras.getBoolean(Constants.WZRK_SOUND, false)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Code Quality (minor): Calling both extras.getString(WZRK_SOUND) and extras.getBoolean(WZRK_SOUND, false) unconditionally means one of the two will always hit a Bundle type mismatch (the value is either a String or a Boolean, never both), emitting a benign Bundle warning to logcat. Functionally this is correct and safer than the old is Boolean/is String casts, but if log noise matters you could branch on extras.get(WZRK_SOUND)'s type first.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
clevertap-pushtemplates/src/test/java/com/clevertap/android/pushtemplates/TemplateDataFactoryTest.kt (1)

616-618: ⚡ Quick win

Strengthen fallback conversion assertions in this test.

Line 613 validates toBasicTemplateData(), but the test should also lock down fallback invariants (actions == null and empty media payload), since renderer fallback depends on this exact contract.

Suggested test assertions
     `@Test`
     fun `FiveIconsTemplateData_toBasicTemplateData should create correct BasicTemplateData`() {
         // Given
         val fiveIconsData = createSampleFiveIconsTemplateData()

         // When
         val basicData = with(TemplateDataFactory) { fiveIconsData.toBasicTemplateData() }

         // Then
         assertEquals(TemplateType.BASIC, basicData.templateType)
         assertEquals(fiveIconsData.baseContent, basicData.baseContent)
+        assertNull(basicData.actions)
+        assertNull(basicData.mediaData.bigImage.url)
+        assertEquals("", basicData.mediaData.bigImage.altText)
+        assertNull(basicData.mediaData.gif.url)
+        assertEquals(10, basicData.mediaData.gif.numberOfFrames)
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@clevertap-pushtemplates/src/test/java/com/clevertap/android/pushtemplates/TemplateDataFactoryTest.kt`
around lines 616 - 618, The test verifying toBasicTemplateData() should also
assert the fallback invariants required by the renderer: after calling
toBasicTemplateData() on the subject (in TemplateDataFactoryTest.kt) add
assertions that basicData.actions is null and that basicData.mediaPayload is
empty (e.g., size == 0 or .isEmpty()) in addition to the existing checks for
templateType and baseContent so the fallback contract is locked down.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/TemplateRenderer.kt`:
- Around line 138-164: The FiveIcons branch currently treats a null validator as
"invalid" and falls back to buildBasicFallback, but tests and other templates
expect a null validator to cause an immediate null return; change the logic in
TemplateRenderer.kt inside the is FiveIconsTemplateData branch to explicitly
handle ValidatorFactory.getValidator(templateData) == null by returning null
(i.e., mirror buildIfValid behavior) instead of executing the invalid-path
fallback; keep the existing validation check and image-unloaded fallback
(FiveIconStyle, fiveIconSmallContentView.getUnloadedFiveIconsCount(),
fiveIconBigContentView.getUnloadedFiveIconsCount(), fiveIconNotificationBuilder)
only when the validator is non-null.

---

Nitpick comments:
In
`@clevertap-pushtemplates/src/test/java/com/clevertap/android/pushtemplates/TemplateDataFactoryTest.kt`:
- Around line 616-618: The test verifying toBasicTemplateData() should also
assert the fallback invariants required by the renderer: after calling
toBasicTemplateData() on the subject (in TemplateDataFactoryTest.kt) add
assertions that basicData.actions is null and that basicData.mediaPayload is
empty (e.g., size == 0 or .isEmpty()) in addition to the existing checks for
templateType and baseContent so the fallback contract is locked down.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 860e81b9-c953-4dc0-b836-ea184211a864

📥 Commits

Reviewing files that changed from the base of the PR and between 01e8640 and e9f6387.

📒 Files selected for processing (11)
  • clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/TemplateData.kt
  • clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/TemplateDataFactory.kt
  • clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/TemplateRenderer.kt
  • clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/FiveIconBigContentView.kt
  • clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/content/FiveIconSmallContentView.kt
  • clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/styles/FiveIconStyle.kt
  • clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/validators/ValidatorFactory.kt
  • clevertap-pushtemplates/src/main/res/layout/five_cta_collapsed.xml
  • clevertap-pushtemplates/src/main/res/layout/five_cta_expanded.xml
  • clevertap-pushtemplates/src/test/java/com/clevertap/android/pushtemplates/TemplateDataFactoryTest.kt
  • clevertap-pushtemplates/src/test/java/com/clevertap/android/pushtemplates/TemplateRendererTest.kt

Comment on lines +138 to 164
is FiveIconsTemplateData -> {
val validator = ValidatorFactory.getValidator(templateData)
if (validator?.validate() == true) {
val fiveIconStyle = FiveIconStyle(templateData, this, extras)
val fiveIconNotificationBuilder = fiveIconStyle.builderFromStyle(
context,
extras,
notificationId,
nb
)

/**
* If most icon bitmaps fail to load, gracefully fall back to a basic
* title/message notification instead of suppressing the notification.
*/
if ((fiveIconStyle.fiveIconSmallContentView as FiveIconSmallContentView).getUnloadedFiveIconsCount() > 2 ||
(fiveIconStyle.fiveIconBigContentView as FiveIconBigContentView).getUnloadedFiveIconsCount() > 2) {
PTLog.debug("More than 2 images were not retrieved in 5CTA Notification, reverting to basic template.")
buildBasicFallback(templateData.toBasicTemplateData(), context, extras, notificationId, nb)
} else {
fiveIconNotificationBuilder
}
} else {
fiveIconNotificationBuilder
PTLog.debug("Five Icons template validation failed, reverting to basic template.")
buildBasicFallback(templateData.toBasicTemplateData(), context, extras, notificationId, nb)
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Verify behavior when FiveIcons validator is null.

When ValidatorFactory.getValidator(templateData) returns null, the condition at line 140 evaluates to false (since null == true is false), causing the code to fall through to the else branch at line 160-162 which calls buildBasicFallback. This differs from other templates where a null validator results in null being returned (via buildIfValid).

The test test_renderNotification_five_icons_template_null_validator expects null but doesn't mock the fallback path (toBasicTemplateData() and subsequent validator). Either the production code should explicitly handle the null validator case to return null, or the test needs to be updated to reflect the fallback behavior.

🐛 Proposed fix to handle null validator explicitly
 is FiveIconsTemplateData -> {
     val validator = ValidatorFactory.getValidator(templateData)
+    if (validator == null) {
+        PTLog.debug("Five Icons template validator is null, cannot render notification.")
+        null
+    } else if (validator.validate()) {
-    if (validator?.validate() == true) {
         val fiveIconStyle = FiveIconStyle(templateData, this, extras)
         // ... rest of the code
     } else {
         PTLog.debug("Five Icons template validation failed, reverting to basic template.")
         buildBasicFallback(templateData.toBasicTemplateData(), context, extras, notificationId, nb)
     }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@clevertap-pushtemplates/src/main/java/com/clevertap/android/pushtemplates/TemplateRenderer.kt`
around lines 138 - 164, The FiveIcons branch currently treats a null validator
as "invalid" and falls back to buildBasicFallback, but tests and other templates
expect a null validator to cause an immediate null return; change the logic in
TemplateRenderer.kt inside the is FiveIconsTemplateData branch to explicitly
handle ValidatorFactory.getValidator(templateData) == null by returning null
(i.e., mirror buildIfValid behavior) instead of executing the invalid-path
fallback; keep the existing validation check and image-unloaded fallback
(FiveIconStyle, fiveIconSmallContentView.getUnloadedFiveIconsCount(),
fiveIconBigContentView.getUnloadedFiveIconsCount(), fiveIconNotificationBuilder)
only when the validator is non-null.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants