Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't inspect views nested in custom container view with generic content #343

Open
qeude opened this issue Oct 16, 2024 · 1 comment
Open
Labels
help wanted Extra attention is needed

Comments

@qeude
Copy link

qeude commented Oct 16, 2024

Hello!

I've been trying to use ViewInspector to test some of my screen, and it seems like there is no way to retrieve and inspect views contained in a container view with generic content.
So to explain, I have these views

SutView

struct SutView: View {
  @StateObject var viewModel: SutViewModel
  @FocusState private var isFocused: Bool

  var body: some View {
    VStack(spacing: 0) {
      CustomView(viewModel: viewModel, errorProcessor: { DefaultErrorViewModel(error: $0) }, actions: self)
      if case .data = viewModel.state {
        if isInputBarHidden == false {
          inputView
        }
      }
    }
    .navigationBarTitleDisplayMode(.inline)
    .task(id: viewModel.taskId) {
      await viewModel.refreshData(silent: false)
    }
    .task(id: isFocused) {
      guard isFocused == true else { return }
      try? await Task.sleep(seconds: 0.4)
    }
    .flashMessage(isPresented: $viewModel.isFlashMessageVisible, model: viewModel.flashMessage)
    .toolbarConfiguration(backgroundColor: CustomFoundation.Color.Background.primary())
    .onDisappear {
      viewModel.stopPolling()
    }
  }

CustomView

public struct CustomView<T: Hashable, Content: View, Footer: View>: View {
  let state: ViewState<T>
  let content: (T) -> Content
  let footer: ((T) -> Footer)?

  public var body: some View {
    ZStack {
      switch state {
      case .initial, .loading:
        ProgressView()
      case .error(let error):
        if let errorProcessor {
          ErrorView(processor: errorProcessor(error))
        }
      case .data(let data):
        Group {
          if let footer {
            CustomContentView(scrollable: scrollable, fitContent: fitContent, padding: contentPadding, anchor: $anchor) {
              content(data)
            } footer: {
              VStack(spacing: 0) {
                Divider()
                  .withoutAnimation()
                footer(data)
              }
            }
          } else {
            CustomContentView(scrollable: scrollable, fitContent: fitContent, padding: contentPadding, anchor: $anchor) {
              content(data)
            }
          }
        }
      }
    }
    .frame(maxWidth: .infinity, maxHeight: fitContent ? nil : .infinity)
    .background(backgroundColor)
  }
}

CustomContentView

struct CustomContentView<Content: View, Footer: View>: View {
  let content: () -> Content
  let footer: (() -> Footer)?

  var body: some View {
    ZStack {
      if scrollable {
        ScrollViewReader { proxy in
          VStack(alignment: .leading, spacing: 0) {
            ScrollView {
              VStack(alignment: .leading, spacing: 0) {
                Color.clear.frame(width: 0, height: 0)
                  .id(CustomAnchor.topAnchorIdentifier)
                content()
                  .accessibilityIdentifier("CustomContent")
                Color.clear.frame(width: 0, height: 0)
                  .id(CustomAnchor.bottomAnchorIdentifier)
              }
              .padding(padding)
              .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
            }
            footer?()
          }
          .task(id: anchor) {
            await scrollTo(anchor: anchor, using: proxy)
          }
        }
        .scrollDismissesKeyboard(.interactively)
      } else {
        VStack(alignment: .leading, spacing: 0) {
          VStack(alignment: .leading, spacing: 0) {
            Color.clear.frame(width: 0, height: 0)
              .id(CustomAnchor.topAnchorIdentifier)
            content()
              .accessibilityIdentifier("CustomContent")
            Color.clear.frame(width: 0, height: 0)
              .id(CustomAnchor.bottomAnchorIdentifier)
          }
          .padding(padding)
          .frame(maxHeight: fitContent ? nil : .infinity, alignment: .top)
          footer?()
        }
        .frame(maxWidth: .infinity, maxHeight: fitContent ? nil : .infinity, alignment: .top)
      }
    }
  }
}

And when trying to use sut.inspect().find(ViewType.VStack.self) I get results but without nested content inside the CustomView. Even when using a find with accessibilityId or anything.
Is there a way to do so?

@nalexn nalexn added the help wanted Extra attention is needed label Nov 24, 2024
@nalexn
Copy link
Owner

nalexn commented Nov 24, 2024

Hey, could you try to provide a shorter code example, these are hard to troubleshoot as is

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants