I've started looking at this. The first hurdle is that updates return both a model update and a side effect. So you could not replay side effects as they may not be deterministic. (Replay produces Cmd which returns a different result message from first time. The time traveling debugger gets around this by disabling Cmd when replaying.) Not to mention running Cmds depends on some outside access (at least mocking it).
There is a discussion of that
here and I made a gist of a possible way to implement side effect isolation
here. Look at the comment first to see what it looks like in use.
The other hurdle is events are likely to be union types with data. All the JSON encoding/decoding I've see in Elm for union types are for the simple kind where the case has no other values (like an enum). So having a case with values will be a challenge. In
JSON.NET, serialized F# union type `CaseName ("something", 1, 3.5)` would look like this: `{ "Case": "CaseName", "Fields": ["something", 1, 3.5] }`. Note: case values are tuples in F#. Javascript allows arrays to contain dissimilar types, so this works.
But, making a custom encoder/decoder for every union case makes you want to rethink life choices. Indeed, it might be better to just use Redux-style messages where the type is a string so you can send the events out of a port for free. It's a shame to lose out on that nice union syntax, but man the pain.
Even then, you will still feel the pain on decoding. Actually, decoding anything is painfully manual in Elm. However, there are no surprises that way.