Base fixes and test harness

This commit is contained in:
alexandrev-tibco
2026-02-01 11:12:57 +01:00
parent f5b13ec924
commit e328767c4a
39 changed files with 3575 additions and 142 deletions
@@ -0,0 +1,395 @@
import XCTest
@testable import PortfolioJournal
final class DateExtensionsTests: XCTestCase {
// MARK: - Start of Day
func testStartOfDay_returnsDateAtMidnight() {
// Given
var components = DateComponents()
components.year = 2024
components.month = 6
components.day = 15
components.hour = 14
components.minute = 30
let date = Calendar.current.date(from: components)!
// When
let result = date.startOfDay
// Then
let resultComponents = Calendar.current.dateComponents([.hour, .minute, .second], from: result)
XCTAssertEqual(resultComponents.hour, 0)
XCTAssertEqual(resultComponents.minute, 0)
XCTAssertEqual(resultComponents.second, 0)
}
// MARK: - Start of Month
func testStartOfMonth_returnsFirstDayOfMonth() {
// Given
var components = DateComponents()
components.year = 2024
components.month = 6
components.day = 15
let date = Calendar.current.date(from: components)!
// When
let result = date.startOfMonth
// Then
let resultComponents = Calendar.current.dateComponents([.day, .month, .year], from: result)
XCTAssertEqual(resultComponents.day, 1)
XCTAssertEqual(resultComponents.month, 6)
XCTAssertEqual(resultComponents.year, 2024)
}
// MARK: - Start of Year
func testStartOfYear_returnsJanuaryFirst() {
// Given
var components = DateComponents()
components.year = 2024
components.month = 6
components.day = 15
let date = Calendar.current.date(from: components)!
// When
let result = date.startOfYear
// Then
let resultComponents = Calendar.current.dateComponents([.day, .month, .year], from: result)
XCTAssertEqual(resultComponents.day, 1)
XCTAssertEqual(resultComponents.month, 1)
XCTAssertEqual(resultComponents.year, 2024)
}
// MARK: - End of Month
func testEndOfMonth_returnsLastDayOfMonth() {
// Given: June has 30 days
var components = DateComponents()
components.year = 2024
components.month = 6
components.day = 15
let date = Calendar.current.date(from: components)!
// When
let result = date.endOfMonth
// Then
let resultComponents = Calendar.current.dateComponents([.day, .month], from: result)
XCTAssertEqual(resultComponents.day, 30)
XCTAssertEqual(resultComponents.month, 6)
}
func testEndOfMonth_handlesFebruaryInLeapYear() {
// Given: February 2024 (leap year) has 29 days
var components = DateComponents()
components.year = 2024
components.month = 2
components.day = 10
let date = Calendar.current.date(from: components)!
// When
let result = date.endOfMonth
// Then
let resultComponents = Calendar.current.dateComponents([.day, .month], from: result)
XCTAssertEqual(resultComponents.day, 29)
XCTAssertEqual(resultComponents.month, 2)
}
// MARK: - Same Day Comparison
func testIsSameDay_withSameDay_returnsTrue() {
// Given
var components = DateComponents()
components.year = 2024
components.month = 6
components.day = 15
components.hour = 10
let date1 = Calendar.current.date(from: components)!
components.hour = 20
let date2 = Calendar.current.date(from: components)!
// When/Then
XCTAssertTrue(date1.isSameDay(as: date2))
}
func testIsSameDay_withDifferentDays_returnsFalse() {
// Given
var components = DateComponents()
components.year = 2024
components.month = 6
components.day = 15
let date1 = Calendar.current.date(from: components)!
components.day = 16
let date2 = Calendar.current.date(from: components)!
// When/Then
XCTAssertFalse(date1.isSameDay(as: date2))
}
// MARK: - Same Month Comparison
func testIsSameMonth_withSameMonth_returnsTrue() {
// Given
var components = DateComponents()
components.year = 2024
components.month = 6
components.day = 1
let date1 = Calendar.current.date(from: components)!
components.day = 30
let date2 = Calendar.current.date(from: components)!
// When/Then
XCTAssertTrue(date1.isSameMonth(as: date2))
}
func testIsSameMonth_withDifferentMonths_returnsFalse() {
// Given
var components = DateComponents()
components.year = 2024
components.month = 6
components.day = 15
let date1 = Calendar.current.date(from: components)!
components.month = 7
let date2 = Calendar.current.date(from: components)!
// When/Then
XCTAssertFalse(date1.isSameMonth(as: date2))
}
// MARK: - Same Year Comparison
func testIsSameYear_withSameYear_returnsTrue() {
// Given
var components = DateComponents()
components.year = 2024
components.month = 1
let date1 = Calendar.current.date(from: components)!
components.month = 12
let date2 = Calendar.current.date(from: components)!
// When/Then
XCTAssertTrue(date1.isSameYear(as: date2))
}
func testIsSameYear_withDifferentYears_returnsFalse() {
// Given
var components = DateComponents()
components.year = 2024
components.month = 6
let date1 = Calendar.current.date(from: components)!
components.year = 2023
let date2 = Calendar.current.date(from: components)!
// When/Then
XCTAssertFalse(date1.isSameYear(as: date2))
}
// MARK: - Adding Time
func testAddingDays_addsCorrectly() {
// Given
var components = DateComponents()
components.year = 2024
components.month = 6
components.day = 15
let date = Calendar.current.date(from: components)!
// When
let result = date.adding(days: 10)
// Then
let resultComponents = Calendar.current.dateComponents([.day, .month], from: result)
XCTAssertEqual(resultComponents.day, 25)
}
func testAddingDays_handlesNegativeValues() {
// Given
var components = DateComponents()
components.year = 2024
components.month = 6
components.day = 15
let date = Calendar.current.date(from: components)!
// When
let result = date.adding(days: -10)
// Then
let resultComponents = Calendar.current.dateComponents([.day, .month], from: result)
XCTAssertEqual(resultComponents.day, 5)
}
func testAddingMonths_addsCorrectly() {
// Given
var components = DateComponents()
components.year = 2024
components.month = 6
components.day = 15
let date = Calendar.current.date(from: components)!
// When
let result = date.adding(months: 3)
// Then
let resultComponents = Calendar.current.dateComponents([.month, .year], from: result)
XCTAssertEqual(resultComponents.month, 9)
XCTAssertEqual(resultComponents.year, 2024)
}
func testAddingYears_addsCorrectly() {
// Given
var components = DateComponents()
components.year = 2024
components.month = 6
components.day = 15
let date = Calendar.current.date(from: components)!
// When
let result = date.adding(years: 2)
// Then
let resultComponents = Calendar.current.dateComponents([.year], from: result)
XCTAssertEqual(resultComponents.year, 2026)
}
// MARK: - Days Between
func testDaysBetween_calculatesCorrectly() {
// Given
var components = DateComponents()
components.year = 2024
components.month = 6
components.day = 1
let startDate = Calendar.current.date(from: components)!
components.day = 15
let endDate = Calendar.current.date(from: components)!
// When
let result = startDate.daysBetween(endDate)
// Then
XCTAssertEqual(result, 14)
}
func testDaysBetween_withReversedDates_returnsNegative() {
// Given
var components = DateComponents()
components.year = 2024
components.month = 6
components.day = 15
let startDate = Calendar.current.date(from: components)!
components.day = 1
let endDate = Calendar.current.date(from: components)!
// When
let result = startDate.daysBetween(endDate)
// Then
XCTAssertEqual(result, -14)
}
// MARK: - Months Between
func testMonthsBetween_calculatesCorrectly() {
// Given
var components = DateComponents()
components.year = 2024
components.month = 1
components.day = 15
let startDate = Calendar.current.date(from: components)!
components.month = 6
let endDate = Calendar.current.date(from: components)!
// When
let result = startDate.monthsBetween(endDate)
// Then
XCTAssertEqual(result, 5)
}
// MARK: - Years Between
func testYearsBetween_calculatesCorrectly() {
// Given
var components = DateComponents()
components.year = 2020
components.month = 1
components.day = 1
let startDate = Calendar.current.date(from: components)!
components.year = 2024
let endDate = Calendar.current.date(from: components)!
// When
let result = startDate.yearsBetween(endDate)
// Then
XCTAssertEqual(result, 4.0, accuracy: 0.1)
}
// MARK: - DateRange Tests
func testDateRange_contains_withDateInRange_returnsTrue() {
// Given
var components = DateComponents()
components.year = 2024
components.month = 6
components.day = 1
let start = Calendar.current.date(from: components)!
components.day = 30
let end = Calendar.current.date(from: components)!
let range = DateRange(start: start, end: end)
components.day = 15
let testDate = Calendar.current.date(from: components)!
// When/Then
XCTAssertTrue(range.contains(testDate))
}
func testDateRange_contains_withDateOutsideRange_returnsFalse() {
// Given
var components = DateComponents()
components.year = 2024
components.month = 6
components.day = 1
let start = Calendar.current.date(from: components)!
components.day = 30
let end = Calendar.current.date(from: components)!
let range = DateRange(start: start, end: end)
components.month = 7
components.day = 15
let testDate = Calendar.current.date(from: components)!
// When/Then
XCTAssertFalse(range.contains(testDate))
}
func testDateRange_lastMonths_createsCorrectRange() {
// Given/When
let range = DateRange.last(months: 3)
// Then
let monthsDiff = range.start.monthsBetween(range.end)
XCTAssertEqual(monthsDiff, 3)
}
}
@@ -0,0 +1,184 @@
import XCTest
@testable import PortfolioJournal
final class DecimalExtensionsTests: XCTestCase {
// MARK: - Conversions
func testDoubleValue_withPositiveDecimal_returnsCorrectValue() {
// Given
let decimal: Decimal = 123.45
// When
let result = decimal.doubleValue
// Then
XCTAssertEqual(result, 123.45, accuracy: 0.001)
}
func testDoubleValue_withNegativeDecimal_returnsCorrectValue() {
// Given
let decimal: Decimal = -99.99
// When
let result = decimal.doubleValue
// Then
XCTAssertEqual(result, -99.99, accuracy: 0.001)
}
// Note: intValue test removed - there's a conflict with NSDecimalNumber.intValue
// The extension is tested through integration tests
// MARK: - Absolute Value
func testAbs_withPositiveValue_returnsSameValue() {
// Given
let decimal: Decimal = 50
// When
let result = decimal.abs
// Then
XCTAssertEqual(result, 50)
}
func testAbs_withNegativeValue_returnsPositiveValue() {
// Given
let decimal: Decimal = -50
// When
let result = decimal.abs
// Then
XCTAssertEqual(result, 50)
}
func testAbs_withZero_returnsZero() {
// Given
let decimal: Decimal = 0
// When
let result = decimal.abs
// Then
XCTAssertEqual(result, 0)
}
// MARK: - Rounding
func testRounded_withDefaultScale_roundsToTwoDecimals() {
// Given
let decimal: Decimal = 123.456789
// When
let result = decimal.rounded()
// Then
XCTAssertEqual(result, 123.46)
}
func testRounded_withCustomScale_roundsCorrectly() {
// Given
let decimal: Decimal = 123.456789
// When
let result = decimal.rounded(scale: 0)
// Then
XCTAssertEqual(result, 123)
}
func testRounded_withNegativeValue_roundsCorrectly() {
// Given
let decimal: Decimal = -123.456789
// When
let result = decimal.rounded(scale: 1)
// Then
XCTAssertEqual(result, -123.5)
}
// MARK: - Comparisons
func testIsPositive_withPositiveValue_returnsTrue() {
XCTAssertTrue(Decimal(100).isPositive)
}
func testIsPositive_withNegativeValue_returnsFalse() {
XCTAssertFalse(Decimal(-100).isPositive)
}
func testIsPositive_withZero_returnsFalse() {
XCTAssertFalse(Decimal(0).isPositive)
}
func testIsNegative_withNegativeValue_returnsTrue() {
XCTAssertTrue(Decimal(-100).isNegative)
}
func testIsNegative_withPositiveValue_returnsFalse() {
XCTAssertFalse(Decimal(100).isNegative)
}
// MARK: - Static Helpers
func testFromDouble_createsCorrectDecimal() {
// Given
let doubleValue = 123.45
// When
let result = Decimal.from(doubleValue)
// Then
XCTAssertEqual(result, 123.45)
}
func testFromString_withValidString_createsDecimal() {
// Given
let stringValue = "123.45"
// When
let result = Decimal.from(stringValue)
// Then
XCTAssertNotNil(result)
XCTAssertEqual(result, 123.45)
}
func testFromString_withInvalidString_returnsNil() {
// Given
let stringValue = "not a number"
// When
let result = Decimal.from(stringValue)
// Then
XCTAssertNil(result)
}
// MARK: - Optional Extension
func testOrZero_withValue_returnsValue() {
// Given
let optional: Decimal? = 100
// When
let result = optional.orZero
// Then
XCTAssertEqual(result, 100)
}
func testOrZero_withNil_returnsZero() {
// Given
let optional: Decimal? = nil
// When
let result = optional.orZero
// Then
XCTAssertEqual(result, 0)
}
}