Skip to content

[MOB-21131] Display Proposition api to support multiple propositions.#112

Merged
akhiljain1907 merged 25 commits intoadobe:dev-v5.3.1from
akhiljain1907:MOB-21131
Apr 21, 2025
Merged

[MOB-21131] Display Proposition api to support multiple propositions.#112
akhiljain1907 merged 25 commits intoadobe:dev-v5.3.1from
akhiljain1907:MOB-21131

Conversation

@akhiljain1907
Copy link
Copy Markdown
Contributor

@akhiljain1907 akhiljain1907 commented Sep 24, 2024

Description

This PR adds an api "trackDisplayedOffers" which takes list of offers as an argument and sends display interaction event to Experience Edge.

Through this additional api, we now support display event to be called on multiple propositions which can be send in batches and not per offer (read: proposition) and so we've moved generateInteractionXDM and trackWithData methods from Offer class to public class.

This api supports calling display interaction event on multiple offers. Since a proposition could contain more than one offers and our generateInteractionXDM method takes list of propositions, we first extract list of unique propositions from passed offers and create new proposition with relevant offer ids to be tracked. We have also moved generateInteractionXDM and trackWithData methods to OptimizeTrackingUtils from Offer+Tracking extension to reuse them within the module.

Related Issue

Motivation and Context

How Has This Been Tested?

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • I have signed the Adobe Open Source CLA.
  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

…ired for multiple propositions

moved generateInteractionXDM and trackWithData method from Offers class to public Optimize extension
added relevant OptimizePuiblicApiTests to validate code functioning for multiple propositions
…changed default value of aepError to unexpected
…sition]? instead of [DecisionScope]? in callback and code review changes
…ve AEPOptimizeError as argument and minor changes
@akhiljain1907 akhiljain1907 changed the base branch from dev-v5.0.2 to main September 24, 2024 19:56
@akhiljain1907 akhiljain1907 changed the base branch from main to dev-v5.0.2 September 24, 2024 19:57
@akhiljain1907 akhiljain1907 changed the base branch from dev-v5.0.2 to main September 25, 2024 09:38
@akhiljain1907 akhiljain1907 changed the base branch from main to dev-v5.0.2 September 25, 2024 09:38
@akhiljain1907 akhiljain1907 changed the base branch from dev-v5.1.0 to dev-v5.3.1 April 1, 2025 14:22
OptimizeConstants.JsonKeys.EXPERIENCE_EVENT_TYPE: eventType,
OptimizeConstants.JsonKeys.EXPERIENCE: [
OptimizeConstants.JsonKeys.EXPERIENCE_DECISIONING: [
OptimizeConstants.JsonKeys.DECISIONING_PROPOSITION_EVENT_TYPE: propositionEventType,
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.

@siddique-adobe this seems to be missing in the Android implementation. Could you check if it needs to be added?

@akhiljain1907
Copy link
Copy Markdown
Contributor Author

Hi @spoorthipujariadobe, I have addressed your comments and made few changes. Can you please review again?

wait(for: [expectation], timeout: 2)
}

func testGenerateInteractionXdm_multiplePropositions() throws {
Copy link
Copy Markdown
Contributor

@spoorthipujariadobe spoorthipujariadobe Apr 8, 2025

Choose a reason for hiding this comment

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

nit: can we move this test to a separate OptimizeTrackingUtilsTests file?

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.

Would be good to add a few more tests here to cover cases like empty propositions and all offers belonging to the same proposition. You can check the Android PR for more cases
https://github.com/adobe/aepsdk-optimize-android/pull/92/files#diff-710393a6e27a3c8cd7cb485acc24b9df4631442f2c7efc5a5aa7b7ed24686b38

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I have moved testGenerateInteractionXdm_multiplePropositions() in OptimizePropositionTests as that's were relevant generate xdm tests were present.
Also i have added a new test file OptimizeTrackingTests which contains test for new displayed api.

Copy link
Copy Markdown
Contributor

@spoorthipujariadobe spoorthipujariadobe left a comment

Choose a reason for hiding this comment

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

Logic looks good. Would be nice to have someone more familiar with iOS review it as well, maybe @ishwetansh ?

try container.encode(scope, forKey: .scope)
try container.encode(AnyCodable.from(dictionary: scopeDetails), forKey: .scopeDetails)
try container.encode(offers, forKey: .items)
try container.encode(items, forKey: .items)
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.

Please confirm if we need items or offers to be encoded here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, we need to encode offers itself. Removed this.

import Foundation

/// Internal helper enum for tracking functionality
enum OptimizeTrackingUtils {
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.

I don't see the use case of using an enum here, it is generally used to define and handle finite cases.
can we please use a struct here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

since we are using only static methods here, it';s recommended to use enum.
FYI when i use struct, i get this warning - Convenience Type Violation: Types used for hosting only static members should be implemented as a caseless enum to avoid instantiation (convenience_type)

Comment on lines +25 to +39
var propositionDetailsData: [[String: Any]] = []

for proposition in propositions {
let propositionMap: [String: Any] = [
OptimizeConstants.JsonKeys.DECISIONING_PROPOSITIONS_ID: proposition.id,
OptimizeConstants.JsonKeys.DECISIONING_PROPOSITIONS_SCOPE: proposition.scope,
OptimizeConstants.JsonKeys.DECISIONING_PROPOSITIONS_SCOPEDETAILS: proposition.scopeDetails,
OptimizeConstants.JsonKeys.DECISIONING_PROPOSITIONS_ITEMS: proposition.offers.map { offer in
[
OptimizeConstants.JsonKeys.DECISIONING_PROPOSITIONS_ITEMS_ID: offer.id
]
}
]
propositionDetailsData.append(propositionMap)
}
Copy link
Copy Markdown
Contributor

@ishwetansh ishwetansh Apr 9, 2025

Choose a reason for hiding this comment

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

We can use a transformable map function here to build the dictionary instead of traditional loop.

let propositionDetailsData: [[String: Any]] = propositions.map { proposition in return [ OptimizeConstants.JsonKeys.DECISIONING_PROPOSITIONS_ID: proposition.id, OptimizeConstants.JsonKeys.DECISIONING_PROPOSITIONS_SCOPE: proposition.scope, OptimizeConstants.JsonKeys.DECISIONING_PROPOSITIONS_SCOPEDETAILS: proposition.scopeDetails, OptimizeConstants.JsonKeys.DECISIONING_PROPOSITIONS_ITEMS: proposition.offers.map { offer in return [ OptimizeConstants.JsonKeys.DECISIONING_PROPOSITIONS_ITEMS_ID: offer.id ] } ] }

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done


import Foundation

class Propositions_OptimizeTests {
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.

I guess, we don't usually use an _ in class names,
can we use PropositionsOptimizeTests

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I previously kept this file in Utils folder of Unit test where this naming convention was followed. But now i have moved these test data in a new file PropositionsTestData which is kept in TestHelpers folder.

XCTAssertEqual(propositions.count, 1)
XCTAssertEqual(propositions.first?.id, proposition.id)
XCTAssertEqual(propositions.first?.scope, proposition.scope)

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.

nit: please remove the blank line.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done

@akhiljain1907
Copy link
Copy Markdown
Contributor Author

Hi @spoorthipujariadobe, @ishwetansh can you please review and approve this PR

@akhiljain1907 akhiljain1907 merged commit 4043d69 into adobe:dev-v5.3.1 Apr 21, 2025
6 checks passed
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