Skip to content

More tests#7

Merged
Sajjon merged 7 commits into
mainfrom
test_diprimitives_coverage
May 12, 2026
Merged

More tests#7
Sajjon merged 7 commits into
mainfrom
test_diprimitives_coverage

Conversation

@Sajjon
Copy link
Copy Markdown
Owner

@Sajjon Sajjon commented May 12, 2026

Adds test files for DateProvider, HapticFeedback, MainScheduler, and the Pasteboard protocol-extension overload so the only previously-tested primitive (Clock) is no longer alone. The DefaultPasteboard production writes and DefaultUrlOpener.open are intentionally left uncovered — exercising them requires touching UIPasteboard.general / UIApplication.shared, which is flaky and slow on the simulator and defeats the abstraction.

Adds test files for DateProvider, HapticFeedback, MainScheduler, and the
Pasteboard protocol-extension overload so the only previously-tested
primitive (Clock) is no longer alone. The DefaultPasteboard production
writes and DefaultUrlOpener.open are intentionally left uncovered —
exercising them requires touching UIPasteboard.general / UIApplication.shared,
which is flaky and slow on the simulator and defeats the abstraction.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented May 12, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.08%. Comparing base (8c21616) to head (3e8b87a).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main       #7      +/-   ##
==========================================
+ Coverage   87.77%   96.08%   +8.31%     
==========================================
  Files          30       18      -12     
  Lines        1562      511    -1051     
==========================================
- Hits         1371      491     -880     
+ Misses        191       20     -171     

see 23 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sajjon and others added 3 commits May 12, 2026 07:36
Replaces the wide xccov text dump with a SwiftIntro-style coverage table:
one Unicode box per non-test target, colour-coded green/yellow/red, plus a
grand total across all libraries. The result-bundle → JSON conversion
moves into _run-cov so cov-cobertura also benefits from a single source
of truth.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Lifts package coverage from 70% to 91% by:

  * Core: deeper ActivityIndicator lifecycle tests (subscribe/output/
    completion/cancellation flips) and a stub-subclass exercise of
    AbstractViewModel.
  * Combine: binders for UIControl.isEnabled, UIControl.becomeFirstResponder,
    UILabel.text, UIButton.titleBinder(for:), UIActivityIndicatorView
    isAnimatingBinder; UITextField + UITextView text/placeholder binders
    and notification-driven textPublisher / isEditingPublisher /
    didBeginEditingPublisher; UITextView.isNearBottomPublisher.

The remaining gaps are unreachable without a host app:
.editingDidBegin/.editingDidEnd on UIControl don't fire reliably under
sendActions(for:) in an SPM test target without a window, and
Never+Helpers.swift's three fatalError traps are uncoverable by design.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
New tests close the reachable gaps in already-tested files:

  * ErrorTracker.compactMap typed-error projection
  * WithLatestFromPublisher upstream-completion forwarding
  * UIControlPublisher dead-control branch (control deallocated
    before subscribe)
  * UITextView.isNearBottomPublisher overflow path (contentSize >
    frame, threshold comparison)

Add codecov.yml + teach scripts/cov_table.py to honour its ignore
list. Three files are excluded so the metric reflects what's
actually testable from this SPM-only test setup:

  * Pasteboard.swift / UrlOpener.swift — production wrappers around
    UIPasteboard.general / UIApplication.shared. Covered via mock
    conformers; testing live singletons was flaky and slow.
  * Never+Helpers.swift — three fatalError traps that deliberately
    crash on invariant violations.

Result: total coverage 97.4% (631/648), Combine 97.4%, Core 95.7%,
DIPrimitives 100%. Controller / Navigation / SceneViews still have
no test target wired up at all.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds broader unit test coverage across the package’s “primitives” and Combine/Core helpers, and introduces local/CI coverage reporting configuration aligned with Codecov.

