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

Add ability to tag widgets for tests #171

Open
MichaelBelousov opened this issue Dec 22, 2024 · 2 comments
Open

Add ability to tag widgets for tests #171

MichaelBelousov opened this issue Dec 22, 2024 · 2 comments

Comments

@MichaelBelousov
Copy link
Collaborator

MichaelBelousov commented Dec 22, 2024

I have a large UI where I would like to be able to do something like:

test "click user 3" {
  var app = app.init();
  defer app.deinit();
  app.frame();
  
  // imaginary API, probably can use existing event API but might be nice to have a helper
  // here that just assumes a center insertion
  dvui.testing.click(.UserWidget, .{ .id_extra = 2 });
  
  app.frame();
  
  std.testing.expectEqual(app.selected_user_index, 2);
}

Then my app would have code like:

var selected_user_index: ?usize = null;
fn frame() !void {
  var hbox = try dvui.box(.horizontal);
  defer hbox.deinit();
  for (users.items, 0..) |user, i| {
    var user_box = dvui.box(.vertical, .{ .id_extra = i });
    defer user_box.deinit();
    try dvui.label("user {}", .{i}, .{ .id_extra = i, .test_tag = .UserWidget });
  }
}

And the zig enum literal passed to test_tag could be used to have an efficient name that can be used to refer to the widget, with dvui erroring if you duplicate the same test_tag,id_extra pair.

As a separate issue, it would be nice to add a "null backend" to ignore drawing widgets, for
test scenarios, I will add such an issue later, right now I just don't initialize my backend which seems to work ok.

fyi, this is lightly based on the common pattern in webdev of adding data-testid attributes to DOM elements to query them in tests

@david-vanderson
Copy link
Owner

This is a good idea, and having a null testing backend is also a great idea. Could in the future be used to test if widgets are in/out of the clipping region for example.

Will put some thought into how to refer to widgets for testing purposes, how to insert events to match them, and the flow of tests. Need some way to specify longer logical tests like:

  • click button "Show Dialog"
  • maybe wait for dialog to finish animating
  • test if dialog button "ok" is visible (and maybe has focus)
  • click "ok"
  • maybe wait for dialog to animate closed
  • test if dialog is no longer shown

@MichaelBelousov
Copy link
Collaborator Author

MichaelBelousov commented Dec 22, 2024

I would avoid complexity but it might be worth considering if the API gets complex enough to try to follow zig's std.testing:

test "show dialog" {
  var app = App.init();
  defer app.deinit();
  
  try dvui.testing.actions.click(.ShowDialogButton, null);
  try dvui.testing.runUntilNotAnimating(.ShowDialogButton, App.frame, .{app});
  try dvui.testing.expectVisible(.DialogOk, null);
  try dvui.testing.expectFocused(.DialogOk, null);
  
  try dvui.testing.actions.click(.DialogOk, null);
  try dvui.testing.runUntilNotAnimating(null, App.frame, .{app});
  try dvui.testing.expectNotVisible(.Dialog, null);
}

Writing it out, I'm not sure if I'm a big fan of that kind of API, I might prefer

std.testing.expectEqual(dvui.testing.get(.DialogOk).focus_state, .focused);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants