Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/ios-pr-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ jobs:
run: ./Scripts/prepare-ios-simulator.sh

# Tuist가 테스트 산출물을 원격 shard storage에 올리고 matrix JSON을 GITHUB_OUTPUT으로 내보낸다.
# 소스 경로 매핑은 xctestrun의 원본 소스 목록과 달라져 xccov가 0/0을 기록한다.
# 커버리지 빌드만 원본 경로를 유지하고 컴파일 캐시는 계속 사용한다.
- name: Build and plan test shards
id: build
continue-on-error: true
Expand All @@ -113,6 +115,10 @@ jobs:
-destination "$SIMULATOR_DESTINATION" \
-derivedDataPath "$CI_DERIVED_DATA" \
-enableCodeCoverage YES \
SWIFT_ENABLE_PREFIX_MAPPING=NO \
SWIFT_ENABLE_PROJECT_PREFIX_MAPPING=NO \
CLANG_ENABLE_PREFIX_MAPPING=NO \
CLANG_ENABLE_PROJECT_PREFIX_MAPPING=NO \
-collect-test-diagnostics never \
ONLY_ACTIVE_ARCH=YES \
COMPILATION_CACHE_ENABLE_CACHING="$XCODE_COMPILATION_CACHE_ENABLED" \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Foundation
import ProjectDescription

