in layout-inspector/testSrc/com/android/tools/idea/layoutinspector/pipeline/appinspection/AppInspectionPropertiesProviderTest.kt [433:625]
fun canQueryParametersForComposables() {
inspectorClientSettings.inLiveMode =
true // Enable live mode, so we only fetch properties on demand
val modelUpdatedLatch =
ReportingCountDownLatch(2) // We'll get two tree layout events on start fetch
inspectorRule.inspectorModel.addModificationListener { _, _, _ ->
modelUpdatedLatch.countDown()
}
inspectorRule.processNotifier.fireConnected(MODERN_PROCESS)
modelUpdatedLatch.await(TIMEOUT, TIMEOUT_UNIT)
val provider = inspectorRule.inspectorClient.provider
val resultQueue = ArrayBlockingQueue<ProviderResult>(1)
provider.addResultListener { _, view, table ->
resultQueue.add(
ProviderResult(view, table, inspectorRule.inspectorModel, inspectorRule.parametersCache)
)
}
inspectorRule.inspectorModel[-2]!!.let { targetNode ->
provider.requestProperties(targetNode).get()
val result = resultQueue.poll(TIMEOUT, TIMEOUT_UNIT)!!
assertThat(result.view).isSameAs(targetNode)
result.table.run {
assertParameter("text", PropertyType.STRING, "placeholder")
assertParameter("clickable", PropertyType.BOOLEAN, "true")
assertParameter("count", PropertyType.INT32, "7", PropertySection.RECOMPOSITIONS)
assertParameter("skips", PropertyType.INT32, "14", PropertySection.RECOMPOSITIONS)
}
}
inspectorRule.inspectorModel[-3]!!.let { targetNode ->
provider.requestProperties(targetNode).get()
val result = resultQueue.poll(TIMEOUT, TIMEOUT_UNIT)!!
assertThat(result.view).isSameAs(targetNode)
result.table.run {
assertParameter("maxLines", PropertyType.INT32, "16")
assertParameter("color", PropertyType.COLOR, "#3700B3")
}
}
inspectorRule.inspectorModel[-4]!!.let { targetNode ->
provider.requestProperties(targetNode).get()
val result = resultQueue.poll(TIMEOUT, TIMEOUT_UNIT)!!
assertThat(result.view).isSameAs(targetNode)
result.table.run {
PropertiesSettings.dimensionUnits = DimensionUnits.PIXELS
assertParameter("elevation", PropertyType.DIMENSION_DP, "1.5px")
assertParameter("fontSize", PropertyType.DIMENSION_SP, "36.0px")
assertParameter("textSize", PropertyType.DIMENSION_EM, "2.0em")
}
result.table.run {
PropertiesSettings.dimensionUnits = DimensionUnits.DP
assertParameter("elevation", PropertyType.DIMENSION_DP, "1.0dp")
assertParameter("fontSize", PropertyType.DIMENSION_SP, "16.0sp")
assertParameter("textSize", PropertyType.DIMENSION_EM, "2.0em")
}
}
val parameter =
inspectorRule.inspectorModel[-5]!!.let { targetNode ->
provider.requestProperties(targetNode).get()
val result = resultQueue.poll(TIMEOUT, TIMEOUT_UNIT)!!
assertThat(result.view).isSameAs(targetNode)
result.table.run {
assertParameter("onTextLayout", PropertyType.LAMBDA, "λ")
assertParameter("dataObject", PropertyType.STRING, "PojoClass")
val groupItem = this[PARAM_NS, "dataObject"] as ParameterGroupItem
assertParameter(
groupItem.children[0],
"stringProperty",
PropertyType.STRING,
"stringValue",
)
assertParameter(groupItem.children[1], "intProperty", PropertyType.INT32, "812")
assertParameter(groupItem.children[2], "lines", PropertyType.STRING, "MyLineClass")
assertThat(groupItem.children.size).isEqualTo(3)
groupItem
}
}
// The 1st element of parameter is a reference to parameter itself.
// When the 1st sub element is expanded in the UI the child elements should be copied from
// parameter.
val propertyExpandedLatch = ReportingCountDownLatch(1)
propertyExpandedLatch.runInEdt {
val first = parameter.children.first() as ParameterGroupItem
assertThat(first.children).isEmpty()
first.expandWhenPossible { restructured ->
assertThat(restructured).isTrue()
assertParameter(first.children[0], "stringProperty", PropertyType.STRING, "stringValue")
assertParameter(first.children[1], "intProperty", PropertyType.INT32, "812")
assertParameter(first.children[2], "lines", PropertyType.STRING, "MyLineClass")
assertThat(first.children.size).isEqualTo(3)
propertyExpandedLatch.countDown()
}
}
propertyExpandedLatch.await(TIMEOUT, TIMEOUT_UNIT)
// The last element of parameter is a reference to a value that has not been loaded from the
// agent yet.
// When the last element is expanded in the UI the child elements will be loaded from the agent.
val propertyDownloadedLatch = ReportingCountDownLatch(1)
val last = parameter.children.last() as ParameterGroupItem
propertyDownloadedLatch.runInEdt {
assertThat(last.children).isEmpty()
last.expandWhenPossible { restructured ->
assertThat(restructured).isTrue()
assertParameter(last.children[0], "firstLine", PropertyType.STRING, "Hello World")
assertParameter(last.children[1], "lastLine", PropertyType.STRING, "End of Text")
assertParameter(last.children[2], "list", PropertyType.ITERABLE, "List[12]")
assertThat(last.children.size).isEqualTo(3)
val list = last.children.last() as ParameterGroupItem
assertParameter(list.children[0], "[0]", PropertyType.STRING, "a")
assertParameter(list.children[1], "[3]", PropertyType.STRING, "b")
assertThat(list.children[2]).isInstanceOf(ShowMoreElementsItem::class.java)
assertThat(list.children[2].index).isEqualTo(4)
assertThat(list.children.size).isEqualTo(3)
propertyDownloadedLatch.countDown()
}
}
propertyDownloadedLatch.await(TIMEOUT, TIMEOUT_UNIT)
// The list parameter from the expanded parameter is a List of String where only a part of the
// elements
// have been downloaded. Download some more elements (first time).
val moreListElements1 = ReportingCountDownLatch(1)
val table1 = spy(PTable.create(mock()))
val event1: AnActionEvent = mock()
doAnswer {
val modification = it.getArgument<PTableGroupModification>(1)
assertThat(modification.added).hasSize(2)
assertThat(modification.removed).isEmpty()
moreListElements1.countDown()
}
.whenever(table1)
.updateGroupItems(any(), any())
doAnswer { table1.component }
.whenever(event1)
.getData(Mockito.eq(PlatformCoreDataKeys.CONTEXT_COMPONENT))
val list = last.children.last() as ParameterGroupItem
moreListElements1.runInEdt {
val showMoreItem = list.children[2] as ShowMoreElementsItem
// Click the "Show more" link:
showMoreItem.link.actionPerformed(event1)
}
moreListElements1.await(TIMEOUT, TIMEOUT_UNIT)
assertParameter(list, "list", PropertyType.ITERABLE, "List[12]")
assertThat(list.reference).isNotNull()
assertParameter(list.children[0], "[0]", PropertyType.STRING, "a")
assertParameter(list.children[1], "[3]", PropertyType.STRING, "b")
assertParameter(list.children[2], "[4]", PropertyType.STRING, "c")
assertParameter(list.children[3], "[6]", PropertyType.STRING, "d")
assertThat(list.children[4]).isInstanceOf(ShowMoreElementsItem::class.java)
assertThat(list.children[4].index).isEqualTo(7)
assertThat(list.children.size).isEqualTo(5)
// Expand the list a second time:
val moreListElements2 = ReportingCountDownLatch(1)
val table2 = spy(PTable.create(mock()))
val event2: AnActionEvent = mock()
doAnswer {
val modification = it.getArgument<PTableGroupModification>(1)
assertThat(modification.added).hasSize(3)
assertThat(modification.removed).hasSize(1)
moreListElements2.countDown()
}
.whenever(table2)
.updateGroupItems(any(), any())
doAnswer { table2.component }
.whenever(event2)
.getData(Mockito.eq(PlatformCoreDataKeys.CONTEXT_COMPONENT))
moreListElements2.runInEdt {
val showMoreItem = list.children[4] as ShowMoreElementsItem
// Click the "Show more" link:
showMoreItem.link.actionPerformed(event2)
}
moreListElements2.await(TIMEOUT, TIMEOUT_UNIT)
assertParameter(list, "list", PropertyType.ITERABLE, "List[12]")
assertThat(list.reference).isNull()
assertParameter(list.children[0], "[0]", PropertyType.STRING, "a")
assertParameter(list.children[1], "[3]", PropertyType.STRING, "b")
assertParameter(list.children[2], "[4]", PropertyType.STRING, "c")
assertParameter(list.children[3], "[6]", PropertyType.STRING, "d")
assertParameter(list.children[4], "[7]", PropertyType.STRING, "e")
assertParameter(list.children[5], "[10]", PropertyType.STRING, "f")
assertParameter(list.children[6], "[11]", PropertyType.STRING, "g")
assertThat(list.children.size).isEqualTo(7)
}