Skip to content

Commit

Permalink
GOVUKAPP-975 Recent Activities modularisation (#224)
Browse files Browse the repository at this point in the history
* Create GOVKit package and populate with shared or likely to be shared objects

* Create RecentActivity package and populate with appropriate objects

* Add GOVKit and RecentActivity imports as necessary, clean up repeated code

* Move GroupedList to GOVKit

* Remove 2 files now in GOVKit

* Add/reorganize GOVKit tests

* remove unneeded package dependencies

* Move some more shared classes to GOVKit, add scheme

* Add GOVKit as app dependency, add GOVKit imports where necessary

* Add govkit tests to test plan

* Fix tests to inject analytics service explicitly where needed.  Move ContstantsTests/BaseViewControllerTests to GOVKit

* Create GOVKitTestUtilities target for sharing mocks, etc.

* Add GOVKit test plan.  Clean up after some renaming.

* Set up RecentActivity tests

* Refactor tests to use new module structure

* Further test refactoring and cleanup.

* Remove commented code.  Fix unit test

* Fix code alignment issues

* Reorganize Date extensions and arrangers

* Remove unneeded extension

* Code review improvement

* Fix test

* Make test mocks internal and import with @testable.
Fix variable declaration

* Delete file that was resurrected accidentally during merge
  • Loading branch information
joshdubey authored Jan 15, 2025
1 parent 96c99e9 commit fea7235
Show file tree
Hide file tree
Showing 191 changed files with 1,871 additions and 694 deletions.
8 changes: 8 additions & 0 deletions GOVKit/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.DS_Store
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
98 changes: 98 additions & 0 deletions GOVKit/.swiftpm/xcode/xcshareddata/xcschemes/GOVKit.xcscheme
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1620"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "GOVKit"
BuildableName = "GOVKit"
BlueprintName = "GOVKit"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "GOVKitTestUtilities"
BuildableName = "GOVKitTestUtilities"
BlueprintName = "GOVKitTestUtilities"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<TestPlans>
<TestPlanReference
reference = "container:Tests/GOVKit.xctestplan"
default = "YES">
</TestPlanReference>
</TestPlans>
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "GOVKitTests"
BuildableName = "GOVKitTests"
BlueprintName = "GOVKitTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "GOVKit"
BuildableName = "GOVKit"
BlueprintName = "GOVKit"
ReferencedContainer = "container:">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
15 changes: 15 additions & 0 deletions GOVKit/Package.resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"originHash" : "75bc73283bb0bd2952e5b7f635611d098006e6832f5e944ff6183924c8b83a00",
"pins" : [
{
"identity" : "govuk-mobile-ios-ui-components",
"kind" : "remoteSourceControl",
"location" : "https://github.com/alphagov/govuk-mobile-ios-ui-components",
"state" : {
"branch" : "develop",
"revision" : "cdeda563886e92f0b9187b2a6448162c6db7b72a"
}
}
],
"version" : 3
}
47 changes: 47 additions & 0 deletions GOVKit/Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// swift-tools-version: 5.10
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "GOVKit",
platforms: [.iOS(.v16)],
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
name: "GOVKit",
targets: ["GOVKit"]
),
.library(
name: "GOVKitTestUtilities",
targets: ["GOVKitTestUtilities"]
)
],
dependencies: [
.package(url: "https://github.com/alphagov/govuk-mobile-ios-ui-components", branch: "develop")
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.target(
name: "GOVKit",
dependencies: [
.product(name: "UIComponents", package: "govuk-mobile-ios-ui-components")
],
resources: [
.process("Resources")
]
),
.target(
name: "GOVKitTestUtilities",
dependencies: ["GOVKit"]
),
.testTarget(
name: "GOVKitTests",
dependencies: ["GOVKit", "GOVKitTestUtilities"],
resources: [
.process("Resources")
]
),
]
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Foundation

