| 1 | package cdp |
| 2 | |
| 3 | import ( |
| 4 | "strings" |
| 5 | "testing" |
| 6 | ) |
| 7 | |
| 8 | func TestChordEventsCarryModifiersAndSuppressTextForShortcuts(t *testing.T) { |
| 9 | tests := []struct { |
| 10 | spec string |
| 11 | key string |
| 12 | code string |
| 13 | vk int |
| 14 | modifiers int |
| 15 | downType string |
| 16 | text string |
| 17 | }{ |
| 18 | {"Enter", "Enter", "Enter", 13, 0, "keyDown", "\r"}, |
| 19 | {"Escape", "Escape", "Escape", 27, 0, "rawKeyDown", ""}, |
| 20 | {"Control+a", "a", "KeyA", 65, modCtrl, "rawKeyDown", ""}, |
| 21 | {"Shift+a", "A", "KeyA", 65, modShift, "keyDown", "A"}, |
| 22 | {"Meta+Shift+p", "P", "KeyP", 80, modMeta | modShift, "rawKeyDown", ""}, |
| 23 | {"ArrowDown", "ArrowDown", "ArrowDown", 40, 0, "rawKeyDown", ""}, |
| 24 | {"F5", "F5", "F5", 116, 0, "rawKeyDown", ""}, |
| 25 | } |
| 26 | for _, tc := range tests { |
| 27 | down, up, err := chordEvents(tc.spec) |
| 28 | if err != nil { |
| 29 | t.Fatalf("chordEvents(%q): %v", tc.spec, err) |
| 30 | } |
| 31 | if down["key"] != tc.key || down["code"] != tc.code { |
| 32 | t.Fatalf("chordEvents(%q) key/code = %v/%v, want %v/%v", tc.spec, down["key"], down["code"], tc.key, tc.code) |
| 33 | } |
| 34 | if down["windowsVirtualKeyCode"] != tc.vk || down["modifiers"] != tc.modifiers { |
| 35 | t.Fatalf("chordEvents(%q) vk/modifiers = %v/%v, want %d/%d", tc.spec, down["windowsVirtualKeyCode"], down["modifiers"], tc.vk, tc.modifiers) |
| 36 | } |
| 37 | if down["type"] != tc.downType { |
| 38 | t.Fatalf("chordEvents(%q) type = %v, want %v", tc.spec, down["type"], tc.downType) |
| 39 | } |
| 40 | if text, _ := down["text"].(string); text != tc.text { |
| 41 | t.Fatalf("chordEvents(%q) text = %q, want %q", tc.spec, text, tc.text) |
| 42 | } |
| 43 | if up["type"] != "keyUp" || up["key"] != tc.key { |
| 44 | t.Fatalf("chordEvents(%q) key-up = %v", tc.spec, up) |
| 45 | } |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | func TestChordEventsRejectUnknownNames(t *testing.T) { |
| 50 | for _, spec := range []string{"Hyper+a", "NoSuchKey", "Control+", ""} { |
| 51 | if _, _, err := chordEvents(spec); err == nil { |
| 52 | t.Fatalf("chordEvents(%q) accepted an unusable chord", spec) |
| 53 | } |
| 54 | } |
| 55 | } |
| 56 | |
| 57 | func TestCharEventsTypeOneRune(t *testing.T) { |
| 58 | events := charEvents('x') |
| 59 | if len(events) != 2 { |
| 60 | t.Fatalf("charEvents emitted %d events, want a down and an up", len(events)) |
| 61 | } |
| 62 | if events[0]["text"] != "x" || events[0]["type"] != "keyDown" { |
| 63 | t.Fatalf("key-down = %v, want a keyDown carrying the character", events[0]) |
| 64 | } |
| 65 | if events[0]["windowsVirtualKeyCode"] != int('X') { |
| 66 | t.Fatalf("virtual key code = %v, want the upper-case code", events[0]["windowsVirtualKeyCode"]) |
| 67 | } |
| 68 | if newline := charEvents('\n'); len(newline) != 2 || newline[0]["key"] != "Enter" { |
| 69 | t.Fatalf("a newline must type Enter, got %v", newline) |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | func TestSafeFilenameKeepsDownloadsInTheirDirectory(t *testing.T) { |
| 74 | tests := map[string]string{ |
| 75 | "report.csv": "report.csv", |
| 76 | "../../etc/passwd": "passwd", |
| 77 | `..\..\windows.ini`: "windows.ini", |
| 78 | "a/b/c.txt": "c.txt", |
| 79 | "weird:name?.txt": "weird_name_.txt", |
| 80 | "..": "", |
| 81 | " ": "", |
| 82 | } |
| 83 | for input, want := range tests { |
| 84 | if got := safeFilename(input); got != want { |
| 85 | t.Fatalf("safeFilename(%q) = %q, want %q", input, got, want) |
| 86 | } |
| 87 | } |
| 88 | if got := safeFilename(strings.Repeat("n", 400) + ".txt"); len(got) != 180 { |
| 89 | t.Fatalf("safeFilename truncated to %d characters, want 180", len(got)) |
| 90 | } |
| 91 | } |
| 92 |