3

I am making a Spec for my framework that needs to test a event with shift key. So I would like to insert pragmatically a ! as if I pressed shift + 1.

I have been using the Syn framework but cannot make it simulate a SHIFT + 1. According to the docs it should be

Syn.type('[shift]1[shift-up]', 'textInput2'); 

but this does not work. I would expect a ! character, the event.shiftKey to be true, and event.key to be 33 but I get a 1 instead of ! and a event.key == 49 instead.

How is this possible with Syn, or vanilla javascript?

I made this jsFiddle to test this, check the console.

vbence
  • 20,084
  • 9
  • 69
  • 118
Sergio
  • 28,539
  • 11
  • 85
  • 132
  • If your goal is to test a code (such as unit-test), you should not bother by simulating the environment. Instead, you should be headed to abstractions and stubbing out the environment dependency. Basically, use interfaces that represent environments, not environments directly though. – Tengiz Apr 23 '14 at 20:33
  • @Tengiz, thanks for feedback. Not quite sure I understand what you mean. I am trying to use JS (& later Grunt-Jasmine) as interface to simulate. I would like also to be as abstract as possible but I need to try behaviours on browsers... – Sergio Apr 23 '14 at 20:38

2 Answers2

3

If you look in the Syn Tests here https://github.com/bitovi/syn/blob/c77ae2cbb19ff0a5d3ecd3f9968e15adad289a79/test/qunit/key_test.js

You can see that they simulate a capital 'A' by doing '[shift]A[shift-up]'. Syn simply creates an event and passes and sets the value. It doesn't simulate the lower level keyboard interaction.

 Syn.type('[shift]![shift-up]', 'textInput2');
 // outputs 33 true 

Setting a timeout will make it work, not sure why, but it does: http://jsfiddle.net/2zsNV/5/

Sergio
  • 28,539
  • 11
  • 85
  • 132
startswithaj
  • 344
  • 1
  • 9
  • My console shows me `33 false ` on your fiddle. Which browser are you using? – Sergio Apr 24 '14 at 04:13
  • I'm using chrome. But I went back and tested it and you're correct sometimes it does print 33 false but if you click run a few times it prints 33 false, 33 true, 33 true, 33 false, 33 true. So I went and had a look at the tests here https://github.com/bitovi/syn/blob/c77ae2cbb19ff0a5d3ecd3f9968e15adad289a79/test/qunit/key_test.js#L333 and he's using a settimeout like here http://jsfiddle.net/2zsNV/2/. I'm not sure why this is happening but Ill have a look into it. – startswithaj Apr 24 '14 at 04:31
  • 1
    http://jsfiddle.net/2zsNV/5/. I'm not sure what the problem but seems by defering it to the next event cycle makes it work – startswithaj Apr 24 '14 at 04:47
2

OK, you're correct Syn doesn't do that correctly, and I can guess why -- the browser can't tell your keyboard layout (see here: detect keyboard layout with javascript) so it really can't tell what you should get for Shift+1, so it just gives you a '1'.

You would assume that

Syn.type('[shift]![shift-up]', 'textInput2'); 

Would work as expected but that doesn't either ... I think that's a bug in Syn.

So, can you do it in raw JavaScript? I can get close.

Apparently it's pretty hard to get it working cross-browser and this led me down a rabbit-hole of trying different things. First I looked at this question: Is it possible to simulate key press events programmatically? but that didn't work correctly in chrome, then I tried various combinations of events and values based on their documentation without much more success. Then I found this question: Firing a keyboard event on Chrome which led me to this code.

Pasting that code into the JS and then calling it with:

var e = crossBrowser_initKeyboardEvent("keypress", {"key": 1, "char": "!", shiftKey: true})
document.getElementById('textInput2').dispatchEvent(e);

Will give the output you expect. However, it doesn't actually write the value into the input box. Of course you could fake that and just add the text there as well, I'm not sure if that's a limitation in the way events work or if there's just something wrong with the code. Of course, for test, that might be all you need.

Here's the fiddle, maybe someone else can make the final jump.

Community
  • 1
  • 1
SpaceDog
  • 3,249
  • 1
  • 17
  • 25