protocol AnalyticsClient {
public protocol AnalyticsClient {
func launch()
func setEnabled(enabled: Bool)
func track(screen: TrackableScreen)
Expand Down
11 changes: 11 additions & 0 deletions GOVKit/Sources/GOVKit/Analytics/AnalyticsServiceInterface.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import UIKit

public protocol AnalyticsServiceInterface {
func launch()
func track(event: AppEvent)
func track(screen: TrackableScreen)
func set(userProperty: UserProperty)

func setAcceptedAnalytics(accepted: Bool)
var permissionState: AnalyticsPermissionState { get }
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Foundation

enum AnalyticsPermissionState {
public enum AnalyticsPermissionState {
case accepted
case denied
case unknown
Expand Down
12 changes: 12 additions & 0 deletions GOVKit/Sources/GOVKit/Analytics/Model/AppEvent.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Foundation

public struct AppEvent {
public let name: String
public let params: [String: Any]?

public init(name: String,
params: [String : Any]?) {
self.name = name
self.params = params
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import Foundation
import UIKit
import SwiftUI

protocol TrackableScreen {
public protocol TrackableScreen {
nonisolated var trackingName: String { get }
nonisolated var trackingClass: String { get }
nonisolated var trackingTitle: String? { get }
Expand All @@ -11,29 +11,29 @@ protocol TrackableScreen {
}

extension TrackableScreen {
var trackingLanguage: String {
public var trackingLanguage: String {
Locale.current.analyticsLanguageCode
}

var additionalParameters: [String: Any] {
public var additionalParameters: [String: Any] {
[:]
}
}

extension TrackableScreen where Self: UIViewController {
var trackingClass: String {
public var trackingClass: String {
String(
describing: type(of: self)
)
}

var trackingTitle: String? {
public var trackingTitle: String? {
title
}
}

extension TrackableScreen where Self: View {
var trackingClass: String {
public var trackingClass: String {
String(
describing: type(of: self)
)
Expand Down
12 changes: 12 additions & 0 deletions GOVKit/Sources/GOVKit/Analytics/Model/UserProperty.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Foundation

public struct UserProperty {
public let key: String
public let value: String?

public init(key: String,
value: String?) {
self.key = key
self.value = value
}
}
29 changes: 29 additions & 0 deletions GOVKit/Sources/GOVKit/Extensions/Analytics/AppEvent+Function.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Foundation

extension AppEvent {
public static func buttonFunction(text: String,
section: String,
action: String) -> AppEvent {
function(
text: text,
type: "Button",
section: section,
action: action
)
}

public static func function(text: String,
type: String,
section: String,
action: String) -> AppEvent {
.init(
name: "Function",
params: [
"text": text,
"type": type,
"section": section,
"action": action
]
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Foundation

extension AppEvent {
public static func navigation(text: String,
type: String,
external: Bool,
additionalParams: [String: Any?] = [:]) -> AppEvent {
let params: [String: Any?] = [
"text": text,
"type": type,
"external": external,
"language": Locale.current.analyticsLanguageCode
].merging(additionalParams) { (current, _) in current }

return .init(
name: "Navigation",
params: params.compactMapValues { $0 }
)
}
}
Original file line number Diff line number Diff line change
@@ -1,53 +1,53 @@
import Foundation

struct Constants {
struct API {
static let govukUrlHost = "www.gov.uk"
static let govukUrlScheme = "https"
public struct Constants {
public struct API {
public static let govukUrlHost = "www.gov.uk"
public static let govukUrlScheme = "https"
private static let govukBaseComponents: URLComponents = {
var components = URLComponents()
components.host = govukUrlHost
components.scheme = govukUrlScheme
return components
}()
static let govukBaseUrl: URL = govukBaseComponents.url!
public static let govukBaseUrl: URL = govukBaseComponents.url!

static let appStoreAppUrl = URL(string: "https://beta.itunes.apple.com/v1/app/6572293285")!
public static let appStoreAppUrl = URL(string: "https://beta.itunes.apple.com/v1/app/6572293285")!

static let helpAndFeedbackUrl: URL = {
public static let helpAndFeedbackUrl: URL = {
var components = govukBaseComponents
components.path = "/contact/govuk-app"
return components.url!
}()

static let termsAndConditionsUrl: URL = {
public static let termsAndConditionsUrl: URL = {
var components = govukBaseComponents
components.path = "/government/publications/govuk-app-terms-and-conditions"
return components.url!
}()

static let accessibilityStatementUrl: URL = {
public static let accessibilityStatementUrl: URL = {
var components = govukBaseComponents
components.path = """
/government/publications/accessibility-statement-for-the-govuk-app
"""
return components.url!
}()

static let privacyPolicyUrl: URL = {
public static let privacyPolicyUrl: URL = {
var components = govukBaseComponents
components.path = """
/government/publications/govuk-app-privacy-notice-how-we-use-your-data
"""
return components.url!
}()

static let defaultSearchUrl: URL = URL(string: "https://search.service.gov.uk")!
public static let defaultSearchUrl: URL = URL(string: "https://search.service.gov.uk")!

static var defaultSearchPath: String = "/v0_1/search.json"
public static var defaultSearchPath: String = "/v0_1/search.json"
}

struct SigningKey {
static let govUK = "integration_pubkey"
public struct SigningKey {
public static let govUK = "integration_pubkey"
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Foundation

extension Locale {
var analyticsLanguageCode: String {
public var analyticsLanguageCode: String {
return language.languageCode?.identifier ?? "Unknown"
}
}
Loading

0 comments on commit fea7235

Please sign in to comment.