generated from bitwarden/template
-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
PM-16142: Guided Tour for Generator screen (#1301)
- Loading branch information
1 parent
f5c0874
commit a29f941
Showing
37 changed files
with
746 additions
and
206 deletions.
There are no files selected for viewing
48 changes: 48 additions & 0 deletions
48
BitwardenShared/UI/Platform/Application/Appearance/Modifiers/SmoothTransitionModifier.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,48 @@ | ||
import SwiftUI | ||
|
||
/// A custom view modifier to apply smooth transition effects and animations. | ||
/// | ||
struct SmoothTransitionModifier<V: Equatable>: ViewModifier { | ||
/// The animation to apply to the view. | ||
let animation: Animation | ||
|
||
/// The value that triggers the animation. | ||
let value: V | ||
|
||
func body(content: Content) -> some View { | ||
content | ||
.animation(animation, value: value) | ||
.modifier(SmoothTransitionEffect()) | ||
} | ||
} | ||
|
||
/// A custom geometry effect that applies a smooth transition effect to a view. | ||
/// This effect allows for animating the translation of a view along the X and Y axes. | ||
struct SmoothTransitionEffect: GeometryEffect { | ||
/// The animatable data representing the translation values for the X and Y axes. | ||
var animatableData: AnimatablePair<CGFloat, CGFloat> | ||
|
||
/// Initializes a new instance of the `SmoothTransitionEffect` with default translation values. | ||
init() { | ||
animatableData = AnimatablePair(0, 0) | ||
} | ||
|
||
/// Computes the projection transform for the given size, applying the translation effect. | ||
/// | ||
/// - Parameter size: The size of the view to which the effect is applied. | ||
/// - Returns: A `ProjectionTransform` representing the translation transformation. | ||
func effectValue(size: CGSize) -> ProjectionTransform { | ||
let translation = CGAffineTransform(translationX: animatableData.first, y: animatableData.second) | ||
return ProjectionTransform(translation) | ||
} | ||
} | ||
|
||
// MARK: - Extensions | ||
|
||
extension View { | ||
/// A view modifier that applies a smooth transition effect to the view. | ||
/// | ||
func smoothTransition<V: Equatable>(animation: Animation, value: V) -> some View { | ||
modifier(SmoothTransitionModifier(animation: animation, value: value)) | ||
} | ||
} |
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
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
108 changes: 108 additions & 0 deletions
108
...enShared/UI/Platform/Application/Views/GuidedTourView/GuidedTourView+GeneratorTests.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,108 @@ | ||
// swiftlint:disable:this file_name | ||
import SnapshotTesting | ||
import SwiftUI | ||
import ViewInspector | ||
import XCTest | ||
|
||
@testable import BitwardenShared | ||
|
||
// MARK: - GuidedTourView+GeneratorTests | ||
|
||
class GuidedTourViewGeneratorTests: BitwardenTestCase { | ||
// MARK: Properties | ||
|
||
var processor: MockProcessor<GuidedTourViewState, GuidedTourViewAction, Void>! | ||
var subject: GuidedTourView! | ||
|
||
// MARK: Setup & Teardown | ||
|
||
override func setUp() { | ||
super.setUp() | ||
processor = MockProcessor( | ||
state: GuidedTourViewState(currentIndex: 0, guidedTourStepStates: [ | ||
.generatorStep1, | ||
.generatorStep2, | ||
.generatorStep3, | ||
.generatorStep4, | ||
.generatorStep5, | ||
.generatorStep6, | ||
]) | ||
) | ||
let store = Store(processor: processor) | ||
subject = GuidedTourView(store: store) | ||
} | ||
|
||
override func tearDown() { | ||
super.tearDown() | ||
processor = nil | ||
subject = nil | ||
} | ||
|
||
// MARK: Snapshot tests | ||
|
||
/// Test the snapshot of the step 1 of the learn generator guided tour. | ||
@MainActor | ||
func test_snapshot_generatorStep1() { | ||
processor.state.currentIndex = 0 | ||
processor.state.guidedTourStepStates[0].spotlightRegion = CGRect(x: 25, y: 80, width: 340, height: 40) | ||
assertSnapshots( | ||
of: subject, | ||
as: [.defaultPortrait] | ||
) | ||
} | ||
|
||
/// Test the snapshot of the step 2 of the learn generator guided tour. | ||
@MainActor | ||
func test_snapshot_generatorStep2() { | ||
processor.state.currentIndex = 1 | ||
processor.state.guidedTourStepStates[1].spotlightRegion = CGRect(x: 25, y: 80, width: 340, height: 40) | ||
assertSnapshots( | ||
of: subject, | ||
as: [.defaultPortrait] | ||
) | ||
} | ||
|
||
/// Test the snapshot of the step 3 of the learn generator guided tour. | ||
@MainActor | ||
func test_snapshot_generatorStep3() { | ||
processor.state.currentIndex = 2 | ||
processor.state.guidedTourStepStates[2].spotlightRegion = CGRect(x: 25, y: 80, width: 340, height: 40) | ||
assertSnapshots( | ||
of: subject, | ||
as: [.defaultPortrait] | ||
) | ||
} | ||
|
||
/// Test the snapshot of the step 4 of the learn generator guided tour. | ||
@MainActor | ||
func test_snapshot_generatorStep4() { | ||
processor.state.currentIndex = 3 | ||
processor.state.guidedTourStepStates[3].spotlightRegion = CGRect(x: 25, y: 300, width: 340, height: 400) | ||
assertSnapshots( | ||
of: subject, | ||
as: [.defaultPortrait] | ||
) | ||
} | ||
|
||
/// Test the snapshot of the step 5 of the learn generator guided tour. | ||
@MainActor | ||
func test_snapshot_generatorStep5() { | ||
processor.state.currentIndex = 4 | ||
processor.state.guidedTourStepStates[4].spotlightRegion = CGRect(x: 300, y: 160, width: 40, height: 40) | ||
assertSnapshots( | ||
of: subject, | ||
as: [.defaultPortrait] | ||
) | ||
} | ||
|
||
/// Test the snapshot of the step 6 of the learn generator guided tour. | ||
@MainActor | ||
func test_snapshot_generatorStep6() { | ||
processor.state.currentIndex = 5 | ||
processor.state.guidedTourStepStates[5].spotlightRegion = CGRect(x: 25, y: 160, width: 340, height: 60) | ||
assertSnapshots( | ||
of: subject, | ||
as: [.defaultPortrait] | ||
) | ||
} | ||
} |
142 changes: 142 additions & 0 deletions
142
BitwardenShared/UI/Platform/Application/Views/GuidedTourView/GuidedTourView+LoginTests.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,142 @@ | ||
// swiftlint:disable:this file_name | ||
import SnapshotTesting | ||
import SwiftUI | ||
import ViewInspector | ||
import XCTest | ||
|
||
@testable import BitwardenShared | ||
|
||
// MARK: - GuidedTourView+LoginTests | ||
|
||
class GuidedTourViewLoginTests: BitwardenTestCase { | ||
// MARK: Properties | ||
|
||
var processor: MockProcessor<GuidedTourViewState, GuidedTourViewAction, Void>! | ||
var subject: GuidedTourView! | ||
|
||
// MARK: Setup & Teardown | ||
|
||
override func setUp() { | ||
super.setUp() | ||
processor = MockProcessor( | ||
state: GuidedTourViewState(currentIndex: 0, guidedTourStepStates: [ | ||
.loginStep1, | ||
.loginStep2, | ||
.loginStep3, | ||
]) | ||
) | ||
let store = Store(processor: processor) | ||
subject = GuidedTourView(store: store) | ||
} | ||
|
||
override func tearDown() { | ||
super.tearDown() | ||
processor = nil | ||
subject = nil | ||
} | ||
|
||
// MARK: Tests | ||
|
||
/// Tap the `back` button should dispatch the `backTapped` action. | ||
@MainActor | ||
func test_backButton_tap() async throws { | ||
processor.state.currentIndex = 1 | ||
let button = try subject.inspect().find(button: Localizations.back) | ||
try button.tap() | ||
XCTAssertEqual(processor.dispatchedActions, [.backTapped]) | ||
} | ||
|
||
/// Tapping the `done` button should dispatch the `doneTapped` action. | ||
@MainActor | ||
func test_doneButton_tap() async throws { | ||
processor.state.currentIndex = 2 | ||
let button = try subject.inspect().find(button: Localizations.done) | ||
try button.tap() | ||
XCTAssertEqual(processor.dispatchedActions, [.doneTapped]) | ||
} | ||
|
||
/// Tapping the dismiss button dispatches the `.dismissTapped` action. | ||
@MainActor | ||
func test_dismissButton_tap() async throws { | ||
processor.state.currentIndex = 2 | ||
let button = try subject.inspect().find(button: Localizations.dismiss) | ||
try button.tap() | ||
XCTAssertEqual(processor.dispatchedActions, [.dismissTapped]) | ||
} | ||
|
||
/// Tapping the `next` button should dispatch the `nextTapped` action. | ||
@MainActor | ||
func test_nextButton_tap() async throws { | ||
let button = try subject.inspect().find(button: Localizations.next) | ||
try button.tap() | ||
XCTAssertEqual(processor.dispatchedActions, [.nextTapped]) | ||
} | ||
|
||
// MARK: Snapshot tests | ||
|
||
/// Test the snapshot of the step 1 of the learn new login guided tour. | ||
@MainActor | ||
func test_snapshot_loginStep1() { | ||
processor.state.currentIndex = 0 | ||
processor.state.guidedTourStepStates[0].spotlightRegion = CGRect(x: 320, y: 470, width: 40, height: 40) | ||
assertSnapshots( | ||
of: subject, | ||
as: [.defaultPortrait, .defaultPortraitDark] | ||
) | ||
} | ||
|
||
/// Test the snapshot of the step 1 of the learn new login guided tour in landscape. | ||
@MainActor | ||
func test_snapshot_loginStep1_landscape() { | ||
processor.state.currentIndex = 0 | ||
processor.state.guidedTourStepStates[0].spotlightRegion = CGRect(x: 650, y: 150, width: 40, height: 40) | ||
assertSnapshots( | ||
of: subject, | ||
as: [.defaultLandscape] | ||
) | ||
} | ||
|
||
/// Test the snapshot of the step 2 of the learn new login guided tour. | ||
@MainActor | ||
func test_snapshot_loginStep2() { | ||
processor.state.currentIndex = 1 | ||
processor.state.guidedTourStepStates[1].spotlightRegion = CGRect(x: 40, y: 470, width: 320, height: 95) | ||
assertSnapshots( | ||
of: subject, | ||
as: [.defaultPortrait, .defaultPortraitDark] | ||
) | ||
} | ||
|
||
/// Test the snapshot of the step 2 of the learn new login guided tour in landscape. | ||
@MainActor | ||
func test_snapshot_loginStep2_landscape() { | ||
processor.state.currentIndex = 1 | ||
processor.state.guidedTourStepStates[1].spotlightRegion = CGRect(x: 40, y: 60, width: 460, height: 95) | ||
assertSnapshots( | ||
of: subject, | ||
as: [.defaultLandscape] | ||
) | ||
} | ||
|
||
/// Test the snapshot of the step 3 of the learn new login guided tour. | ||
@MainActor | ||
func test_snapshot_loginStep3() { | ||
processor.state.currentIndex = 2 | ||
processor.state.guidedTourStepStates[2].spotlightRegion = CGRect(x: 40, y: 500, width: 320, height: 90) | ||
assertSnapshots( | ||
of: subject, | ||
as: [.defaultPortrait, .defaultPortraitDark] | ||
) | ||
} | ||
|
||
/// Test the snapshot of the step 3 of the learn new login guided tour in landscape. | ||
@MainActor | ||
func test_snapshot_loginStep3_landscape() { | ||
processor.state.currentIndex = 2 | ||
processor.state.guidedTourStepStates[2].spotlightRegion = CGRect(x: 40, y: 60, width: 460, height: 90) | ||
assertSnapshots( | ||
of: subject, | ||
as: [.defaultLandscape] | ||
) | ||
} | ||
} |
Oops, something went wrong.