v1.1.7 changed isTradingHour to always return true on weekdays (the US
four-session + overnight coverage spans 24h). Two tests still asserted
the pre-v1.1.7 lunch-break / after-close = not-trading behavior and
have been failing locally for months; CI's new Run Tests step caught
them and aborted the v1.3.5 release.
Update both tests to assert the current desired behavior (trading) and
add a comment explaining the rationale.
PRIOR BEHAVIOR (data-loss bug):
AppStateTests.setUp() constructed AppState() directly, which used the real
~/Library/Application Support/Stockbar/ for stocks.json. Each test method
that did 'sut.stocks = [s1, s2]' triggered didSet → saveStocks → silently
overwrote the user's actual portfolio file with 2 test entries. backupIfNeeded
then rolled all 10 backup snapshots forward, eventually erasing every
historical copy of real data.
This destroyed a user's 29-stock portfolio when xcodebuild test was run
during Korean stock feature development (2026-05-14 10:08).
FIX:
- AppState gains a static appSupportDirOverride: URL? hook
- AppStateTests.setUp() creates a unique tmpDir, sets the override, tearDown
resets and removes the directory
- Verified: after running all 7 AppStateTests, the real stocks.json is
byte-identical to before the run.
This must land before any further test run touches AppState.
Pre-existing test asserted quotes["159941"] != nil but raw data only
contains sh600000 and sz000001 — typo in original assertion. Replace with
the two real codes.
Note: two RefreshSchedulerTests (afterClose, lunchBreak) still fail; they
expose a long-standing 'return true; return false' bug in isTradingHour
(weekdays always trade). Out of scope for the Korean stocks change.
ChartService.fetchIntraday dispatches .krStock to new fetchKoreanIntraday,
which reuses the Yahoo v8 chart endpoint. parseKoreanChartPoints (exposed
static for tests) maps KST timestamps to indices: 09:00 → 0, 15:29 → 389
(KR session is 6.5h = 390 minutes, no pre/post market).
RefreshScheduler comment updated to note KR trading window (KST 09:00-15:30
= BJ 08:00-14:30) is already covered by the always-true weekday branch.
AppState.koreanMarketSession (nonisolated) returns '盘中' during KST 09:00-15:30
on weekdays, nil otherwise. Marked nonisolated so it can be called from sync
non-MainActor contexts (notably tests).
AppState.refresh now has a 5th parallel branch fetching Korean quotes via
DataService.fetchKoreanQuotes. KR is non-throwing (returns [:] on failure) so
it's awaited outside the try block — any KR network failure does not abort
A股/港股fetch results.
DataService.parseKoreanChartMeta parses Yahoo v8 chart 'meta' segment into
Quote (price/change/percent/updateTime). Yahoo v7 batch quote endpoint
returns 401 since 2024, so we fall back to v8 chart per-symbol.
DataService.fetchKoreanQuotes uses withTaskGroup to issue concurrent
requests for the watchlist; single-symbol failure does not affect others.
Fixtures captured from live API for KOSPI (005930.KS Samsung) and KOSDAQ
(293490.KQ Pearl Abyss); synthetic quote_empty.json covers null price.
Adding Market.krStock cascades into several exhaustive switches that must all
update together: ExchangeRates.convert, DisplayCurrency, StockChartView ranges
and labels. Bundles tasks 2/3/4/5/14 into one build-passing landing.
- Market enum: add krStock case + kr_ prefix routing in Market.from
- ExchangeRates: add usdToKrw (fallback 1380), krwToCny derived, KRW path in convert
- DisplayCurrency: add .krw (₩), display name 韩元
- CurrencyService.fetchRates: include fx_susdkrw in Sina FX batch URL
- StockChartView: KR fullDayRange 0...389 (KST 09:00-15:30, 390 min); KR axis labels
09:00/10:30/12:00/13:30/15:30
Tests: +5 Stock cases for KR, +8 CurrencyKRWTests covering all KR↔CNY/USD/HKD/KRW
conversion paths and fallback constant.
Pre-existing tests called AppSettings(colorScheme:, refreshInterval:, statusBarStockId:)
which no longer compiles after AppSettings struct refactor. Switch to default
init + mutation pattern; behavior unchanged.