Changes:

  • Adds new XCTest files covering DI primitives (DateProvider, HapticFeedback, MainScheduler, Pasteboard convenience overload) plus additional Core/Combine branches.
  • Introduces a scripts/cov_table.py helper to render per-target/per-file coverage tables, and wires it into just cov.
  • Adds a codecov.yml configuration (project coverage status; patch coverage disabled; ignore list for excluded files).

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
Tests/NanoViewControllerDIPrimitivesTests/PasteboardTests.swift Tests Pasteboard.copy(_:) extension overload forwarding behavior.
Tests/NanoViewControllerDIPrimitivesTests/MainSchedulerTests.swift Tests ImmediateMainScheduler sync behavior and DispatchMainScheduler async behavior.
Tests/NanoViewControllerDIPrimitivesTests/HapticFeedbackTests.swift Smoke-coverage for DefaultHapticFeedback.notify(_:) across feedback types.
Tests/NanoViewControllerDIPrimitivesTests/DateProviderTests.swift Tests DefaultDateProvider.now() against wall-clock bounds / progression.
Tests/NanoViewControllerCoreTests/ErrorTrackerCompactMapTests.swift Covers typed projections via ErrorTracker.compactMap(_:).
Tests/NanoViewControllerCoreTests/ActivityIndicatorTests.swift Verifies activity lifecycle pulses flip the indicator as documented.
Tests/NanoViewControllerCoreTests/AbstractViewModelTests.swift Exercises AbstractViewModel input stitching and override behavior.
Tests/NanoViewControllerCombineTests/WithLatestFromCompletionTests.swift Covers upstream completion forwarding in withLatestFrom.
Tests/NanoViewControllerCombineTests/UIViewBindersTests.swift Covers UIActivityIndicatorView.isAnimatingBinder start/stop branches.
Tests/NanoViewControllerCombineTests/UITextFieldPublishersTests.swift Covers text binders/publishers and UITextView “near bottom” helpers.
Tests/NanoViewControllerCombineTests/UIControlPublisherDeadControlTests.swift Covers “control already deallocated” completion path.
Tests/NanoViewControllerCombineTests/UIControlBindersTests.swift Covers UIControl/UILabel/UIButton binder helpers.
scripts/cov_table.py New script to print per-target/per-file coverage tables honoring Codecov ignore patterns.
justfile Updates cov to use cov_table.py; moves JSON generation into _run-cov.
codecov.yml Adds Codecov configuration and coverage ignore list.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +20 to +27
func test_now_advancesMonotonically() async throws {
let provider = DefaultDateProvider()
let first = provider.now()
try await Task.sleep(for: .milliseconds(20))
let second = provider.now()

XCTAssertGreaterThan(second, first)
}
Comment thread codecov.yml Outdated
Comment on lines +51 to +56
# - SceneViews / Navigation / Controller — large UIKit-bound modules
# with no test target wired up yet. They contribute 0 lines to xccov
# because they're never exercised; listing them here makes that
# intent explicit (and prevents future contributors from being
# confused by a sudden coverage drop when one of them gets its first
# test).
Comment thread scripts/cov_table.py
Comment on lines +19 to +20
COV_JSON = sys.argv[1]

  * DateProviderTests: drop the `>` monotonicity assertion — `Date()` is
    a wall-clock read, not strictly monotonic, so an NTP adjustment or
    fast successive calls could fail the assertion. Replace with a
    bounded-window check that still re-exercises `now()` without baking
    in an ordering invariant the API doesn't promise.
  * codecov.yml: rewrite the misleading SceneViews/Navigation/Controller
    note. Those modules are intentionally NOT in the ignore list — they
    have no test target yet, so xccov reports 0 lines (not 0%), and once
    a test target is added they should count toward the total.
  * scripts/cov_table.py: validate sys.argv length and print a usage
    line + exit 2 instead of letting an IndexError propagate.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.

// MIT License — Copyright (c) 2018-2026 Alexander Cyon (github.com/sajjon)

@testable import NanoViewControllerDIPrimitives
import UIKit
Comment on lines +7 to +8
/// returns `Date()`. Verifies that successive `now()` calls advance
/// monotonically and stay within a tight window of the real wall clock.
Comment on lines +21 to +31
// `Date()` reads the wall clock, which is not strictly monotonic
// (an NTP adjustment can move it backward, and successive reads on
// fast hardware can return equal timestamps). We only assert that
// the second read stays within a generous window of the first —
// enough to cover the `now()` line a second time without baking in
// a brittle ordering invariant the underlying API doesn't promise.
let provider = DefaultDateProvider()
let first = provider.now()
let second = provider.now()

XCTAssertLessThan(abs(second.timeIntervalSince(first)), 1.0)
Sajjon and others added 2 commits May 12, 2026 12:01
  * DateProviderTests: reword the file's doc-comment so it no longer
    claims a monotonicity invariant the tests deliberately don't assert.
    Widen the bounded-window check from 1s to 30s so contended CI runners
    (which can stall arbitrary user code for seconds) don't flake; the
    looser envelope still catches a wholly-broken impl.
  * PasteboardTests: drop the unused `import UIKit` (the file references
    no UIKit symbols directly — the `Pasteboard` protocol's UIKit import
    propagates transitively but doesn't belong in the test file).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds `// ARRANGE`, `// ACT`, `// ASSERT` markers inside each test
function across all 22 test files in the package. The mechanical
restructure preserves every assertion and ordering; behaviour is
unchanged. All 89 tests still pass after the refactor.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@Sajjon Sajjon merged commit 8c50130 into main May 12, 2026
2 checks passed
@Sajjon Sajjon deleted the test_diprimitives_coverage branch May 12, 2026 18:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants