Skip to content

Commit 7c5fe8e

Browse files
authored
Move eligible KeystoneTests into the cross-platform Swift package tests (#25815)
* Move macOS-clean utility tests into the cross-platform Swift package Relocate the Queue, LoggingURLRedactor, DashboardDynamicCardAnalyticsEvent, SiteCreationHeaderData, QRLoginURLParser, and ReaderCSS tests from KeystoneTests into WordPressSharedTests, moving each subject into WordPressShared so it builds on macOS and runs under `swift test` at the repo root. Also move URLHelpersTests and delete two stale KeystoneTests copies (DictionaryHelpersTests, URLIncrementalFilenameTests) whose WordPressShared copies already ran. * Extract Array, Math, NotificationCenter, and IncrementalDelay to WordPressShared Move the Array and Math extensions and NotificationCenter.observeOnce into WordPressShared, and split IncrementalDelay out of Delay.swift (leaving the GCD DispatchDelayedAction/DelayStateWrapper helpers in the app). Relocate their tests into WordPressSharedTests and add the WordPressShared import to the remaining callers. * Move MediaUploadHashTests into the cross-platform Swift package Relocate the String.hash guard test from KeystoneTests to WordPressSharedTests so it runs under `swift test` at the repo root. #25811 moved the other Gutenberg tests into GutenbergProcessorsTests but left this one behind — it asserts a Swift String hash value and has no processor dependency. Drops the vestigial `@testable import WordPress`.
1 parent 7915a92 commit 7c5fe8e

43 files changed

Lines changed: 114 additions & 171 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

WordPress/Classes/Utility/Analytics/DashboardDynamicCardAnalyticsEvent.swift renamed to Modules/Sources/WordPressShared/Analytics/DashboardDynamicCardAnalyticsEvent.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
enum DashboardDynamicCardAnalyticsEvent: Hashable {
1+
public enum DashboardDynamicCardAnalyticsEvent: Hashable {
22

33
case cardShown(id: String)
44
case cardTapped(id: String, url: String?)
55
case cardCtaTapped(id: String, url: String?)
66

7-
var name: String {
7+
public var name: String {
88
switch self {
99
case .cardShown: return "dynamic_dashboard_card_shown"
1010
case .cardTapped: return "dynamic_dashboard_card_tapped"
1111
case .cardCtaTapped: return "dynamic_dashboard_card_cta_tapped"
1212
}
1313
}
1414

15-
var properties: [String: String] {
15+
public var properties: [String: String] {
1616
switch self {
1717
case .cardShown(let id):
1818
return [Keys.id: id]
File renamed without changes.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import Foundation
2+
3+
/// Provides a sequence of incremental delays, repeating the last one
4+
/// indefinitely.
5+
///
6+
public struct IncrementalDelay<Element> {
7+
public var current: Element
8+
9+
private let delaySequence: AnySequence<Element>
10+
private var iterator: AnyIterator<Element>
11+
12+
public init(_ sequence: [Element]) {
13+
precondition(!sequence.isEmpty, "IncrementalDelay sequence can't be empty")
14+
delaySequence = sequence.repeatingLast()
15+
iterator = delaySequence.makeIterator()
16+
current = iterator.next()!
17+
}
18+
19+
public mutating func increment() {
20+
current = iterator.next()!
21+
}
22+
23+
public mutating func reset() {
24+
iterator = delaySequence.makeIterator()
25+
current = iterator.next()!
26+
}
27+
}

WordPress/Classes/Utility/Logging/LoggingURLRedactor.swift renamed to Modules/Sources/WordPressShared/Utility/LoggingURLRedactor.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import Foundation
22

3-
struct LoggingURLRedactor {
3+
public struct LoggingURLRedactor {
44

5-
static func redactedURL(_ url: URL) -> URL {
5+
public static func redactedURL(_ url: URL) -> URL {
66

77
if isAuthURL(url) {
88
return redactParameter(named: "token", in: url)

WordPress/Classes/Extensions/Math.swift renamed to Modules/Sources/WordPressShared/Utility/Math.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ extension Int {
1010
/// - Precondition: divisor must be > 0
1111
/// - returns: an Int rounded to the nearest integer that's a multiple of the argument.
1212
///
13-
func round(_ divisor: UInt) -> Int {
13+
public func round(_ divisor: UInt) -> Int {
1414
assert(divisor > 0)
1515
if self == 0 || divisor == 0 {
1616
return self
@@ -30,39 +30,39 @@ extension Comparable {
3030
/// - max if self > max
3131
/// - otherwise it returns self
3232
///
33-
func clamp(min minValue: Self, max maxValue: Self) -> Self {
33+
public func clamp(min minValue: Self, max maxValue: Self) -> Self {
3434
return Swift.min(Swift.max(self, minValue), maxValue)
3535
}
3636
}
3737

3838
extension CGSize {
39-
func clamp(min minValue: CGSize, max maxValue: CGSize) -> CGSize {
39+
public func clamp(min minValue: CGSize, max maxValue: CGSize) -> CGSize {
4040
let width = self.width.clamp(min: minValue.width, max: maxValue.width)
4141
let height = self.height.clamp(min: minValue.height, max: maxValue.height)
4242
return CGSize(width: width, height: height)
4343
}
4444

45-
func clamp(min minValue: CGFloat, max maxValue: CGFloat) -> CGSize {
45+
public func clamp(min minValue: CGFloat, max maxValue: CGFloat) -> CGSize {
4646
let minSize = CGSize(width: minValue, height: minValue)
4747
let maxSize = CGSize(width: maxValue, height: maxValue)
4848
return clamp(min: minSize, max: maxSize)
4949
}
5050

51-
func clamp(min minValue: Int, max maxValue: Int) -> CGSize {
51+
public func clamp(min minValue: Int, max maxValue: Int) -> CGSize {
5252
return clamp(min: CGFloat(minValue), max: CGFloat(maxValue))
5353
}
5454

55-
func scaled(by scale: CGFloat) -> CGSize {
55+
public func scaled(by scale: CGFloat) -> CGSize {
5656
CGSize(width: width * scale, height: height * scale)
5757
}
5858

59-
func rounded() -> CGSize {
59+
public func rounded() -> CGSize {
6060
CGSize(width: width.rounded(), height: height.rounded())
6161
}
6262
}
6363

6464
extension CGFloat {
65-
func zeroIfNaN() -> CGFloat {
65+
public func zeroIfNaN() -> CGFloat {
6666
return self.isNaN ? 0.0 : self
6767
}
6868
}

WordPress/Classes/Extensions/NotificationCenter+ObserveOnce.swift renamed to Modules/Sources/WordPressShared/Utility/NotificationCenter+ObserveOnce.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ extension NotificationCenter {
2626
///
2727
@discardableResult
2828
@objc
29-
func observeOnce(forName name: NSNotification.Name?, object: Any?, queue: OperationQueue?, using block: @escaping (Foundation.Notification) -> Swift.Void, filter: ((Foundation.Notification) -> Bool)? = nil) -> NSObjectProtocol {
29+
public func observeOnce(forName name: NSNotification.Name?, object: Any?, queue: OperationQueue?, using block: @escaping (Foundation.Notification) -> Swift.Void, filter: ((Foundation.Notification) -> Bool)? = nil) -> NSObjectProtocol {
3030
let oneTimeObserver = OneTimeObserver(action: block)
3131

3232
let observer = NotificationCenter.default.addObserver(

WordPress/Classes/ViewRelated/QR Login/Helpers/QRLoginURLParser.swift renamed to Modules/Sources/WordPressShared/Utility/QRLoginURLParser.swift

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,29 @@
11
import Foundation
22

3-
struct QRLoginToken: Equatable {
4-
let token: String
5-
let data: String
3+
public struct QRLoginToken: Equatable {
4+
public let token: String
5+
public let data: String
66

7-
static func == (lhs: Self, rhs: Self) -> Bool {
8-
return lhs.token == rhs.token && lhs.data == rhs.data
7+
public init(token: String, data: String) {
8+
self.token = token
9+
self.data = data
10+
}
11+
12+
public static func == (lhs: Self, rhs: Self) -> Bool {
13+
lhs.token == rhs.token && lhs.data == rhs.data
914
}
1015
}
1116

12-
struct QRLoginURLParser {
17+
public struct QRLoginURLParser {
1318
private let urlString: String
1419

15-
init(urlString: String) {
20+
public init(urlString: String) {
1621
self.urlString = urlString
1722
}
1823

1924
/// Attempts to retrieve the QR Login token information from the incoming urlString
2025
/// - Returns: QRLoginToken or nil if the parsing fails for any reason
21-
func parse() -> QRLoginToken? {
26+
public func parse() -> QRLoginToken? {
2227
// Early validation, making sure this is a valid URL from a valid host
2328
guard let url = URL(string: urlString), Self.isValidHost(url: url) else {
2429
return nil
@@ -39,7 +44,7 @@ struct QRLoginURLParser {
3944
}
4045

4146
/// Validates that the input URL is coming from a valid host
42-
static func isValidHost(url: URL) -> Bool {
47+
public static func isValidHost(url: URL) -> Bool {
4348
guard let host = url.host else {
4449
return false
4550
}

WordPress/Classes/Utility/Queue.swift renamed to Modules/Sources/WordPressShared/Utility/Queue.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,23 @@ import Foundation
66
public struct Queue<Element> {
77
private var elements = [Element]()
88

9+
public init() {}
10+
911
/// Push `element` onto the back of the queue
1012
///
11-
mutating func push(_ element: Element) {
13+
public mutating func push(_ element: Element) {
1214
elements.insert(element, at: elements.startIndex)
1315
}
1416

1517
/// Remove and return the item at the front of the queue
1618
///
17-
mutating func pop() -> Element? {
18-
return elements.popLast()
19+
public mutating func pop() -> Element? {
20+
elements.popLast()
1921
}
2022

2123
/// Removes all elements; If `where` is given, only the elements matching the
2224
/// predicate will be removed.
23-
mutating func removeAll(where shouldBeRemoved: ((Element) -> Bool)? = nil) {
25+
public mutating func removeAll(where shouldBeRemoved: ((Element) -> Bool)? = nil) {
2426
if let shouldBeRemoved {
2527
elements.removeAll(where: shouldBeRemoved)
2628
} else {

WordPress/Classes/ViewRelated/Reader/Detail/WebView/ReaderCSS.swift renamed to Modules/Sources/WordPressShared/Utility/ReaderCSS.swift

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import Foundation
2-
import WordPressShared
32

43
/// A struct that returns the Reader CSS URL
54
/// If you need to fix an issue in the CSS, see pbArwn-GU-p2
65
///
7-
struct ReaderCSS {
6+
public struct ReaderCSS {
87
private let store: KeyValueDatabase
98

109
private let now: Int
@@ -14,17 +13,17 @@ struct ReaderCSS {
1413
private let expirationDays: Int = 5
1514

1615
private var expirationDaysInSeconds: Int {
17-
return expirationDays * 60 * 60 * 24
16+
expirationDays * 60 * 60 * 24
1817
}
1918

2019
static let updatedKey = "ReaderCSSLastUpdated"
2120

2221
/// Returns a custom Reader CSS URL
2322
/// This value can be changed under Settings > Debug
2423
///
25-
var customAddress: String? {
24+
public var customAddress: String? {
2625
get {
27-
return store.object(forKey: "reader-css-url") as? String
26+
store.object(forKey: "reader-css-url") as? String
2827
}
2928
set {
3029
store.set(newValue, forKey: "reader-css-url")
@@ -34,19 +33,22 @@ struct ReaderCSS {
3433
/// Returns the Reader CSS appending a timestamp
3534
/// We force it to update based on the `expirationDays` property
3635
///
37-
var address: String {
36+
public var address: String {
3837
guard let lastUpdated = store.object(forKey: type(of: self).updatedKey) as? Int,
39-
now - lastUpdated < expirationDaysInSeconds || !isInternetReachable() else {
38+
now - lastUpdated < expirationDaysInSeconds || !isInternetReachable()
39+
else {
4040
saveCurrentDate()
4141
return url(appendingTimestamp: now)
4242
}
4343

4444
return url(appendingTimestamp: lastUpdated)
4545
}
4646

47-
init(now: Int = Int(Date().timeIntervalSince1970),
48-
store: KeyValueDatabase = UserPersistentStoreFactory.instance(),
49-
isInternetReachable: @escaping () -> Bool = ReachabilityUtils.isInternetReachable) {
47+
public init(
48+
now: Int = Int(Date().timeIntervalSince1970),
49+
store: KeyValueDatabase = UserPersistentStoreFactory.instance(),
50+
isInternetReachable: @escaping () -> Bool = ReachabilityUtils.isInternetReachable
51+
) {
5052
self.store = store
5153
self.now = now
5254
self.isInternetReachable = isInternetReachable
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/// Describes the header information presented to a user during individual steps of Site Creation.
2+
/// This struct is best suited for cases where these values are static (i.e., not retrieved from the server).
3+
///
4+
public struct SiteCreationHeaderData {
5+
public let title: String
6+
public let subtitle: String
7+
8+
public init(title: String, subtitle: String) {
9+
self.title = title
10+
self.subtitle = subtitle
11+
}
12+
}

0 commit comments

Comments
 (0)