public extension String {
static func appVersion(version: String = "1.1.0") -> String {
static func appVersion(version: String = "1.1.1") -> String {
return version
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,7 @@ extension OnBoardingCoordinator {
.routeAction(id: _, action: .selectPart(.delegate(.presentBack))),
.routeAction(id: _, action: .selectManaging(.delegate(.presentBack))),
.routeAction(id: _, action: .selectTeam(.delegate(.presentBack))):
state.routes.goBack()
return .none
return .send(.view(.backAction))

// MARK: - 이름 입력

Expand Down
28 changes: 28 additions & 0 deletions Projects/App/Tests/Sources/AppStateTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,34 @@ import TCAFlow

@Suite("App State")
struct AppStateTests {
@MainActor
@Test("이름 뒤로가기는 로그인으로 나가지 않고 초대 코드로 돌아온다")
func nameBackReturnsToInviteCode() async {
var onboarding = OnBoardingCoordinator.State()
onboarding.routes.append(.push(.onBoardingName(.init())))
var state = AuthCoordinator.State()
state.routes.append(.push(.onboarding(onboarding)))
let store = Store(initialState: state) { AuthCoordinator() }

await store.send(.router(.routeAction(
id: 1,
action: .onboarding(.router(.routeAction(
id: 1, action: .onBoardingName(.delegate(.presentBack))
)))
))).finish()

#expect(store.routes.count == 2)
guard case let .onboarding(result) = store.routes.last?.screen else {
Issue.record("이름 뒤로가기 후에도 온보딩이 유지되어야 한다")
return
}
#expect(result.routes.count == 1)
guard case .InviteCode = result.routes.first?.screen else {
Issue.record("초대 코드 화면으로 돌아와야 한다")
return
}
}

@MainActor
@Test("중첩 가입 라우터는 이름 다음 직무 화면까지 표시한다")
func nestedOnboardingDisplaysSecondPush() async throws {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public struct SelectPartView: View {
Spacer()
.frame(height: 12)

StepNavigationBar(activeStep: 2) {
StepNavigationBar().activeStep(2).buttonAction {
store.send(.delegate(.presentBack))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@ public struct OnBoardingNameView: View {
Spacer()
.frame(height: 12)

StepNavigationBar(activeStep: 1) {
store.send(.delegate(.presentBack))
}
StepNavigationBar()
.activeStep(1)
.buttonAction {
store.send(.delegate(.presentBack))
}

ScrollView {
signUpNameText()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ public struct SelectManagingView: View {
Spacer()
.frame(height: 12)

StepNavigationBar(activeStep: 3) {
store.send(.delegate(.presentBack))
}
StepNavigationBar()
.activeStep(3)
.buttonAction {
store.send(.delegate(.presentBack))
}

// 목록을 받아오는 동안 실제 화면과 같은 자리에서 스켈레톤을 보여준다.
switch store.viewState {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ public struct SelectTeamView: View {
Spacer()
.frame(height: 12)

StepNavigationBar(activeStep: 3) {
store.send(.delegate(.presentBack))
}
StepNavigationBar()
.activeStep(3)
.buttonAction {
store.send(.delegate(.presentBack))
}

// 목록을 받아오는 동안 실제 화면과 같은 자리에서 스켈레톤을 보여준다.
switch store.viewState {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@ import ComposableArchitecture
struct OnBoardingNameReducerTests {
@Test("입력한 이름으로 다음 이동을 요청한다", arguments: ["서원지", "가나다라마"])
func enteredNameNavigates(name: String) async {
let store = TestStore(initialState: OnBoardingNameFeature.State()) {
var state = OnBoardingNameFeature.State()
// 매개변수 케이스끼리 같은 영속 키의 세션을 공유하지 않도록 분리한다.
state.$userSession = Shared(value: .empty)
let store = TestStore(initialState: state) {
OnBoardingNameFeature()
}
await store.send(.view(.nameChanged(name))) {
$0.$userSession.withLock { $0.name = name }
}
#expect(store.state.userSession.name == name)
#expect(store.state.enableButton)
await store.send(.view(.checkIsAvailableName))
await store.receive(\.delegate.presentSignUpPart)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,24 @@
import SwiftUI

public struct StepNavigationBar: View {
private var activeStep: Int
private var buttonAction: () -> Void

public init(
activeStep: Int,
buttonAction: @escaping () -> Void
) {
self.activeStep = activeStep
self.buttonAction = buttonAction
}
private var activeStep = 1
private var buttonAction: () -> Void = {}

public init() {}

public var body: some View {
HStack {
Image(asset: .backButton)
.resizable()
.scaledToFit()
.frame(width: 12, height: 20)
.foregroundStyle(Color.gray400)
.onTapGesture {
buttonAction()
}
Button(action: buttonAction) {
Image(asset: .backButton)
.resizable()
.scaledToFit()
.frame(width: 12, height: 20)
.foregroundStyle(.gray400)
.frame(width: 44, height: 44)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep the step indicators centered

Adding a 44-point frame only on the leading side changes the space distributed by the two Spacers, shifting the progress indicators more than 20 points to the right on every onboarding screen. Preserve the larger tap target while balancing it with an equivalent trailing placeholder or overlaying the back button so the indicators remain centered.

Useful? React with 👍 / 👎.

.contentShape(Rectangle())
}
.buttonStyle(.plain)
.accessibilityLabel("뒤로가기")

Spacer()

Expand All @@ -51,7 +48,6 @@ public struct StepNavigationBar: View {
// MARK: - 체이닝 설정
//
// 값 타입 사본을 돌려주므로 호출 순서에 영향받지 않는다.
// 기존 init 은 그대로 두어, 체이닝은 선택지로만 더한다.
public extension StepNavigationBar {
/// `activeStep` 을 바꾼 사본을 돌려준다.
func activeStep(_ activeStep: Int) -> Self {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ struct DDDDesignKitTests {
}

build(NavigationBackButton(buttonAction: {}).buttonAction({}))
build(StepNavigationBar(activeStep: 1, buttonAction: {}).activeStep(3).buttonAction({}))
build(StepNavigationBar().activeStep(3).buttonAction({}))
build(CustomNavigationBackBar(buttonAction: {}))
build(
CustomNavigationBar(backAction: {}, addAction: {}, image: .plus)
Expand Down
17 changes: 17 additions & 0 deletions Scripts/ci-workflow-structure.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,23 @@ function job(source, name, nextName) {
return source.slice(start, end);
}

test("커버리지 빌드는 원본 소스 경로를 유지하면서 컴파일 캐시를 사용한다", () => {
const build = job(read(".github/workflows/ios-pr-coverage.yml"), "build-test-shards", "test-shards");
const tests = read("Scripts/run-isolated-module-tests.sh");
for (const command of [build, tests]) {
assert.match(command, /-enableCodeCoverage YES/);
for (const setting of [
"SWIFT_ENABLE_PREFIX_MAPPING",
"SWIFT_ENABLE_PROJECT_PREFIX_MAPPING",
"CLANG_ENABLE_PREFIX_MAPPING",
"CLANG_ENABLE_PROJECT_PREFIX_MAPPING",
]) {
assert.ok(command.includes(`${setting}=NO`), setting);
}
assert.match(command, /COMPILATION_CACHE_ENABLE_CACHING=/);
}
});

test("iOS workflow는 공통 runner setup action을 사용한다", () => {
const action = read(".github/actions/setup-ios-runner/action.yml");
assert.match(action, /using: composite/);
Expand Down
4 changes: 4 additions & 0 deletions Scripts/run-isolated-module-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ mise exec -- tuist test run "$TEST_SCHEME" \
-destination "$SIMULATOR_DESTINATION" \
-derivedDataPath "$CI_DERIVED_DATA" \
-enableCodeCoverage YES \
SWIFT_ENABLE_PREFIX_MAPPING=NO \
SWIFT_ENABLE_PROJECT_PREFIX_MAPPING=NO \
CLANG_ENABLE_PREFIX_MAPPING=NO \
CLANG_ENABLE_PROJECT_PREFIX_MAPPING=NO \
-retry-tests-on-failure \
-test-iterations 2 \
-collect-test-diagnostics never \
Expand Down
Loading