Unit Test ZK Spreadsheet Using ZATS
Sam Chuang, Engineer, Potix Corporation
August 22, 2012
ZATS Mimic 1.0.0, ZK Spreadsheet 2.3.0
Introduction
ZK Spreadsheet is a mega component containing toolbar, context menu etc bringing Excel functionality within Java based Ajax web applications using pure Java. Using browser automation frameworks to unit test ZK Spreadsheet could be a time-consuming task. Luckily, ZK has ZATS to offer! ZATS enables developers to test their composer without an application server and without a browser saving huge amounts of time and a developer's nightmare. However, ZATS does not provide a agent that perform ZK Spreadsheet action. Thus, we need to provide a SpreadsheetAgent that would help send commands to spreadsheet.
Fore more information on ZATS, please see [1] & [2]
Test Case Scenario
Let's start by consider two test cases that targeting ZK Spreadsheet App
Scenario 1
- User input "1" in cell A1
- Input "2" in cell B1
- Input "=A1+B1" in cell C3
Scenario 2
- User right click on a cell, then ZK Spreadsheet App open a context menu.
- Click "Format Number" menuitem.
- ZK Spreadsheet App then popup a "Number Format" dialog
Prepare SpreadsheetAgent API
We can use ClientCtrl.postUpdate to send command to ZK Spreadsheet. To observe the command name and arguments need to send to ZK Spreadsheet, we can use Firebug's Console Tab. (For Firebug usage, please refer to here.)
ZK Spreadsheet First Load
When browser first load a page contains ZK Spreadsheet, it will send "onZSSSyncBlock" command. This command is used for sync the client side information with server.
Note that ZATS is designed for test controller layer data and logic, thus we cannot get client side information through ZATS. However, we can still mimic this behavior by send fake data to server.
private void syncBlock() {
//Note. "fake" client data. For example, client panel height
String desktopId = spreadsheet.getDesktop().getId();
Map<String, Object> syncBlockData = new HashMap<String, Object>();
syncBlockData.put("sheetId", spreadsheet.getUuid());
syncBlockData.put("dpWidth", 640); //pixel value of data panel width
syncBlockData.put("dpHeight", 380); //pixel value of data panel height
syncBlockData.put("viewWidth", 800);
syncBlockData.put("viewHeight", 500);
syncBlockData.put("blockLeft", 0);
syncBlockData.put("blockTop", 0);
syncBlockData.put("blockRight", 9);
syncBlockData.put("blockBottom", 19);
syncBlockData.put("fetchLeft", -1);
syncBlockData.put("fetchTop", -1);
syncBlockData.put("fetchWidth", -1);
syncBlockData.put("fetchHeight", -1);
syncBlockData.put("rangeLeft", 0);
syncBlockData.put("rangeTop", 0);
syncBlockData.put("rangeRight", 9);
syncBlockData.put("rangeBottom", 19);
((ClientCtrl)getClient()).postUpdate(desktopId, "onZSSSyncBlock", spreadsheet.getUuid(), syncBlockData, null);
}
Edit Cell
When we input "3" in to cell A1, ZK client engine sent "onStopEditing" command to server.
API that simulate user edit text on a cell
public void setEditText(int row, int col, String editValue) {
String desktopId = spreadsheet.getDesktop().getId();
Map<String, Object> stopEditingData = new HashMap<String, Object>();
stopEditingData.put("token", "0");
stopEditingData.put("sheetId", "0");//always assume editing on the first sheet
stopEditingData.put("row", row);
stopEditingData.put("col", col);
stopEditingData.put("value", editValue);
stopEditingData.put("type", "inlineEditing");
((ClientCtrl)getClient()).postUpdate(desktopId, "onStopEditing", spreadsheet.getUuid(), stopEditingData, null);
}
Click Context Menu Item
- Right click on a cell
Note. when use focus on a cell and right click, ZK client engine doesn't send any command to server. Means open context menu is done from client side. No need to send command to server.
- Click "Format Number" Menuitem
When we click the menuitem, ZK client engine send "onZSSAction" to server.
API that simulate click on context menu item
public void postActionCommand(int tRow, int lCol, int bRow, int rCol, String action) {
final String desktopId = spreadsheet.getDesktop().getId();
Map<String, Object> args = new HashMap<String, Object>();
args.put("sheetId", "0");
args.put("tag", "toolbar");
args.put("act", action);
args.put("tRow", tRow);
args.put("lCol", lCol);
args.put("bRow", bRow);
args.put("rCol", rCol);
((ClientCtrl)getClient()).postUpdate(desktopId, "onZSSAction", spreadsheet.getUuid(), args, null);
}
SpreadsheetAgentBuilder
Create a SpreadsheetAgentBuilder that used to create SpreadsheetAgent instance.
public class SpreadsheetAgentBuilder implements OperationAgentBuilder<ComponentAgent, SpreadsheetAgent> {
public class SpreadsheetAgent extends AgentDelegator<ComponentAgent> implements OperationAgent {
private Spreadsheet spreadsheet;
public static final String ACTION_FORMAT_CELL = "formatCell";
public SpreadsheetAgent(ComponentAgent target) {
super(target);
spreadsheet = (Spreadsheet)target.getDelegatee();
syncBlock();//sent sync block command to spreadsheet (fake data)
}
public Spreadsheet getSpreadsheet() {
return spreadsheet;
}
//omit...
}
public SpreadsheetAgent getOperation(ComponentAgent agent) {
return new SpreadsheetAgent(agent);
}
public Class<SpreadsheetAgent> getOperationClass() {
return SpreadsheetAgent.class;
}
}
See the full source code of SpreadsheetAgentBuilder.java
Writing Test Cases
Init ZATS
Register SpreadsheetAgentBuilder, allow us to get SpreadsheetAgent instance.
@BeforeClass
public static void init() {
Zats.init("./src/main/webapp");
OperationAgentManager manager = OperationAgentManager.getInstance();
manager.registerBuilder("5.0.0", "*", Spreadsheet.class, new SpreadsheetAgentBuilder());
}
Test Case 1
- User input "1" in cell A1
- Input "2" in cell B1
- Input "=A1+B1" in cell C3
@Test
public void editFormulaTest() {
DesktopAgent desktop = Zats.newClient().connect("/index.zul");
SpreadsheetAgent spreadsheetAgent = desktop.query("spreadsheet").as(SpreadsheetAgent.class);//get SpreadsheetAgent
spreadsheetAgent.setEditText(0, 0, "1");//input "1" in A1
spreadsheetAgent.setEditText(0, 1, "2");//input "2" in B1
spreadsheetAgent.setEditText(0, 2, "=A1+B1");//input formula in C1
Spreadsheet spreadsheet = spreadsheetAgent.getSpreadsheet();
Row row = spreadsheet.getSelectedSheet().getRow(0);
Cell cell = row.getCell(2);
Assert.assertEquals(Cell.CELL_TYPE_FORMULA, cell.getCellType());
Assert.assertEquals(Cell.CELL_TYPE_NUMERIC, cell.getCachedFormulaResultType());
Assert.assertEquals(Double.valueOf(3), cell.getNumericCellValue());
}
Test Case 2
- User right click on a cell, then ZK Spreadsheet open a context menu.
- Click "Format Number" menuitem.
@Test
public void openFormatNumberDialogTest() {
DesktopAgent desktop = Zats.newClient().connect("/index.zul");
SpreadsheetAgent spreadsheetAgent = desktop.query("spreadsheet").as(SpreadsheetAgent.class);
spreadsheetAgent.postActionCommand(6, 8, SpreadsheetAgent.ACTION_FORMAT_CELL);
ComponentAgent windowAgent = desktop.query("window[title='Number Format']");
Assert.assertNotNull(windowAgent);
Window win = (Window) windowAgent.getDelegatee();
Assert.assertEquals(true, win.isVisible());
Assert.assertEquals("modal", win.getMode());
Assert.assertEquals("Number Format", win.getTitle());
}
See the full source code of SpreadsheetTest.java
Summary
ZATS can be used to write unit test for any ZK component, include custom component. Unlike traditional web browser testing framework, without interfere with browser make the unit test easy to develop and minimize the time for testing.
Download
The whole example code can be downloaded here - Github
References
Comments
Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License. |