Skip to content

Commit

Permalink
PIR broker configs: Add sub actions to ExpectationAction (#3452)
Browse files Browse the repository at this point in the history
Task/Issue URL:
https://app.asana.com/0/1199230911884351/1208594469701836/f
Tech Design URL:
CC:

**Description**:
Add add sub actions to ExpectationAction 

**Steps to test this PR**:
1. Test PIR still works and check using the debug DB browser that
brokers are still read correctly

<!--
Tagging instructions
If this PR isn't ready to be merged for whatever reason it should be
marked with the `DO NOT MERGE` label (particularly if it's a draft)
If it's pending Product Review/PFR, please add the `Pending Product
Review` label.

If at any point it isn't actively being worked on/ready for
review/otherwise moving forward (besides the above PR/PFR exception)
strongly consider closing it (or not opening it in the first place). If
you decide not to close it, make sure it's labelled to make it clear the
PRs state and comment with more information.
-->

**Definition of Done**:

* [ ] Does this PR satisfy our [Definition of
Done](https://app.asana.com/0/1202500774821704/1207634633537039/f)?

---
###### Internal references:
[Pull Request Review
Checklist](https://app.asana.com/0/1202500774821704/1203764234894239/f)
[Software Engineering
Expectations](https://app.asana.com/0/59792373528535/199064865822552)
[Technical Design
Template](https://app.asana.com/0/59792373528535/184709971311943)
[Pull Request
Documentation](https://app.asana.com/0/1202500774821704/1204012835277482/f)

---------

Co-authored-by: Brian Hall <[email protected]>
  • Loading branch information
THISISDINOSAUR and brianhall authored Oct 28, 2024
1 parent 68be519 commit 2b14de1
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,50 @@ struct Item: Codable, Sendable {
let expect: String?
let selector: String?
let parent: String?
let failSilently: Bool?
}

internal struct ExpectationAction: Action {
internal final class ExpectationAction: Action {
let id: String
let actionType: ActionType
let expectations: [Item]
let dataSource: DataSource?
let actions: [Action]?

enum CodingKeys: String, CodingKey {
case id, actionType, expectations, dataSource, actions
}

init(id: String, actionType: ActionType, expectations: [Item], dataSource: DataSource?, actions: [Action]?) {
self.id = id
self.actionType = actionType
self.expectations = expectations
self.dataSource = dataSource
self.actions = actions
}

required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(String.self, forKey: .id)
self.actionType = try container.decode(ActionType.self, forKey: .actionType)
self.expectations = try container.decode([Item].self, forKey: .expectations)
self.dataSource = try container.decodeIfPresent(DataSource.self, forKey: .dataSource)
let actionsList = try container.decodeIfPresent([[String: Any]].self, forKey: .actions)
if let actionsList = actionsList {
self.actions = try Step.parse(actionsList)
} else {
self.actions = nil
}
}

func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(actionType, forKey: .actionType)
try container.encode(expectations, forKey: .expectations)
try container.encode(dataSource, forKey: .dataSource)

var actionsContainer = container.nestedUnkeyedContainer(forKey: .actions)
try actions?.encode(to: &actionsContainer)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,25 +58,7 @@ struct Step: Codable, Sendable {
try container.encode(optOutType, forKey: .optOutType)

var actionsContainer = container.nestedUnkeyedContainer(forKey: .actions)
for action in actions {
if let navigateAction = action as? NavigateAction {
try actionsContainer.encode(navigateAction)
} else if let extractAction = action as? ExtractAction {
try actionsContainer.encode(extractAction)
} else if let fillFormAction = action as? FillFormAction {
try actionsContainer.encode(fillFormAction)
} else if let getCaptchaInfoAction = action as? GetCaptchaInfoAction {
try actionsContainer.encode(getCaptchaInfoAction)
} else if let solveCaptchaInfoAction = action as? SolveCaptchaAction {
try actionsContainer.encode(solveCaptchaInfoAction)
} else if let emailConfirmationAction = action as? EmailConfirmationAction {
try actionsContainer.encode(emailConfirmationAction)
} else if let clickAction = action as? ClickAction {
try actionsContainer.encode(clickAction)
} else if let expectactionAction = action as? ExpectationAction {
try actionsContainer.encode(expectactionAction)
}
}
try actions.encode(to: &actionsContainer)
}

static func parse(_ actions: [[String: Any]]) throws -> [Action] {
Expand Down Expand Up @@ -120,3 +102,27 @@ struct Step: Codable, Sendable {
return actionList
}
}

extension Array where Element == Action {
func encode(to container: inout any UnkeyedEncodingContainer) throws {
for action in self {
if let navigateAction = action as? NavigateAction {
try container.encode(navigateAction)
} else if let extractAction = action as? ExtractAction {
try container.encode(extractAction)
} else if let fillFormAction = action as? FillFormAction {
try container.encode(fillFormAction)
} else if let getCaptchaInfoAction = action as? GetCaptchaInfoAction {
try container.encode(getCaptchaInfoAction)
} else if let solveCaptchaInfoAction = action as? SolveCaptchaAction {
try container.encode(solveCaptchaInfoAction)
} else if let emailConfirmationAction = action as? EmailConfirmationAction {
try container.encode(emailConfirmationAction)
} else if let clickAction = action as? ClickAction {
try container.encode(clickAction)
} else if let expectactionAction = action as? ExpectationAction {
try container.encode(expectactionAction)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ extension KeyedDecodingContainer {
return try decode(type, forKey: key)
}

func decodeIfPresent(_ type: [[String: Any]].Type, forKey key: K) throws -> [[String: Any]]? {
guard contains(key) else {
return nil
}
guard try decodeNil(forKey: key) == false else {
return nil
}
return try decode(type, forKey: key)
}

func decode(_ type: [Any].Type, forKey key: K) throws -> [Any] {
var container = try self.nestedUnkeyedContainer(forKey: key)
return try container.decode(type)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ final class DataBrokerOperationActionTests: XCTestCase {
}

func testWhenRunningActionWithoutExtractedProfile_thenExecuteIsCalledWithProfileData() async {
let expectationAction = ExpectationAction(id: "1", actionType: .expectation, expectations: [Item](), dataSource: nil)
let expectationAction = ExpectationAction(id: "1", actionType: .expectation, expectations: [Item](), dataSource: nil, actions: nil)
let sut = OptOutJob(
privacyConfig: PrivacyConfigurationManagingMock(),
prefs: ContentScopeProperties.mock,
Expand Down Expand Up @@ -415,7 +415,7 @@ final class DataBrokerOperationActionTests: XCTestCase {

func testWhenExpectationActionRuns_thenStageIsSetToSubmit() async {
let mockStageCalculator = MockStageDurationCalculator()
let expectationAction = ExpectationAction(id: "1", actionType: .expectation, expectations: [Item](), dataSource: nil)
let expectationAction = ExpectationAction(id: "1", actionType: .expectation, expectations: [Item](), dataSource: nil, actions: nil)
let sut = OptOutJob(
privacyConfig: PrivacyConfigurationManagingMock(),
prefs: ContentScopeProperties.mock,
Expand Down

0 comments on commit 2b14de1

Please sign in to comment.