77} from "@codemirror/language" ;
88import { highlightSelectionMatches , searchKeymap } from "@codemirror/search" ;
99import { EditorSelection , EditorState } from "@codemirror/state" ;
10- import { EditorView } from "@codemirror/view" ;
10+ import { EditorView , runScopeHandlers } from "@codemirror/view" ;
1111import createBaseExtensions from "cm/baseExtensions" ;
1212import indentGuides from "cm/indentGuides" ;
1313import {
@@ -33,7 +33,7 @@ import { TestRunner } from "./tester";
3333export async function runCodeMirrorTests ( writeOutput ) {
3434 const runner = new TestRunner ( "CodeMirror 6 Editor Tests" ) ;
3535
36- function createEditor ( doc = "" , extensions = [ ] ) {
36+ function createEditor ( doc = "" , extensions = [ ] , baseExtensionOptions = { } ) {
3737 const container = document . createElement ( "div" ) ;
3838 container . style . width = "500px" ;
3939 container . style . height = "300px" ;
@@ -42,18 +42,31 @@ export async function runCodeMirrorTests(writeOutput) {
4242
4343 const state = EditorState . create ( {
4444 doc,
45- extensions : [ ...createBaseExtensions ( ) , ...extensions ] ,
45+ extensions : [
46+ ...createBaseExtensions ( baseExtensionOptions ) ,
47+ ...extensions ,
48+ ] ,
4649 } ) ;
4750
4851 const view = new EditorView ( { state, parent : container } ) ;
4952 return { view, container } ;
5053 }
5154
52- async function withEditor ( test , fn , initialDoc = "" , extensions = [ ] ) {
55+ async function withEditor (
56+ test ,
57+ fn ,
58+ initialDoc = "" ,
59+ extensions = [ ] ,
60+ baseExtensionOptions = { } ,
61+ ) {
5362 let view , container ;
5463
5564 try {
56- ( { view, container } = createEditor ( initialDoc , extensions ) ) ;
65+ ( { view, container } = createEditor (
66+ initialDoc ,
67+ extensions ,
68+ baseExtensionOptions ,
69+ ) ) ;
5770 test . assert ( view != null , "EditorView instance should be created" ) ;
5871 await new Promise ( ( resolve ) => setTimeout ( resolve , 100 ) ) ;
5972 await fn ( view ) ;
@@ -139,6 +152,50 @@ export async function runCodeMirrorTests(writeOutput) {
139152 container . remove ( ) ;
140153 } ) ;
141154
155+ runner . test ( "Backspace deletes an auto-closed bracket pair" , async ( test ) => {
156+ await withEditor (
157+ test ,
158+ async ( view ) => {
159+ view . dispatch ( { selection : { anchor : 1 } } ) ;
160+ const handled = runScopeHandlers (
161+ view ,
162+ new KeyboardEvent ( "keydown" , { key : "Backspace" } ) ,
163+ "editor" ,
164+ ) ;
165+
166+ test . assert (
167+ handled ,
168+ "Backspace should be handled between a bracket pair" ,
169+ ) ;
170+ test . assertEqual ( view . state . doc . toString ( ) , "" ) ;
171+ } ,
172+ "()" ,
173+ ) ;
174+ } ) ;
175+
176+ runner . test (
177+ "Backspace behaves normally when auto-close is disabled" ,
178+ async ( test ) => {
179+ await withEditor (
180+ test ,
181+ async ( view ) => {
182+ view . dispatch ( { selection : { anchor : 1 } } ) ;
183+ const handled = runScopeHandlers (
184+ view ,
185+ new KeyboardEvent ( "keydown" , { key : "Backspace" } ) ,
186+ "editor" ,
187+ ) ;
188+
189+ test . assert ( handled , "Backspace should retain its default behavior" ) ;
190+ test . assertEqual ( view . state . doc . toString ( ) , ")" ) ;
191+ } ,
192+ "()" ,
193+ [ ] ,
194+ { autoCloseBrackets : false } ,
195+ ) ;
196+ } ,
197+ ) ;
198+
142199 runner . test ( "State access" , async ( test ) => {
143200 await withEditor ( test , async ( view ) => {
144201 const state = view . state ;
0 commit comments