@embedFile() works like @import() in that you can embed both by file path and module import name, so if you want to use @embedFile() you could do something like this in your build.zig:
However, note that this will quickly cause your .zig-cache to balloon in size because each new emulator binary you build will contain a whole copy of the wasm binary. So I think locating the wasm binary at runtime is the overall better approach.
It’s hard to know when you’ve only shared a snippet of your build script, but I suspect that the problem is that your test exe doesn’t depend on any step that installs the wasm binary to zig-out/bin/app.wasm. You need to have run_exe_tests depend on either b.getInstallStep() or &b.addInstallArtifact(app_exe, .{}).step.
I don’t think hard-coding the emulator to look for zig-out/bin/app.wasm is a good approach. In my opinion more sound solution would be to take the path to the wasm binary as a command-line argument. You can set up your run_exe step to pass app_exe.getEmittedBin() as an argument to the executable.
But, because zig test/b.addTest() uses a test runner which by default completely hijacks the command-line arguement handling (and rejects any arguments it doesn’t understand), in order to use that approach you need to compile the test binary specifying custom test runner which supports arbitrary command-line arguments. Refer to the default test_runner.zig for inspiration.
Don’t have time for the proper reply, but the short, cryptic one is that you should avoid using dependOn as much as possible outside of top-level steps, and instead leverage implicit dependency tracking provided by LazyPaths, e.g.,