Skip to content

Commit

Permalink
[Shipping labels] Display remote validation errors in address form (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
rachelmcr authored Jan 31, 2025
2 parents b26dbdd + 6177844 commit 2134384
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ final class WooShippingAddressField: ObservableObject {
func clearError() {
errorMessage = nil
}

/// Sets the current validation error.
/// This can be used to override the local validation, e.g. when remote validation fails.
func setError(_ message: String) {
errorMessage = message
}
}

/// Represents the types of fields in a WooCommerce Shipping address.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ struct WooShippingEditAddressView: View {
VStack(spacing: Constants.verticalSpacing) {
HStack {
Image(systemName: viewModel.status == .verified ? "checkmark.circle" : "exclamationmark.circle")
Text(Localization.Status.label(for: viewModel.status))
Text(viewModel.statusLabel)
}
.font(.subheadline)
.foregroundStyle(viewModel.status == .verified ? Constants.green : Constants.red)
Expand Down Expand Up @@ -391,28 +391,6 @@ private extension WooShippingEditAddressView {
value: "Done",
comment: "Button to dismiss the keyboard")

enum Status {
static func label(for status: WooShippingAddressStatus) -> String {
switch status {
case .verified:
return verified
case .unverified:
return unverified
case .missingInformation:
return missingInformation
}
}
static let verified = NSLocalizedString("wooShipping.createLabels.editAddress.verified",
value: "Address verified",
comment: "Label when the address has been verified in the Woo Shipping label creation flow")
static let unverified = NSLocalizedString("wooShipping.createLabels.editAddress.unverified",
value: "Unverified address",
comment: "Label when the address is unverified in the Woo Shipping label creation flow")
static let missingInformation = NSLocalizedString("wooShipping.createLabels.editAddress.missingInformation",
value: "Missing information",
comment: "Label when the address is missing information in the Woo Shipping label creation flow")
}

enum Button {
static func label(for status: WooShippingAddressStatus) -> String {
switch status {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ final class WooShippingEditAddressViewModel: ObservableObject, Identifiable {
}
}

/// Label to describe the status of the address.
var statusLabel: String {
if let remoteValidationError, hasChanges {
return remoteValidationError
} else {
return Localization.Status.label(for: status)
}
}

// MARK: State/Country

/// ResultsController: Loads Countries from the Storage Layer.
Expand Down Expand Up @@ -144,6 +153,9 @@ final class WooShippingEditAddressViewModel: ObservableObject, Identifiable {
/// View model for normalizing the address.
@Published var normalizeAddressVM: WooShippingNormalizeAddressViewModel?

/// Error from remote validation, if any.
@Published private var remoteValidationError: String?

init(type: AddressType,
id: String,
name: String,
Expand Down Expand Up @@ -265,8 +277,17 @@ final class WooShippingEditAddressViewModel: ObservableObject, Identifiable {
let validation = try await remotelyValidateAddress(addressToValidate)
normalizeAddressVM = WooShippingNormalizeAddressViewModel(enteredAddress: validation.originalAddress,
suggestedAddress: validation.normalizedAddress)
} catch let error as WooShippingAddressValidationError {
if let nameError = error.nameError {
name.setError(nameError)
}
if let addressError = error.addressError {
address.setError(addressError)
}
if let generalError = error.generalError {
remoteValidationError = generalError
}
} catch {
// TODO: Handle `WooShippingAddressValidationError` errors.
DDLogError("⛔️ Error validating address for Woo Shipping label: \(error)")
}
}
Expand Down Expand Up @@ -461,5 +482,27 @@ private extension WooShippingEditAddressViewModel {
value: "Please provide a valid postal code.",
comment: "Validation message when the postal code field is empty in the Woo Shipping label creation flow")
}

enum Status {
static func label(for status: WooShippingAddressStatus) -> String {
switch status {
case .verified:
return verified
case .unverified:
return unverified
case .missingInformation:
return missingInformation
}
}
static let verified = NSLocalizedString("wooShipping.createLabels.editAddress.verified",
value: "Address verified",
comment: "Label when the address has been verified in the Woo Shipping label creation flow")
static let unverified = NSLocalizedString("wooShipping.createLabels.editAddress.unverified",
value: "Unverified address",
comment: "Label when the address is unverified in the Woo Shipping label creation flow")
static let missingInformation = NSLocalizedString("wooShipping.createLabels.editAddress.missingInformation",
value: "Missing information",
comment: "Label when the address is missing information in the Woo Shipping label creation flow")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,48 @@ final class WooShippingEditAddressViewModelTests: XCTestCase {
// Then
XCTAssertNotNil(viewModel.normalizeAddressVM)
}

@MainActor
func test_remotelyValidateAddress_sets_status_and_field_errors_on_validation_error() async {
// Given
let expectedNameError = "Either Name or Company is required"
let expectedAddressError = "House number is missing"
let expectedGeneralError = "Address not found"
let stores = MockStoresManager(sessionManager: .testingInstance)
let viewModel = WooShippingEditAddressViewModel(type: .destination,
id: "",
name: "",
company: "",
country: "",
address: "",
city: "",
state: "",
postalCode: "",
email: "",
phone: "",
isDefaultAddress: true,
showCompanyField: true,
isVerified: true,
phoneNumberRequired: true,
stores: stores,
debounceDelayInSeconds: 0)
stores.whenReceivingAction(ofType: WooShippingAction.self) { action in
if case let .validateAddress(_, _, completion) = action {
completion(.failure(WooShippingAddressValidationError(addressError: expectedAddressError,
generalError: expectedGeneralError,
nameError: expectedNameError)))
}
}

// When
viewModel.address.value = "ALGONKIN ST"
await viewModel.remotelyValidateAddress()

// Then
XCTAssertEqual(viewModel.name.errorMessage, expectedNameError)
XCTAssertEqual(viewModel.address.errorMessage, expectedAddressError)
XCTAssertEqual(viewModel.statusLabel, expectedGeneralError)
}
}

private extension WooShippingEditAddressViewModel {
Expand Down

0 comments on commit 2134384

Please sign in to comment.