false bool values not taken into account while laying out views
buppal opened this issue · 19 comments
LYTBoolValues()
adds both true
and false
. But the views in the test are rendered for only true
values. The test does not render any views for false
values.
I can't reproduce this locally. When I run the SampleAppTests it uses BoolValues:
public class func dataSpecForTest() -> [NSObject: AnyObject] {
return [
"text": LYTStringValues(),
"buttonText": LYTStringValues(),
"buttonEnabled": LYTBoolValues(),
"imageType": LYTDataValues(values: ["linkedin", "garbageString", NSNull()])
]
}
If I put a break point on line 40 and po data["buttonEnabled"]
, eventually (after a few tries) I see:
▿ Optional<AnyObject>
- Some : 1
▿ Optional<AnyObject>
- Some : 0
It does return true multiple times in a row before moving to false though. Can you send me some sample code that reproduces the issue?
Yes, that prints fine in the debugger, even for me. I see true/false being printed alternatively. But the view is not rendered according to the false value. If you have a button and label, and you set the button to hidden according to the bool value, it won't get hidden.
It looks like the Sample App manages to test this:
XCTAssertEqual(view.rightButton.enabled, data["buttonEnabled"] as? Bool ?? false)
The tests pass indicating that the button is correctly enabled/disabled.
What does your viewForData
method look like?
That's interesting. I have attached my view and ViewTests. If you see in the code I am sending you, the info button should be visible half of the times, and not visible for the other half. Let me know if there is anything needed regarding the code I just sent you.
So to be clear, this line gets called:
infoButton.hidden = !viewModel.shouldShowPriceBreakdown
and viewModel.shouldShowPriceBreakdown
is sometimes true
and sometimes false
.
But, when you inspect the value of hidden, it's always false?
Yes. To put it in a more clear way, viewModel.shouldShowPriceBreakdown is sometimes true
and sometimes false
. But in the index.html, the view always shows. It should show/not show according to this bool, and that does not seem to work.
so, the index.html only shows views which have errors. Perhaps you are only failing the test when this view is being shown? For instance, if a view is overlapping this view, it will only fail when this view is not hidden.
Oh no. I purposely put an XCTFail() to assert and see the views.
To debug this, you could try putting XCTFail()
in the block for your test. This will cause every view to fail and you'll see all views in the index.html
.
Ah, yeah...looks like you did this. When you query the view for infoButton.hidden
it gives you the right answer correct?
yes.
So, the bug here is that the screenshot logic seems to not be working. Let me see if I can repro.
Yes right. May be it is hardcoded to true somewhere while laying out the views in the html. That's what I can guess, but not sure.
Meh...no dice again.
Changed the sample app to be:
func setup(json: [NSObject: AnyObject]) {
label.text = json["text"] as? String
button.setTitle(json["buttonText"] as? String, forState: .Normal)
label.hidden = true
}
So the label is always hidden. When I run tests, I see all the views printed out (I added an XCTFail()
) but the view is hidden.
Could you try in your tests something like adding the current view to the window and see how it renders?
Ah that's interesting. I think may be we are calling the action infoButtonTapped()
. This function in turn toggles the visibility of the info button. May be this is kind of dynamic and is not taken into account while rendering them in the html? Thoughts?
static func viewForData(data: [NSObject: AnyObject], reuseView: UIView?,
size: LYTViewSize?, context: AutoreleasingUnsafeMutablePointer<AnyObject?>) -> UIView {
let view = BundleSavingsAndTotalView(viewModel: FakeBundleSavingsAndTotalViewModel(data: data))
let shouldShowPriceBreakdown = data["shouldShowPriceBreakdown"] as! Bool
if shouldShowPriceBreakdown {
view.infoButtonTapped()
}
return view
}
}
private func updatePriceBreakdownView(isVisible isVisible: Bool, animated: Bool) {
if animated {
UIView.animateWithDuration(animationDuration) {
self.bundlePriceBreakdownView.hidden = !isVisible
}
} else {
bundlePriceBreakdownView.hidden = !isVisible
}
infoButton.hidden = isVisible
}
Well, when you call animateWithDuration
, it actually changes the .hidden
value immediately. Only the layer value will change.
Currently, layout tests aren't setup up to do interactions well because they run synchronously. You could do this with waits, but probably not a great solution because of how slow they will run.
Oh ok, so you mean the data layer property will change, but the LayoutTest library wont take that into account?
Probably I will write a UIViewController test for interactions and test only layout with UILayoutTests.
Closing this issue, got why that was happening, probably expected behavior. Thanks for the help!