NativePlugins API update

Summary:
The main change is is changing from the inheritance model:
`FlipperPlugin > NativePlugin > TablePlugin > ConcretePlugin`

to a composition model where:
`NativePlugin > TablePlugin > ConcretePlugin`

And behind the scenes, there's a `FlipperPlugin` that has a `NativePlugin` reference.

Now your native plugin will call methods like (in the table case) `display.updateRows` instead of `super.updateRows()`

The reasons for this are:

* Testability: we can easily mock the display and assert output.
* Encapsulation: Previously, native plugins could call `mConnection.send(...)` and send completely unsupported messages to the desktop. Now they only have access to the display's public api, which is guaranteed to work.

I've also changed it so that on every row update, we send the latest table metadata along with it. This makes sure we can ensure that the right table schema is displayed for the current data.

QueryResponder interface also added, which will come in useful for queryable datasets.

Reviewed By: passy

Differential Revision: D14751885

fbshipit-source-id: ea0bbd25f7eaa60020f8866fe210d8bd1c22e90b
This commit is contained in:
John Knox
2019-04-05 10:01:40 -07:00
committed by Facebook Github Bot
parent 703f43a903
commit fa3dcdc5dd
14 changed files with 394 additions and 186 deletions

View File

@@ -0,0 +1,14 @@
package com.facebook.flipper.nativeplugins.table;
public class MockTablePlugin extends TablePlugin {
@Override
public TableMetadata getMetadata() {
return new TableMetadata.Builder().columns().build();
}
@Override
public String getTitle() {
return "Mock Table Plugin";
}
}

View File

@@ -0,0 +1,10 @@
package com.facebook.flipper.nativeplugins.table;
import com.facebook.flipper.nativeplugins.components.Sidebar;
import java.util.Map;
public class MockTableRow extends TableRow {
public MockTableRow(String id, Map<Column, ? extends Value> values, Sidebar sidebar) {
super(id, values, sidebar);
}
}

View File

@@ -0,0 +1,12 @@
package com.facebook.flipper.nativeplugins.table;
public class TableMetadataTestUtils {
public static Column[] getColumns(TableMetadata tableMetadata) {
return tableMetadata.mColumns;
}
public static QueryableTableRowProvider getQueryResponder(TableMetadata tableMetadata) {
return tableMetadata.responder;
}
}

View File

@@ -0,0 +1,91 @@
package com.facebook.flipper.nativeplugins.table;
import static org.junit.Assert.assertEquals;
import com.facebook.flipper.core.FlipperArray;
import com.facebook.flipper.core.FlipperObject;
import com.facebook.flipper.nativeplugins.components.Sidebar;
import com.facebook.flipper.testing.FlipperConnectionMock;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
public class TableRowDisplayImplTest {
FlipperConnectionMock mConnection;
MockTablePlugin mockTablePlugin;
static final Column NAME_COLUMN =
new Column.Builder("name")
.displayName("Name")
.displayWidthPercent(90)
.isFilterable(true)
.showByDefault(false)
.build();
static final Column AGE_COLUMN =
new Column.Builder("age")
.displayName("Age")
.displayWidthPercent(50)
.isFilterable(false)
.showByDefault(true)
.build();
@Before
public void setup() {
mConnection = new FlipperConnectionMock();
mockTablePlugin = new MockTablePlugin();
}
private TableRow row(String id, String name, int age) {
Map<Column, TableRow.Value> map1 = new HashMap<>();
map1.put(NAME_COLUMN, new TableRow.StringValue(name));
map1.put(AGE_COLUMN, new TableRow.IntValue(age));
return new MockTableRow(id, map1, new Sidebar());
}
@Test
public void testUpdateRow() {
TableRowDisplay display = new TableRowDisplayImpl(mConnection, mockTablePlugin);
display.updateRow(row("row1", "santa", 55), null);
assertEquals(1, mConnection.sent.get("updateRows").size());
FlipperArray rowArray = (FlipperArray) mConnection.sent.get("updateRows").get(0);
assertEquals(1, rowArray.length());
FlipperObject updatedRow = rowArray.getObject(0);
assertEquals(serializedRow("row1", "santa", 55), updatedRow);
}
@Test
public void testUpdateRows() {
TableRowDisplay display = new TableRowDisplayImpl(mConnection, mockTablePlugin);
List<TableRow> rows = new ArrayList<>();
rows.add(row("row1", "santa", 55));
rows.add(row("row2", "elf", 15));
display.updateRows(rows, null);
assertEquals(1, mConnection.sent.get("updateRows").size());
FlipperArray rowArray = (FlipperArray) mConnection.sent.get("updateRows").get(0);
assertEquals(2, rowArray.length());
assertEquals(serializedRow("row1", "santa", 55), rowArray.getObject(0));
assertEquals(serializedRow("row2", "elf", 15), rowArray.getObject(1));
}
private FlipperObject serializedRow(String id, String name, int age) {
return new FlipperObject(
"{\"columns\":{\"name\":{\"type\":\"string\",\"value\":\""
+ name
+ "\"},\"id\":\""
+ id
+ "\",\"age\":{\"type\":\"int\",\"value\":"
+ age
+ "}},\"sidebar\":[],\"id\":\""
+ id
+ "\"}");
}
}