turbo-editors/turbo-corepublic Fork 0
v0.9.0
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-core.git
git clone ssh://git@rickub.com/turbo-editors/turbo-core.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

javascript_test.go · 118 lines · 4.2 KBGo Blame HistoryRaw
🛟 Updated. 28d5985 k33g 19h ago1package syntax
2
3import "testing"
4
5// wantJS is wantLine for JavaScript.
6func wantJS(t *testing.T, src string, line int, want ...string) {
7 t.Helper()
8 wantLine(t, LanguageJavaScript, src, line, want...)
9}
10
11func TestJavaScriptColoursKeywords(t *testing.T) {
12 wantJS(t, "const x = 1", 0,
13 "const:keyword", "x:identifier", "=:operator", "1:number")
14 wantJS(t, "async function f() {}", 0,
15 "async:keyword", "function:keyword", "f:function",
16 "(:punctuation", "):punctuation", "{:punctuation", "}:punctuation")
17}
18
19func TestJavaScriptColoursConstantsAndGlobals(t *testing.T) {
20 wantJS(t, "x = true", 0, "x:identifier", "=:operator", "true:constant")
21 wantJS(t, "x = null", 0, "x:identifier", "=:operator", "null:constant")
22 wantJS(t, "console.log(1)", 0,
23 "console:builtin", ".:punctuation", "log:function",
24 "(:punctuation", "1:number", "):punctuation")
25}
26
27func TestANameBeforeAParenthesisIsACall(t *testing.T) {
28 wantJS(t, "doThing()", 0, "doThing:function", "(:punctuation", "):punctuation")
29 wantJS(t, "doThing", 0, "doThing:identifier")
30}
31
32func TestJavaScriptColoursStrings(t *testing.T) {
33 wantJS(t, `x = "double"`, 0, "x:identifier", "=:operator", `"double":string`)
34 wantJS(t, "x = 'single'", 0, "x:identifier", "=:operator", "'single':string")
35}
36
37func TestAnEscapedQuoteDoesNotEndAJavaScriptString(t *testing.T) {
38 wantJS(t, `x = "he said \"no\""`, 0, "x:identifier", "=:operator", `"he said \"no\"":string`)
39}
40
41func TestAnUnterminatedJavaScriptStringIsColouredToTheEndOfTheLine(t *testing.T) {
42 wantJS(t, `x = "half written`, 0, "x:identifier", "=:operator", `"half written:string`)
43}
44
45func TestJavaScriptColoursLineAndBlockComments(t *testing.T) {
46 wantJS(t, "x = 1 // a note", 0,
47 "x:identifier", "=:operator", "1:number", "// a note:comment")
48 wantJS(t, "x = /* inline */ 1", 0,
49 "x:identifier", "=:operator", "/* inline */:comment", "1:number")
50}
51
52func TestABlockCommentCarriesAcrossLines(t *testing.T) {
53 src := "/* first\n second\n third */ x = 1"
54
55 wantJS(t, src, 0, "/* first:comment")
56 wantJS(t, src, 1, " second:comment")
57 wantJS(t, src, 2, " third */:comment", "x:identifier", "=:operator", "1:number")
58}
59
60func TestCodeInsideABlockCommentIsNotColoured(t *testing.T) {
61 src := "/*\nconst x = 1\n*/"
62
63 wantJS(t, src, 1, "const x = 1:comment")
64}
65
66func TestJavaScriptColoursTemplateLiterals(t *testing.T) {
67 wantJS(t, "x = `plain`", 0, "x:identifier", "=:operator", "`plain`:string")
68 wantJS(t, "x = `a ${b} c`", 0, "x:identifier", "=:operator", "`a ${b} c`:string")
69}
70
71func TestATemplateLiteralCarriesAcrossLines(t *testing.T) {
72 src := "const html = `\n <p>hi</p>\n`\nconst x = 1"
73
74 wantJS(t, src, 1, " <p>hi</p>:string")
75 wantJS(t, src, 2, "`:string")
76 // The line after it is code again.
77 wantJS(t, src, 3, "const:keyword", "x:identifier", "=:operator", "1:number")
78}
79
80func TestJavaScriptColoursNumbers(t *testing.T) {
81 for _, value := range []string{"42", "3.14", "0x1f", "0b1010", "0o777", "1_000_000", "1e6", "10n"} {
82 t.Run(value, func(t *testing.T) {
83 got := spansOf(t, LanguageJavaScript, "x = "+value, 0)
84 if last := got[len(got)-1]; last != value+":number" {
85 t.Errorf("%q was coloured %q, want a number", value, last)
86 }
87 })
88 }
89}
90
91func TestJavaScriptTakesOperatorsInRuns(t *testing.T) {
92 wantJS(t, "a === b", 0, "a:identifier", "===:operator", "b:identifier")
93 wantJS(t, "a ?? b", 0, "a:identifier", "??:operator", "b:identifier")
94 wantJS(t, "a => b", 0, "a:identifier", "=>:operator", "b:identifier")
95}
96
97func TestARegexIsLeftAsOperatorsRatherThanGuessedAt(t *testing.T) {
98 // Telling /x/g from a division needs to know whether the previous token
99 // could end an expression. Getting it wrong colours the rest of the line
100 // as a string, which is worse than this.
101 got := spansOf(t, LanguageJavaScript, "x = /ab/g", 0)
102 for _, span := range got {
103 if len(span) > 7 && span[len(span)-7:] == ":string" {
104 t.Errorf("a regex was guessed at as a string: %v", got)
105 }
106 }
107}
108
109func TestJavaScriptGivesOneEntryPerLine(t *testing.T) {
110 if got := len(Highlight(LanguageJavaScript, "a\nb\n\nc\n")); got != 5 {
111 t.Errorf("Highlight() returned %d lines for a 5-line document", got)
112 }
113}
114
115func TestJavaScriptSpansStayInsideTheirLine(t *testing.T) {
116 src := "import { a } from 'b'\n/* c\nd */\nconst t = `x${y}z`\nconsole.log(0x1f)\n"
117 assertSpansFit(t, LanguageJavaScript, src)
118}