-
Notifications
You must be signed in to change notification settings - Fork 134
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1194 from DataDog/maciey/REPLAY-1448-uistepper
REPLAY-1448 Add support for UIStepper
- Loading branch information
Showing
6 changed files
with
237 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 90 additions & 0 deletions
90
.../Recorder/ViewTreeSnapshotProducer/ViewTreeSnapshot/NodeRecorders/UIStepperRecorder.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* | ||
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. | ||
* This product includes software developed at Datadog (https://www.datadoghq.com/). | ||
* Copyright 2019-Present Datadog, Inc. | ||
*/ | ||
|
||
import UIKit | ||
|
||
internal struct UIStepperRecorder: NodeRecorder { | ||
func semantics(of view: UIView, with attributes: ViewAttributes, in context: ViewTreeRecordingContext) -> NodeSemantics? { | ||
guard let stepper = view as? UIStepper else { | ||
return nil | ||
} | ||
guard attributes.isVisible else { | ||
return InvisibleElement.constant | ||
} | ||
|
||
let stepperFrame = CGRect(origin: attributes.frame.origin, size: stepper.intrinsicContentSize) | ||
let ids = context.ids.nodeIDs(5, for: stepper) | ||
|
||
let builder = UIStepperWireframesBuilder( | ||
wireframeRect: stepperFrame, | ||
cornerRadius: stepper.subviews.first?.layer.cornerRadius ?? 0, | ||
backgroundWireframeID: ids[0], | ||
dividerWireframeID: ids[1], | ||
minusWireframeID: ids[2], | ||
plusHorizontalWireframeID: ids[3], | ||
plusVerticalWireframeID: ids[4], | ||
isMinusEnabled: stepper.value > stepper.minimumValue, | ||
isPlusEnabled: stepper.value < stepper.maximumValue | ||
) | ||
let node = Node(viewAttributes: attributes, wireframesBuilder: builder) | ||
return SpecificElement(subtreeStrategy: .ignore, nodes: [node]) | ||
} | ||
} | ||
|
||
internal struct UIStepperWireframesBuilder: NodeWireframesBuilder { | ||
let wireframeRect: CGRect | ||
let cornerRadius: CGFloat | ||
let backgroundWireframeID: WireframeID | ||
let dividerWireframeID: WireframeID | ||
let minusWireframeID: WireframeID | ||
let plusHorizontalWireframeID: WireframeID | ||
let plusVerticalWireframeID: WireframeID | ||
let isMinusEnabled: Bool | ||
let isPlusEnabled: Bool | ||
|
||
func buildWireframes(with builder: WireframesBuilder) -> [SRWireframe] { | ||
let background = builder.createShapeWireframe( | ||
id: backgroundWireframeID, | ||
frame: wireframeRect, | ||
borderColor: nil, | ||
borderWidth: nil, | ||
backgroundColor: SystemColors.tertiarySystemFill, | ||
cornerRadius: cornerRadius | ||
) | ||
let verticalMargin: CGFloat = 6 | ||
let divider = builder.createShapeWireframe( | ||
id: dividerWireframeID, | ||
frame: CGRect( | ||
origin: CGPoint(x: 0, y: verticalMargin), | ||
size: CGSize(width: 1, height: wireframeRect.size.height - 2 * verticalMargin) | ||
).putInside(wireframeRect, horizontalAlignment: .center, verticalAlignment: .middle), | ||
backgroundColor: SystemColors.placeholderText | ||
) | ||
|
||
let horizontalElementRect = CGRect(origin: .zero, size: CGSize(width: 14, height: 2)) | ||
let verticalElementRect = CGRect(origin: .zero, size: CGSize(width: 2, height: 14)) | ||
let (leftButtonFrame, rightButtonFrame) = wireframeRect.divided(atDistance: wireframeRect.size.width / 2, from: .minXEdge) | ||
let minus = builder.createShapeWireframe( | ||
id: minusWireframeID, | ||
frame: horizontalElementRect.putInside(leftButtonFrame, horizontalAlignment: .center, verticalAlignment: .middle), | ||
backgroundColor: isMinusEnabled ? SystemColors.label : SystemColors.placeholderText, | ||
cornerRadius: horizontalElementRect.size.height | ||
) | ||
let plusHorizontal = builder.createShapeWireframe( | ||
id: plusHorizontalWireframeID, | ||
frame: horizontalElementRect.putInside(rightButtonFrame, horizontalAlignment: .center, verticalAlignment: .middle), | ||
backgroundColor: isPlusEnabled ? SystemColors.label : SystemColors.placeholderText, | ||
cornerRadius: horizontalElementRect.size.height | ||
) | ||
let plusVertical = builder.createShapeWireframe( | ||
id: plusVerticalWireframeID, | ||
frame: verticalElementRect.putInside(rightButtonFrame, horizontalAlignment: .center, verticalAlignment: .middle), | ||
backgroundColor: isPlusEnabled ? SystemColors.label : SystemColors.placeholderText, | ||
cornerRadius: verticalElementRect.size.width | ||
) | ||
return [background, divider, minus, plusHorizontal, plusVertical] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
47 changes: 47 additions & 0 deletions
47
...rder/ViewTreeSnapshotProducer/ViewTreeSnapshot/NodeRecorders/UIStepperRecorderTests.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/* | ||
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. | ||
* This product includes software developed at Datadog (https://www.datadoghq.com/). | ||
* Copyright 2019-Present Datadog, Inc. | ||
*/ | ||
|
||
import XCTest | ||
@testable import DatadogSessionReplay | ||
|
||
class UIStepperRecorderTests: XCTestCase { | ||
private let recorder = UIStepperRecorder() | ||
private let stepper = UIStepper() | ||
/// `ViewAttributes` simulating common attributes of switch's `UIView`. | ||
private var viewAttributes: ViewAttributes = .mockAny() | ||
|
||
func testWhenStepperIsNotVisible() throws { | ||
// When | ||
viewAttributes = .mock(fixture: .invisible) | ||
|
||
// Then | ||
let semantics = try XCTUnwrap(recorder.semantics(of: stepper, with: viewAttributes, in: .mockAny())) | ||
XCTAssertTrue(semantics is InvisibleElement) | ||
} | ||
|
||
func testWhenStepperIsVisible() throws { | ||
// Given | ||
stepper.tintColor = .mockRandom() | ||
|
||
// When | ||
viewAttributes = .mock(fixture: .visible()) | ||
|
||
// Then | ||
let semantics = try XCTUnwrap(recorder.semantics(of: stepper, with: viewAttributes, in: .mockAny())) | ||
XCTAssertTrue(semantics is SpecificElement) | ||
XCTAssertEqual(semantics.subtreeStrategy, .ignore, "Stepper's subtree should not be recorded") | ||
|
||
let builder = try XCTUnwrap(semantics.nodes.first?.wireframesBuilder as? UIStepperWireframesBuilder) | ||
} | ||
|
||
func testWhenViewIsNotOfExpectedType() { | ||
// When | ||
let view = UITextField() | ||
|
||
// Then | ||
XCTAssertNil(recorder.semantics(of: view, with: viewAttributes, in: .mockAny())) | ||
} | ||
} |