pthom / imgui_bundle

Dear ImGui Bundle: an extensive set of Ready-to-use widgets and libraries, based on ImGui. Start your first app in 5 lines of code, or less. Whether you prefer Python or C++, this pack has your back!
https://pthom.github.io/imgui_bundle/
MIT License
590 stars 62 forks source link

Simulate key presses with the test engine #200

Closed csuckow closed 2 months ago

csuckow commented 2 months ago

Hey there! I was trying to implement some tests for my shortcuts (which were created using imgui.get_io().key_...), however I was not able to find a way to simulate the actual button presses. Probably just missing something obvious here ...

To make a minimal example, I have tried to extend the test engine sample with the following test:

    # Demo 4: Write to text field
    test_write = imgui.test_engine.register_test(engine, "Demo Tests", "Write to text field")
    def test_write_func(ctx: imgui.test_engine.TestContext) -> None:
        ctx.set_ref("Dear ImGui Demo")
        ctx.item_open("**/Widgets")
        ctx.item_open("**/Text Input")
        ctx.item_open("**/Multi-line Text Input")
        ctx.item_click("**/##source")
        ctx.key_press(int(imgui.Key.h))   # doesn't work
        # ctx.key_press(glfw.KEY_H)       # crashes
    test_write.test_func = test_write_func

Many thanks!

pthom commented 2 months ago

Hello, I updated your example and added to the demo.

https://github.com/pthom/imgui_bundle/blob/6b430fcfeb61cdebd7a7302b88bb9780bc7c9747/bindings/imgui_bundle/demos_python/demos_immapp/demo_testengine.py#L99-L110

Basically the answer is that ctx.key_up/down/key_press sends events that you can process in the GUI However, you need to use key_chars to input text in the text widgets.

csuckow commented 2 months ago

Thanks for the quick response! I have some keyboard shortcuts in my ui which are activated via the io functions (e.g. if imgui.get_io().key_alt: (...)). How would I test those functions? For some reason, they do not seem to fire when using ctx.key_press.

pthom commented 2 months ago
from imgui_bundle import imgui, hello_imgui, immapp

def my_register_tests():
    engine = hello_imgui.get_imgui_test_engine()

    test_inc = imgui.test_engine.register_test(engine, "Demo Tests", "Increment")
    def test_inc_func(ctx: imgui.test_engine.TestContext) -> None:
        ctx.item_click("**/Increment")
    test_inc.test_func = test_inc_func

    test_inc = imgui.test_engine.register_test(engine, "Demo Tests", "Press keys")
    def test_inc_func(ctx: imgui.test_engine.TestContext) -> None:
        ctx.key_down(imgui.Key.left_alt.value)
        ctx.key_down(imgui.Key.a.value)
        ctx.key_up(imgui.Key.a.value)
        ctx.key_up(imgui.Key.left_alt.value)
    test_inc.test_func = test_inc_func

count = 0
nb_alt_a = 0

def gui():
    global count, nb_alt_a

    imgui.text("Hello, world!")
    if imgui.button("Increment"):
        count += 1
    imgui.text("count = %d" % count)

    if imgui.is_key_down(imgui.Key.left_alt) and imgui.is_key_down(imgui.Key.a):
        nb_alt_a += 1

    imgui.text(f"nb_alt_a = {nb_alt_a}")

    imgui.show_id_stack_tool_window()
    imgui.test_engine.show_test_engine_windows(
        hello_imgui.get_imgui_test_engine(), None
    )

def main():
    params = hello_imgui.RunnerParams()
    params.callbacks.show_gui = gui
    params. callbacks.register_tests = my_register_tests
    params.use_imgui_test_engine = True

    hello_imgui.run(params)

if __name__ == "__main__":
    main()
csuckow commented 2 months ago

Thanks a lot for the example, this helped me a lot! My code was missing the .value after imgui.Key.left_alt.

Moreover, the test does not work when changing if imgui.is_key_down(imgui.Key.left_alt) (...) to if imgui.get_io().key_alt (...):, which is what I was using before. However, changing to is_key_down was no problem as it seems to fire at the same times.