forked from logseq/logseq
-
Notifications
You must be signed in to change notification settings - Fork 0
/
code-editing.spec.ts
320 lines (259 loc) · 11.7 KB
/
code-editing.spec.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
import { expect } from '@playwright/test'
import { test } from './fixtures'
import {
createRandomPage,
escapeToCodeEditor,
escapeToBlockEditor,
repeatKeyPress,
} from './utils'
/**
* NOTE: CodeMirror is a complex library that requires a lot of setup to work.
* This test suite is designed to test the basic functionality of the editor.
* It is not intended to test the full functionality of CodeMirror.
* For more information, see: https://codemirror.net/doc/manual.html
*/
// TODO: Fix test that started intermittently failing some time around
// https://github.com/logseq/logseq/pull/9540
test.skip('switch code editing mode', async ({ page }) => {
await createRandomPage(page)
// NOTE: ` will trigger auto-pairing in Logseq
// NOTE: ( will trigger auto-pairing in CodeMirror
// NOTE: waitForTimeout is needed to ensure that the hotkey handler is finished (shift+enter)
// NOTE: waitForTimeout is needed to ensure that the CodeMirror editor is fully loaded and unloaded
// NOTE: multiple textarea elements are existed in the editor, be careful to select the right one
// code block with 0 line
await page.type('textarea >> nth=0', '```clojure\n')
// line number: 1
await page.waitForSelector('.CodeMirror pre', { state: 'visible' })
expect(await page.locator('.CodeMirror-gutter-wrapper .CodeMirror-linenumber').innerText()).toBe('1')
// lang label: clojure
expect(await page.innerText('.block-body .extensions__code-lang')).toBe('clojure')
await page.press('.CodeMirror textarea', 'Escape')
await page.waitForSelector('.CodeMirror pre', { state: 'hidden' })
expect(await page.inputValue('textarea >> nth=0')).toBe('```clojure\n```')
await page.waitForTimeout(200)
await page.press('textarea >> nth=0', 'Escape')
await page.waitForSelector('.CodeMirror pre', { state: 'visible' })
// NOTE: must wait here, await loading of CodeMirror editor
await page.waitForTimeout(200)
await page.click('.CodeMirror pre')
await page.waitForTimeout(200)
await page.type('.CodeMirror textarea', '(+ 1 1')
await page.press('.CodeMirror textarea', 'Escape')
await page.waitForSelector('.CodeMirror pre', { state: 'hidden' })
expect(await page.inputValue('.block-editor textarea')).toBe('```clojure\n(+ 1 1)\n```')
await page.waitForTimeout(200) // editor unloading
await page.press('.block-editor textarea', 'Escape')
await page.waitForTimeout(200) // editor loading
// click position is estimated to be at the beginning of the first line
await page.click('.CodeMirror pre', { position: { x: 1, y: 5 } })
await page.waitForTimeout(200)
await page.type('.CodeMirror textarea', ';; comment\n\n \n')
await page.press('.CodeMirror textarea', 'Escape')
await page.waitForSelector('.CodeMirror pre', { state: 'hidden' })
expect(await page.inputValue('.block-editor textarea')).toBe('```clojure\n;; comment\n\n \n(+ 1 1)\n```')
})
test('convert from block content to code', async ({ page }) => {
await createRandomPage(page)
await page.type('.block-editor textarea', '```')
await page.press('.block-editor textarea', 'Shift+Enter')
await page.waitForTimeout(200) // wait for hotkey handler
await page.press('.block-editor textarea', 'Escape')
await page.waitForSelector('.CodeMirror pre', { state: 'visible' })
await page.waitForTimeout(500)
await page.click('.CodeMirror pre')
await page.waitForTimeout(500)
expect(await page.locator('.CodeMirror-gutter-wrapper .CodeMirror-linenumber >> nth=-1').innerText()).toBe('1')
await page.press('.CodeMirror textarea', 'Escape')
await page.waitForTimeout(500)
expect(await page.inputValue('.block-editor textarea')).toBe('```\n```')
// reset block, code block with 1 line
await page.fill('.block-editor textarea', '```\n\n```')
await page.waitForTimeout(200) // wait for fill
await escapeToCodeEditor(page)
expect(await page.locator('.CodeMirror-gutter-wrapper .CodeMirror-linenumber >> nth=-1').innerText()).toBe('1')
await escapeToBlockEditor(page)
expect(await page.inputValue('.block-editor textarea')).toBe('```\n\n```')
// reset block, code block with 2 line
await page.fill('.block-editor textarea', '```\n\n\n```')
await page.waitForTimeout(200)
await escapeToCodeEditor(page)
expect(await page.locator('.CodeMirror-gutter-wrapper .CodeMirror-linenumber >> nth=-1').innerText()).toBe('2')
await escapeToBlockEditor(page)
expect(await page.inputValue('.block-editor textarea')).toBe('```\n\n\n```')
await page.fill('.block-editor textarea', '```\n indented\nsecond line\n\n```')
await page.waitForTimeout(200)
await escapeToCodeEditor(page)
await escapeToBlockEditor(page)
expect(await page.inputValue('.block-editor textarea')).toBe('```\n indented\nsecond line\n\n```')
await page.fill('.block-editor textarea', '```\n indented\n indented\n```')
await page.waitForTimeout(200)
await escapeToCodeEditor(page)
await escapeToBlockEditor(page)
expect(await page.inputValue('.block-editor textarea')).toBe('```\n indented\n indented\n```')
})
test('code block mixed input source', async ({ page }) => {
await createRandomPage(page)
await page.fill('.block-editor textarea', '```\n ABC\n```')
await page.waitForTimeout(500) // wait for fill
await escapeToCodeEditor(page)
await page.type('.CodeMirror textarea', ' DEF\nGHI')
await page.waitForTimeout(500)
await page.press('.CodeMirror textarea', 'Escape')
await page.waitForTimeout(500)
// NOTE: auto-indent is on
expect(await page.inputValue('.block-editor textarea')).toBe('```\n ABC DEF\n GHI\n```')
})
test('code block with text around', async ({ page }) => {
await createRandomPage(page)
await page.fill('.block-editor textarea', 'Heading\n```\n```\nFooter')
await page.waitForTimeout(200)
await escapeToCodeEditor(page)
await page.type('.CodeMirror textarea', 'first\n second')
await page.waitForTimeout(500)
await page.press('.CodeMirror textarea', 'Escape')
await page.waitForTimeout(500)
expect(await page.inputValue('.block-editor textarea')).toBe('Heading\n```\nfirst\n second\n```\nFooter')
})
test('multiple code block', async ({ page }) => {
await createRandomPage(page)
// NOTE: the two code blocks are of the same content
await page.fill('.block-editor textarea', '中文 Heading\n```clojure\n```\nMiddle 🚀\n```clojure\n```\nFooter')
await page.waitForTimeout(200)
await page.press('.block-editor textarea', 'Escape')
await page.waitForSelector('.CodeMirror pre', { state: 'visible' })
// first
await page.waitForTimeout(500)
await page.click('.CodeMirror pre >> nth=0')
await page.waitForTimeout(500)
await page.type('.CodeMirror textarea >> nth=0', ':key-test\n', { strict: true })
await page.waitForTimeout(500)
await page.press('.CodeMirror textarea >> nth=0', 'Escape')
await page.waitForTimeout(500)
expect(await page.inputValue('.block-editor textarea'))
.toBe('中文 Heading\n```clojure\n:key-test\n\n```\nMiddle 🚀\n```clojure\n```\nFooter')
// second
await page.press('.block-editor textarea', 'Escape')
await page.waitForSelector('.CodeMirror pre', { state: 'visible' })
await page.waitForTimeout(500)
await page.click('.CodeMirror >> nth=1 >> pre')
await page.waitForTimeout(500)
await page.type('.CodeMirror textarea >> nth=1', '\n :key-test 日本語\n', { strict: true })
await page.waitForTimeout(500)
await page.press('.CodeMirror textarea >> nth=1', 'Escape')
await page.waitForTimeout(500)
expect(await page.inputValue('.block-editor textarea'))
.toBe('中文 Heading\n```clojure\n:key-test\n\n```\nMiddle 🚀\n```clojure\n\n :key-test 日本語\n\n```\nFooter')
})
test('click outside to exit', async ({ page }) => {
await createRandomPage(page)
await page.fill('.block-editor textarea', 'Header ``Click``\n```\n ABC\n```')
await page.waitForTimeout(200) // wait for fill
await escapeToCodeEditor(page)
await page.type('.CodeMirror textarea', ' DEF\nGHI')
await page.waitForTimeout(500)
await page.click('text=Click')
await page.waitForTimeout(500)
// NOTE: auto-indent is on
expect(await page.inputValue('.block-editor textarea')).toBe('Header ``Click``\n```\n ABC DEF\n GHI\n```')
})
test('click language label to exit #3463', async ({ page, block }) => {
await createRandomPage(page)
await page.fill('.block-editor textarea', '```cpp\n```')
await page.waitForTimeout(200)
await escapeToCodeEditor(page)
await page.type('.CodeMirror textarea', '#include<iostream>')
await page.waitForTimeout(500)
await page.click('text=cpp') // the language label
await page.waitForTimeout(500)
expect(await page.inputValue('.block-editor textarea')).toBe('```cpp\n#include<iostream>\n```')
})
test('multi properties with code', async ({ page }) => {
await createRandomPage(page)
await page.fill('.block-editor textarea',
'type:: code\n' +
'类型:: 代码\n' +
'```go\n' +
'if err != nil {\n' +
'\treturn err\n' +
'}\n' +
'```'
)
await page.waitForTimeout(200)
await escapeToCodeEditor(page)
// first character of code
await page.click('.CodeMirror pre', { position: { x: 1, y: 5 } })
await page.waitForTimeout(500)
await page.type('.CodeMirror textarea', '// Returns nil\n')
await page.waitForTimeout(500)
await page.press('.CodeMirror textarea', 'Escape')
await page.waitForTimeout(500)
expect(await page.inputValue('.block-editor textarea')).toBe(
'type:: code\n' +
'类型:: 代码\n' +
'```go\n' +
'// Returns nil\n' +
'if err != nil {\n' +
'\treturn err\n' +
'}\n' +
'```'
)
})
test('Select codeblock language', async ({ page }) => {
await createRandomPage(page)
// Open the slash command menu
await page.type('textarea >> nth=0', '/code block', { delay: 20 })
expect(
await page.waitForSelector('[data-modal-name="commands"]', {
state: 'visible',
})
).toBeTruthy()
// Select `code block` command and open the language dropdown menu
await page.press('textarea >> nth=0', 'Enter', { delay: 10 })
// wait for the modal to open
expect(
await page.waitForSelector('[data-modal-name="select-code-block-mode"]', {
state: 'visible',
})
).toBeTruthy()
// Select Clojure from the dropdown menu
await repeatKeyPress(page, 'ArrowDown', 6)
await page.press('textarea >> nth=0', 'Enter', { delay: 10 })
// expect the codeblock to be visible
expect(await page.waitForSelector('.CodeMirror', { state: 'visible' }))
// Exit codeblock and return to block edit mode
await page.press('.CodeMirror textarea >> nth=0', 'Escape', { delay: 10 })
expect(await page.inputValue('.block-editor textarea')).toBe(
'```clojure\n```'
)
})
test('Select codeblock language while surrounded by text', async ({ page }) => {
await createRandomPage(page)
await page.type('textarea >> nth=0', 'ABC XYZ', { delay: 20 })
await repeatKeyPress(page, 'ArrowLeft', 3)
// Open the slash command menu
await page.type('textarea >> nth=0', '/code block', { delay: 20 })
expect(
await page.waitForSelector('[data-modal-name="commands"]', {
state: 'visible',
})
).toBeTruthy()
// Select `code block` command and open the language dropdown menu
await page.press('textarea >> nth=0', 'Enter', { delay: 10 })
// wait for the modal to open
expect(
await page.waitForSelector('[data-modal-name="select-code-block-mode"]', {
state: 'visible',
})
).toBeTruthy()
// Select Clojure from the dropdown menu
await repeatKeyPress(page, 'ArrowDown', 6)
await page.press('textarea >> nth=0', 'Enter', { delay: 10 })
// expect the codeblock to be visible
expect(await page.waitForSelector('.CodeMirror', { state: 'visible' }))
// Exit codeblock and return to block edit mode
await page.press('.CodeMirror textarea >> nth=0', 'Escape', { delay: 10 })
expect(await page.inputValue('.block-editor textarea')).toBe(
'ABC \n```clojure\n```\nXYZ'
)
})