Skip to content

Commit

Permalink
Paywalls: fix crash when computing localization with duplicate pack…
Browse files Browse the repository at this point in the history
…ages (#2958)

Thanks to @joshdholtz for catching this.
  • Loading branch information
NachoSoto committed Sep 8, 2023
1 parent dfde2a6 commit 2d952c5
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 7 deletions.
18 changes: 18 additions & 0 deletions RevenueCatUI/Data/TemplateViewConfiguration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,24 @@ extension TemplateViewConfiguration.PackageConfiguration {

}

// MARK: - Helpers

@available(iOS 16.0, macOS 13.0, tvOS 16.0, *)
extension TemplateViewConfiguration.PackageConfiguration {

/// - Returns: a dictionary for all localizations keyed by each package.
func localizationPerPackage() -> [Package: ProcessedLocalizedConfiguration] {
return .init(
self.all
.lazy
.map { ($0.content, $0.localization) },
// Ignore duplicates
uniquingKeysWith: { first, _ in first }
)
}

}

// MARK: - Creation

@available(iOS 16.0, macOS 13.0, tvOS 16.0, *)
Expand Down
6 changes: 1 addition & 5 deletions RevenueCatUI/Templates/MultiPackageBoldTemplate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,7 @@ struct MultiPackageBoldTemplate: TemplateViewType {
self._selectedPackage = .init(initialValue: configuration.packages.default.content)

self.configuration = configuration
self.localization = Dictionary(
uniqueKeysWithValues: configuration.packages.all
.lazy
.map { ($0.content, $0.localization) }
)
self.localization = configuration.packages.localizationPerPackage()
}

var body: some View {
Expand Down
61 changes: 59 additions & 2 deletions Tests/RevenueCatUITests/Data/TemplateViewConfigurationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ class BaseTemplateViewConfigurationTests: TestCase {}
@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
class TemplateViewConfigurationCreationTests: BaseTemplateViewConfigurationTests {

private typealias Config = TemplateViewConfiguration.PackageConfiguration

func testCreateWithNoPackages() {
expect {
try Config.create(
Expand Down Expand Up @@ -129,6 +127,63 @@ class TemplateViewConfigurationCreationTests: BaseTemplateViewConfigurationTests

}

@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
class TemplateViewConfigurationHelpersTests: BaseTemplateViewConfigurationTests {

func testLocalizationPerPackageWithOnePackage() throws {
let configuration = try Config.create(
with: [TestData.monthlyPackage],
filter: [.monthly],
default: nil,
localization: Self.localization,
setting: .single
)

expect(configuration.localizationPerPackage()) == [
TestData.monthlyPackage: Self.localization.processVariables(with: TestData.monthlyPackage)
]
}

func testLocalizationPerPackageWithMultiplePackages() throws {
let configuration = try Config.create(
with: [TestData.monthlyPackage,
TestData.annualPackage,
TestData.weeklyPackage,
TestData.lifetimePackage],
filter: [.annual, .monthly, .lifetime],
default: .monthly,
localization: Self.localization,
setting: .multiple
)

expect(configuration.localizationPerPackage()) == [
TestData.monthlyPackage: Self.localization.processVariables(with: TestData.monthlyPackage),
TestData.annualPackage: Self.localization.processVariables(with: TestData.annualPackage),
TestData.lifetimePackage: Self.localization.processVariables(with: TestData.lifetimePackage)
]
}

// Frontend ensures that having duplicates isn't possible, but this ensures proper behavior.
func testLocalizationPerPackageWithDuplicatePackages() throws {
let configuration = try Config.create(
with: [TestData.monthlyPackage,
TestData.annualPackage,
TestData.weeklyPackage,
TestData.lifetimePackage],
filter: [.monthly, .monthly, .annual],
default: .monthly,
localization: Self.localization,
setting: .multiple
)

expect(configuration.localizationPerPackage()) == [
TestData.monthlyPackage: Self.localization.processVariables(with: TestData.monthlyPackage),
TestData.annualPackage: Self.localization.processVariables(with: TestData.annualPackage)
]
}

}

@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
class TemplateViewConfigurationFilteringTests: BaseTemplateViewConfigurationTests {

Expand Down Expand Up @@ -193,6 +248,8 @@ class TemplateViewConfigurationFilteringTests: BaseTemplateViewConfigurationTest
@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
private extension BaseTemplateViewConfigurationTests {

typealias Config = TemplateViewConfiguration.PackageConfiguration

static let consumable = Package(
identifier: "consumable",
packageType: .custom,
Expand Down

0 comments on commit 2d952c5

Please sign in to comment.