From 996158f29da9efbee04cc72f7ada33bbcb7a7dee Mon Sep 17 00:00:00 2001 From: Diullei Gomes Date: Mon, 18 Feb 2013 21:15:05 -0300 Subject: [PATCH] ace definitions updated; I added some tests. --- .gitignore | 3 + ace/ace.d.ts | 291 ++++-- ace/all-tests.ts | 21 + ace/tests/ace-anchor-tests.ts | 131 +++ ace/tests/ace-background_tokenizer-tests.ts | 39 + .../ace-default-tests.ts} | 5 +- ace/tests/ace-document-tests.ts | 254 +++++ ace/tests/ace-edit_session-tests.ts | 919 ++++++++++++++++++ ace/tests/ace-editor1-tests.ts | 153 +++ ...ce-editor_highlight_selected_word-tests.ts | 214 ++++ ace/tests/ace-editor_navigation-tests.ts | 117 +++ ace/tests/ace-editor_text_edit-tests.ts | 498 ++++++++++ ace/tests/ace-multi_select-tests.ts | 111 +++ ace/tests/ace-placeholder-tests.ts | 106 ++ ace/tests/ace-range_list-tests.ts | 117 +++ 15 files changed, 2912 insertions(+), 67 deletions(-) create mode 100644 ace/all-tests.ts create mode 100644 ace/tests/ace-anchor-tests.ts create mode 100644 ace/tests/ace-background_tokenizer-tests.ts rename ace/{ace-tests.ts => tests/ace-default-tests.ts} (99%) create mode 100644 ace/tests/ace-document-tests.ts create mode 100644 ace/tests/ace-edit_session-tests.ts create mode 100644 ace/tests/ace-editor1-tests.ts create mode 100644 ace/tests/ace-editor_highlight_selected_word-tests.ts create mode 100644 ace/tests/ace-editor_navigation-tests.ts create mode 100644 ace/tests/ace-editor_text_edit-tests.ts create mode 100644 ace/tests/ace-multi_select-tests.ts create mode 100644 ace/tests/ace-placeholder-tests.ts create mode 100644 ace/tests/ace-range_list-tests.ts diff --git a/.gitignore b/.gitignore index ae6b742951..da632fc918 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ .DS_Store _Resharper.DefinitelyTyped +bin +obj +Properties diff --git a/ace/ace.d.ts b/ace/ace.d.ts index 75b597ba2c..0a945f27f2 100644 --- a/ace/ace.d.ts +++ b/ace/ace.d.ts @@ -5,18 +5,96 @@ module AceAjax { - interface CommandManager { - addCommand(command); + export interface Delta { + action: string; + range: Range; + text: string; + lines: string[]; } - interface TextMode { + export interface EditorCommand { + + name:string; + + bindKey:any; + + exec:Function; + } + + export interface CommandManager { + + byName; + + commands; + + platform: string; + + addCommands(commands:EditorCommand[]); + + addCommand(command:EditorCommand); + + exec(name: string, editor: Editor, args: any); + } + + export interface Annotation { + + row: number; + + column: number; + + text: string; + + type: string; + } + + export interface TokenInfo { + + value: string; + } + + export interface Position { + + row: number; + + column: number; + } + + export interface KeyBinding { + + setDefaultHandler(kb); + + setKeyboardHandler(kb); + + addKeyboardHandler(kb, pos); + + removeKeyboardHandler(kb): bool; + + getKeyboardHandler(): any; + + onCommandKey(e, hashId, keyCode); + + onTextInput(text); + } + declare var KeyBinding: { + new(editor: Editor): KeyBinding; + } + + export interface TextMode { + getTokenizer(): any; + toggleCommentLines(state, doc, startRow, endRow); + getNextLineIndent (state, line, tab): string; + checkOutdent(state, line, input): bool; + autoOutdent(state, doc, row); + createWorker(session): any; + createModeDelegates (mapping); + transformAction(state, action, editor, session, param): any; } @@ -27,7 +105,7 @@ module AceAjax { /** * The main class required to set up an Ace instance in the browser. **/ - interface Ace { + export interface Ace { /** * Provides access to require in packed noconflict mode @@ -52,14 +130,14 @@ module AceAjax { * @param text {:textParam} * @param mode {:modeParam} **/ - createEditSession(text: Document, mode: TextMode): EditSession; + createEditSession(text: Document, mode: TextMode): IEditSession; /** * Creates a new [[EditSession]], and returns the associated [[Document]]. * @param text {:textParam} * @param mode {:modeParam} **/ - createEditSession(text: string, mode: TextMode): EditSession; + createEditSession(text: string, mode: TextMode): IEditSession; } //////////////// @@ -69,14 +147,14 @@ module AceAjax { /** * Defines the floating pointer in the document. Whenever text is inserted or deleted before the cursor, the position of the cursor is updated. **/ - interface Anchor { + export interface Anchor { on(event: string, fn: (e) => any); /** * Returns an object identifying the `row` and `column` position of the current anchor. **/ - getPosition(): any; + getPosition(): Position; /** * Returns the current document. @@ -124,7 +202,9 @@ module AceAjax { * Tokenizes the current [[Document `Document`]] in the background, and caches the tokenized rows for future use. * If a certain row is changed, everything below that row is re-tokenized. **/ - interface BackgroundTokenizer { + export interface BackgroundTokenizer { + + states: any[]; /** * Sets a new tokenizer for this object. @@ -185,7 +265,9 @@ module AceAjax { * Contains the text of the document. Document can be attached to several [[EditSession `EditSession`]]s. * At its core, `Document`s are just an array of strings, with each row in the document matching up to the array index. **/ - interface Document { + export interface Document { + + on(event: string, fn: (e) => any); /** * Replaces all the lines in the current `Document` with the value of `text`. @@ -261,20 +343,20 @@ module AceAjax { * @param position The position to start inserting at * @param text A chunk of text to insert **/ - insert(position: any, text: string): any; + insert(position: Position, text: string): any; /** * Inserts the elements in `lines` into the document, starting at the row index given by `row`. This method also triggers the `'change'` event. * @param row The index of the row to insert at * @param lines An array of strings **/ - insertLines(row: number, lines: Array): any; + insertLines(row: number, lines: string[]): any; /** * Inserts a new line into the document at the current row's `position`. This method also triggers the `'change'` event. * @param position The position to insert at **/ - insertNewLine(position: any): any; + insertNewLine(position: Position): any; /** * Inserts `text` into the `position` at the current row. This method also triggers the `'change'` event. @@ -320,12 +402,12 @@ module AceAjax { /** * Applies all the changes previously accumulated. These can be either `'includeText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`. **/ - applyDeltas(); + applyDeltas(deltas: Delta[]); /** * Reverts any changes previously applied. These can be either `'includeText'`, `'insertLines'`, `'removeText'`, and `'removeLines'`. **/ - revertDeltas(); + revertDeltas(deltas: Delta[]); /** * Converts an index position in a document to a `{row, column}` object. @@ -338,7 +420,7 @@ module AceAjax { * @param index An index to convert * @param startRow=0 The row from which to start the conversion **/ - indexToPosition(index: number, startRow: number): any; + indexToPosition(index: number, startRow: number): Position; /** * Converts the `{row, column}` position in a document to the character's index. @@ -351,7 +433,7 @@ module AceAjax { * @param pos The `{row, column}` to convert * @param startRow=0 The row from which to start the conversion **/ - positionToIndex(pos: any, startRow: number): number; + positionToIndex(pos: Position, startRow: number): number; } declare var Document: { /** @@ -374,11 +456,35 @@ module AceAjax { * Stores all the data about [[Editor `Editor`]] state providing easy way to change editors state. * `EditSession` can be attached to only one [[Document `Document`]]. Same `Document` can be attached to several `EditSession`s. **/ - interface EditSession { + export interface IEditSession { + + selection: Selection; + + bgTokenizer: BackgroundTokenizer; + + doc: Document; on(event: string, fn: (e) => any); - selection: Selection; + findMatchingBracket(position: Position); + + addFold(text: string, range: Range); + + getFoldAt(row: number, column: number): any; + + removeFold(arg: any); + + expandFold(arg: any); + + unfold(arg1: any, arg2: bool); + + screenToDocumentColumn(row: number, column: number); + + getFoldDisplayLine(foldLine: any, docRow: number, docColumn: number): any; + + getFoldsInRange(range: Range): any; + + highlight(text: string); /** * Sets the `EditSession` to point to a new `Document`. If a `BackgroundTokenizer` exists, it also points to `doc`. @@ -432,7 +538,7 @@ module AceAjax { * @param row The row number to retrieve from * @param column The column number to retrieve from **/ - getTokenAt(row: number, column: number): any; + getTokenAt(row: number, column: number): TokenInfo; /** * Sets the undo manager. @@ -579,7 +685,7 @@ module AceAjax { * Sets annotations for the `EditSession`. This functions emits the `'changeAnnotation'` event. * @param annotations A list of annotations **/ - setAnnotations(annotations: Array); + setAnnotations(annotations: Annotation[]); /** * Returns the annotations for the `EditSession`. @@ -704,7 +810,7 @@ module AceAjax { * @param position The position {row, column} to start inserting at * @param text A chunk of text to insert **/ - insert(position: any, text: string): any; + insert(position: Position, text: string): any; /** * Removes the `range` from the document. @@ -911,9 +1017,11 @@ module AceAjax { * @param text [If `text` is a `Document`, it associates the `EditSession` with it. Otherwise, a new `Document` is created, with the initial text]{: #textParam} * @param mode [The inital language mode to use for the document]{: #modeParam} **/ - new(text: string, mode?: TextMode): EditSession; + new(text: string, mode?: TextMode): IEditSession; - new(text: string[]): EditSession; + new(content: string, mode?: string): IEditSession; + + new (text: string[], mode?: string): IEditSession; } //////////////////////////////// @@ -925,7 +1033,11 @@ module AceAjax { * The `Editor` manages the [[EditSession]] (which manages [[Document]]s), as well as the [[VirtualRenderer]], which draws everything to the screen. * Event sessions dealing with the mouse and keyboard are bubbled up from `Document` to the `Editor`, which decides what to do with them. **/ - interface Editor { + export interface Editor { + + inMultiSelectMode: bool; + + selectMoreLines(n: number); onTextInput(text: string); @@ -933,10 +1045,22 @@ module AceAjax { commands: CommandManager; - session: EditSession; + session: IEditSession; selection: Selection; + renderer: VirtualRenderer; + + keyBinding: KeyBinding; + + container: HTMLElement; + + onSelectionChange(e); + + onChangeMode(e?); + + execCommand(command:string, args?: any); + /** * Sets a new key handler, such as "vim" or "windows". * @param keyboardHandler The new key handler @@ -952,12 +1076,12 @@ module AceAjax { * Sets a new editsession to use. This method also emits the `'changeSession'` event. * @param session The new session to use **/ - setSession(session: EditSession); + setSession(session: IEditSession); /** * Returns the current session being used. **/ - getSession(): EditSession; + getSession(): IEditSession; /** * Sets the current document to `val`. @@ -1411,7 +1535,7 @@ module AceAjax { /** * Gets the current position of the cursor. **/ - getCursorPosition(): any; + getCursorPosition(): Position; /** * Returns the screen position of the cursor. @@ -1438,13 +1562,13 @@ module AceAjax { * @param row The new row number * @param column The new column number **/ - moveCursorTo(row: number, column: number); + moveCursorTo(row: number, column?: number, animate?:bool); /** * Moves the cursor to the position indicated by `pos.row` and `pos.column`. - * @param pos An object with two properties, row and column + * @param position An object with two properties, row and column **/ - moveCursorToPosition(pos: any); + moveCursorToPosition(position: Position); /** * Moves the cursor's row and column to the next matching bracket. @@ -1470,19 +1594,19 @@ module AceAjax { * Moves the cursor up in the document the specified number of times. Note that this does de-select the current selection. * @param times The number of times to change navigation **/ - navigateUp(times: number); + navigateUp(times?: number); /** * Moves the cursor down in the document the specified number of times. Note that this does de-select the current selection. * @param times The number of times to change navigation **/ - navigateDown(times: number); + navigateDown(times?: number); /** * Moves the cursor left in the document the specified number of times. Note that this does de-select the current selection. * @param times The number of times to change navigation **/ - navigateLeft(times: number); + navigateLeft(times?: number); /** * Moves the cursor right in the document the specified number of times. Note that this does de-select the current selection. @@ -1584,14 +1708,16 @@ module AceAjax { * @param renderer Associated `VirtualRenderer` that draws everything * @param session The `EditSession` to refer to **/ - new(renderer: VirtualRenderer, session: EditSession): Editor; + new(renderer: VirtualRenderer, session?: IEditSession): Editor; } //////////////////////////////// /// PlaceHolder //////////////////////////////// - interface PlaceHolder { + export interface PlaceHolder { + + on(event: string, fn: (e) => any); /** * PlaceHolder.setup() @@ -1637,16 +1763,39 @@ module AceAjax { } declare var PlaceHolder: { /** - * - session (Document): The document to associate with the anchor - * - length (Number): The starting row position - * - pos (Number): The starting column position - * - others (String): - * - mainClass (String): - * - othersClass (String): + * - @param session (Document): The document to associate with the anchor + * - @param length (Number): The starting row position + * - @param pos (Number): The starting column position + * - @param others (String): + * - @param mainClass (String): + * - @param othersClass (String): **/ - new(): PlaceHolder; + new (session: Document, length: number, pos: number, others: string, mainClass: string, othersClass: string): PlaceHolder; + + new (session: IEditSession, length: number, pos: Position, positions: Position[]): PlaceHolder; } + //////////////// + /// RangeList + //////////////// + + export interface IRangeList { + ranges: Range[]; + + pointIndex(pos: Position, startIndex?: number); + + addList(ranges: Range[]); + + add(ranges: Range); + + merge(): Range[]; + + substractPoint(pos: Position); + } + export var RangeList: { + new (): IRangeList; + } + //////////////// /// Range //////////////// @@ -1654,11 +1803,19 @@ module AceAjax { /** * This object is used in various places to indicate a region within the editor. To better visualize how this works, imagine a rectangle. Each quadrant of the rectangle is analogus to a range, as ranges contain a starting row and starting column, and an ending row, and ending column. **/ - interface Range { + export interface Range { - start: number; + startRow:number; - end: number; + startColumn:number; + + endRow:number; + + endColumn:number; + + start: Position; + + end: Position; /** * Returns `true` if and only if the starting row and column, and ending row and column, are equivalent to those given by `range`. @@ -1819,7 +1976,7 @@ module AceAjax { * Given the current `Range`, this function converts those starting and ending points into screen positions, and then returns a new `Range` object. * @param session The `EditSession` to retrieve coordinates from **/ - toScreenRange(session: EditSession): Range; + toScreenRange(session: IEditSession): Range; /** * Creates and returns a new `Range` based on the row and column of the given parameters. @@ -1844,7 +2001,7 @@ module AceAjax { /// RenderLoop //////////////// - interface RenderLoop { } + export interface RenderLoop { } declare var RenderLoop: { new(): RenderLoop; } @@ -1856,7 +2013,7 @@ module AceAjax { /** * A set of methods for setting and retrieving the editor's scrollbar. **/ - interface ScrollBar { + export interface ScrollBar { /** * Emitted when the scroll bar, well, scrolls. @@ -1902,7 +2059,7 @@ module AceAjax { /** * A class designed to handle all sorts of text searches within a [[Document `Document`]]. **/ - interface Search { + export interface Search { /** * Sets the search options via the `options` parameter. @@ -1925,13 +2082,13 @@ module AceAjax { * Searches for `options.needle`. If found, this method returns the [[Range `Range`]] where the text first occurs. If `options.backwards` is `true`, the search goes backwards in the session. * @param session The session to search with **/ - find(session: EditSession): Range; + find(session: IEditSession): Range; /** * Searches for all occurances `options.needle`. If found, this method returns an array of [[Range `Range`s]] where the text first occurs. If `options.backwards` is `true`, the search goes backwards in the session. * @param session The session to search with **/ - findAll(session: EditSession): Range[]; + findAll(session: IEditSession): Range[]; /** * Searches for `options.needle` in `input`, and, if found, replaces it with `replacement`. @@ -1966,10 +2123,18 @@ module AceAjax { * Contains the cursor position and the text selection of an edit session. * The row/columns used in the selection are in document coordinates representing ths coordinates as thez appear in the document before applying soft wrap and folding. **/ - interface Selection { + export interface Selection { + + fromOrientedRange(range: Range); + + setSelectionRange(match); + + getAllRanges(): Range[]; on(event: string, fn: (e) => any); + addRange(range: Range); + /** * Returns `true` if the selection is empty. **/ @@ -2187,7 +2352,7 @@ module AceAjax { * @param column The column to move to * @param keepDesiredColumn [If `true`, the cursor move does not respect the previous column]{: #preventUpdateBool} **/ - moveCursorTo(row: number, column: number, keepDesiredColumn: bool); + moveCursorTo(row: number, column: number, keepDesiredColumn?: bool); /** * Moves the cursor to the screen position indicated by row and column. {:preventUpdateBoolDesc} @@ -2202,14 +2367,14 @@ module AceAjax { * Creates a new `Selection` object. * @param session The session to use **/ - new(session: EditSession): Selection; + new(session: IEditSession): Selection; } //////////////// /// Split //////////////// - interface Split { + export interface Split { /** * Returns the number of splits. @@ -2267,7 +2432,7 @@ module AceAjax { * @param session The new edit session * @param idx The editor's index you're interested in **/ - setSession(session: EditSession, idx: number); + setSession(session: IEditSession, idx: number); /** * Returns the orientation. @@ -2296,7 +2461,7 @@ module AceAjax { /** * This class provides an essay way to treat the document as a stream of tokens, and provides methods to iterate over these tokens. **/ - interface TokenIterator { + export interface TokenIterator { /** * Tokenizes all the items from the current point to the row prior in the document. @@ -2330,7 +2495,7 @@ module AceAjax { * @param initialRow The row to start the tokenizing at * @param initialColumn The column to start the tokenizing at **/ - new(session: EditSession, initialRow: number, initialColumn: number): TokenIterator; + new(session: IEditSession, initialRow: number, initialColumn: number): TokenIterator; } ////////////////// @@ -2341,7 +2506,7 @@ module AceAjax { /** * This class takes a set of highlighting rules, and creates a tokenizer out of them. For more information, see [the wiki on extending highlighters](https://github.com/ajaxorg/ace/wiki/Creating-or-Extending-an-Edit-Mode#wiki-extendingTheHighlighter). **/ - interface Tokenizer { + export interface Tokenizer { /** * Returns an object containing two properties: `tokens`, which contains all the tokens; and `state`, the current state. @@ -2364,7 +2529,7 @@ module AceAjax { /** * This object maintains the undo stack for an [[EditSession `EditSession`]]. **/ - interface UndoManager { + export interface UndoManager { /** * Provides a means for implementing your own undo manager. `options` has one property, `args`, an [[Array `Array`]], with two elements: @@ -2416,7 +2581,7 @@ module AceAjax { /** * The class that is responsible for drawing everything you see on the screen! **/ - interface VirtualRenderer { + export interface VirtualRenderer { /** * Associates the renderer with an [[EditSession `EditSession`]]. diff --git a/ace/all-tests.ts b/ace/all-tests.ts new file mode 100644 index 0000000000..163d973ea2 --- /dev/null +++ b/ace/all-tests.ts @@ -0,0 +1,21 @@ +/// + +var exports: any; +var assert: any; +var MockRenderer = null; +var JavaScriptMode = null; + +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// + + + diff --git a/ace/tests/ace-anchor-tests.ts b/ace/tests/ace-anchor-tests.ts new file mode 100644 index 0000000000..40e81600ab --- /dev/null +++ b/ace/tests/ace-anchor-tests.ts @@ -0,0 +1,131 @@ +/// + +exports = { + + "test create anchor" : function() { + var doc = new AceAjax.Document("juhu"); + var anchor = new AceAjax.Anchor(doc, 0, 0); + + assert.position(anchor.getPosition(), 0, 0); + assert.equal(anchor.getDocument(), doc); + }, + + "test insert text in same row before cursor should move anchor column": function() { + var doc = new AceAjax.Document("juhu\nkinners"); + var anchor = new AceAjax.Anchor(doc, 1, 4); + + doc.insert({row: 1, column: 1}, "123"); + assert.position(anchor.getPosition(), 1, 7); + }, + + "test insert lines before cursor should move anchor row": function() { + var doc = new AceAjax.Document("juhu\nkinners"); + var anchor = new AceAjax.Anchor(doc, 1, 4); + + doc.insertLines(1, ["123", "456"]); + assert.position(anchor.getPosition(), 3, 4); + }, + + "test insert new line before cursor should move anchor column": function() { + var doc = new AceAjax.Document("juhu\nkinners"); + var anchor = new AceAjax.Anchor(doc, 1, 4); + + doc.insertNewLine({row: 0, column: 0}); + assert.position(anchor.getPosition(), 2, 4); + }, + + "test insert new line in anchor line before anchor should move anchor column and row": function() { + var doc = new AceAjax.Document("juhu\nkinners"); + var anchor = new AceAjax.Anchor(doc, 1, 4); + + doc.insertNewLine({row: 1, column: 2}); + assert.position(anchor.getPosition(), 2, 2); + }, + + "test delete text in anchor line before anchor should move anchor column": function() { + var doc = new AceAjax.Document("juhu\nkinners"); + var anchor = new AceAjax.Anchor(doc, 1, 4); + + doc.remove(new AceAjax.Range(1, 1, 1, 3)); + assert.position(anchor.getPosition(), 1, 2); + }, + + "test remove range which contains the anchor should move the anchor to the start of the range": function() { + var doc = new AceAjax.Document("juhu\nkinners"); + var anchor = new AceAjax.Anchor(doc, 0, 3); + + doc.remove(new AceAjax.Range(0, 1, 1, 3)); + assert.position(anchor.getPosition(), 0, 1); + }, + + "test delete character before the anchor should have no effect": function() { + var doc = new AceAjax.Document("juhu\nkinners"); + var anchor = new AceAjax.Anchor(doc, 1, 4); + + doc.remove(new AceAjax.Range(1, 4, 1, 5)); + assert.position(anchor.getPosition(), 1, 4); + }, + + "test delete lines in anchor line before anchor should move anchor row": function() { + var doc = new AceAjax.Document("juhu\n1\n2\nkinners"); + var anchor = new AceAjax.Anchor(doc, 3, 4); + + doc.removeLines(1, 2); + assert.position(anchor.getPosition(), 1, 4); + }, + + "test remove new line before the cursor": function() { + var doc = new AceAjax.Document("juhu\nkinners"); + var anchor = new AceAjax.Anchor(doc, 1, 4); + + doc.removeNewLine(0); + assert.position(anchor.getPosition(), 0, 8); + }, + + "test delete range which contains the anchor should move anchor to the end of the range": function() { + var doc = new AceAjax.Document("juhu\nkinners"); + var anchor = new AceAjax.Anchor(doc, 1, 4); + + doc.remove(new AceAjax.Range(0, 2, 1, 2)); + assert.position(anchor.getPosition(), 0, 4); + }, + + "test delete line which contains the anchor should move anchor to the end of the range": function() { + var doc = new AceAjax.Document("juhu\nkinners\n123"); + var anchor = new AceAjax.Anchor(doc, 1, 5); + + doc.removeLines(1, 1); + assert.position(anchor.getPosition(), 1, 0); + }, + + "test remove after the anchor should have no effect": function() { + var doc = new AceAjax.Document("juhu\nkinners\n123"); + var anchor = new AceAjax.Anchor(doc, 1, 2); + + doc.remove(new AceAjax.Range(1, 4, 2, 2)); + assert.position(anchor.getPosition(), 1, 2); + }, + + "test anchor changes triggered by document changes should emit change event": function(next) { + var doc = new AceAjax.Document("juhu\nkinners\n123"); + var anchor = new AceAjax.Anchor(doc, 1, 5); + + anchor.on("change", function(e) { + assert.position(anchor.getPosition(), 0, 0); + next(); + }); + + doc.remove(new AceAjax.Range(0, 0, 2, 1)); + }, + + "test only fire change event if position changes": function() { + var doc = new AceAjax.Document("juhu\nkinners\n123"); + var anchor = new AceAjax.Anchor(doc, 1, 5); + + anchor.on("change", function(e) { + assert.fail(); + }); + + doc.remove(new AceAjax.Range(2, 0, 2, 1)); + } +}; diff --git a/ace/tests/ace-background_tokenizer-tests.ts b/ace/tests/ace-background_tokenizer-tests.ts new file mode 100644 index 0000000000..8c29358a40 --- /dev/null +++ b/ace/tests/ace-background_tokenizer-tests.ts @@ -0,0 +1,39 @@ +/// + +function forceTokenize(session) { + for (var i = 0, l = session.getLength(); i < l; i++) + session.getTokens(i) +} + +function testStates(session, states) { + for (var i = 0, l = session.getLength(); i < l; i++) + assert.equal(session.bgTokenizer.states[i], states[i]) + assert.ok(l == states.length) +} + +exports = { + + "test background tokenizer update on session change": function() { + var doc = new AceAjax.EditSession([ + "/*", + "*/", + "var juhu" + ]); + doc.setMode("./mode/javascript") + + forceTokenize(doc) + testStates(doc, ["comment", "start", "start"]) + + doc.remove(new AceAjax.Range(0, 2, 1, 2)) + testStates(doc, [null, "start"]) + + forceTokenize(doc) + testStates(doc, ["comment", "comment"]) + + doc.insert({ row: 0, column: 2 }, "\n*/") + testStates(doc, [undefined, undefined, "comment"]) + + forceTokenize(doc) + testStates(doc, ["comment", "start", "start"]) + } +}; diff --git a/ace/ace-tests.ts b/ace/tests/ace-default-tests.ts similarity index 99% rename from ace/ace-tests.ts rename to ace/tests/ace-default-tests.ts index 43556fb831..dcd1ab1033 100644 --- a/ace/ace-tests.ts +++ b/ace/tests/ace-default-tests.ts @@ -1,6 +1,4 @@ -/// - -var assert: any; +/// var editor = ace.edit("editor"); editor.setTheme("ace/theme/monokai"); @@ -450,4 +448,3 @@ editor.moveCursorTo(1, 0); editor.toLowerCase() assert.equal(session.getValue(), ["AJAX", "dot", "ORG"].join("\n")); assert.position(editor.getCursorPosition(), 1, 0); - diff --git a/ace/tests/ace-document-tests.ts b/ace/tests/ace-document-tests.ts new file mode 100644 index 0000000000..1f3e0a9a24 --- /dev/null +++ b/ace/tests/ace-document-tests.ts @@ -0,0 +1,254 @@ +/// + +exports = { + "test: insert text in line": function() { + var doc = new AceAjax.Document(["12", "34"]); + + var deltas = []; + doc.on("change", function (e) { deltas.push(e.data); }); + + doc.insert({ row: 0, column: 1 }, "juhu"); + assert.equal(doc.getValue(), ["1juhu2", "34"].join("\n")); + + var d = deltas.concat(); + doc.revertDeltas(d); + assert.equal(doc.getValue(), ["12", "34"].join("\n")); + + doc.applyDeltas(d); + assert.equal(doc.getValue(), ["1juhu2", "34"].join("\n")); + } , + + "test: insert new line": function() { + var doc = new AceAjax.Document(["12", "34"]); + + var deltas = []; + doc.on("change", function (e) { deltas.push(e.data); }); + + doc.insertNewLine({ row: 0, column: 1 }); + assert.equal(doc.getValue(), ["1", "2", "34"].join("\n")); + + var d = deltas.concat(); + doc.revertDeltas(d); + assert.equal(doc.getValue(), ["12", "34"].join("\n")); + + doc.applyDeltas(d); + assert.equal(doc.getValue(), ["1", "2", "34"].join("\n")); + } , + + "test: insert lines at the beginning": function() { + var doc = new AceAjax.Document(["12", "34"]); + + var deltas = []; + doc.on("change", function (e) { deltas.push(e.data); }); + + doc.insertLines(0, ["aa", "bb"]); + assert.equal(doc.getValue(), ["aa", "bb", "12", "34"].join("\n")); + + var d = deltas.concat(); + doc.revertDeltas(d); + assert.equal(doc.getValue(), ["12", "34"].join("\n")); + + doc.applyDeltas(d); + assert.equal(doc.getValue(), ["aa", "bb", "12", "34"].join("\n")); + } , + + "test: insert lines at the end": function() { + var doc = new AceAjax.Document(["12", "34"]); + + var deltas = []; + doc.on("change", function (e) { deltas.push(e.data); }); + + doc.insertLines(2, ["aa", "bb"]); + assert.equal(doc.getValue(), ["12", "34", "aa", "bb"].join("\n")); + } , + + "test: insert lines in the middle": function() { + var doc = new AceAjax.Document(["12", "34"]); + + var deltas = []; + doc.on("change", function (e) { deltas.push(e.data); }); + + doc.insertLines(1, ["aa", "bb"]); + assert.equal(doc.getValue(), ["12", "aa", "bb", "34"].join("\n")); + + var d = deltas.concat(); + doc.revertDeltas(d); + assert.equal(doc.getValue(), ["12", "34"].join("\n")); + + doc.applyDeltas(d); + assert.equal(doc.getValue(), ["12", "aa", "bb", "34"].join("\n")); + } , + + "test: insert multi line string at the start": function() { + var doc = new AceAjax.Document(["12", "34"]); + + var deltas = []; + doc.on("change", function (e) { deltas.push(e.data); }); + + doc.insert({ row: 0, column: 0 }, "aa\nbb\ncc"); + assert.equal(doc.getValue(), ["aa", "bb", "cc12", "34"].join("\n")); + + var d = deltas.concat(); + doc.revertDeltas(d); + assert.equal(doc.getValue(), ["12", "34"].join("\n")); + + doc.applyDeltas(d); + assert.equal(doc.getValue(), ["aa", "bb", "cc12", "34"].join("\n")); + } , + + "test: insert multi line string at the end": function() { + var doc = new AceAjax.Document(["12", "34"]); + + var deltas = []; + doc.on("change", function (e) { deltas.push(e.data); }); + + doc.insert({ row: 2, column: 0 }, "aa\nbb\ncc"); + assert.equal(doc.getValue(), ["12", "34aa", "bb", "cc"].join("\n")); + + var d = deltas.concat(); + doc.revertDeltas(d); + assert.equal(doc.getValue(), ["12", "34"].join("\n")); + + doc.applyDeltas(d); + assert.equal(doc.getValue(), ["12", "34aa", "bb", "cc"].join("\n")); + } , + + "test: insert multi line string in the middle": function() { + var doc = new AceAjax.Document(["12", "34"]); + + var deltas = []; + doc.on("change", function (e) { deltas.push(e.data); }); + + doc.insert({ row: 0, column: 1 }, "aa\nbb\ncc"); + assert.equal(doc.getValue(), ["1aa", "bb", "cc2", "34"].join("\n")); + + var d = deltas.concat(); + doc.revertDeltas(d); + assert.equal(doc.getValue(), ["12", "34"].join("\n")); + + doc.applyDeltas(d); + assert.equal(doc.getValue(), ["1aa", "bb", "cc2", "34"].join("\n")); + } , + + "test: delete in line": function() { + var doc = new AceAjax.Document(["1234", "5678"]); + + var deltas = []; + doc.on("change", function (e) { deltas.push(e.data); }); + + doc.remove(new AceAjax.Range(0, 1, 0, 3)); + assert.equal(doc.getValue(), ["14", "5678"].join("\n")); + + var d = deltas.concat(); + doc.revertDeltas(d); + assert.equal(doc.getValue(), ["1234", "5678"].join("\n")); + + doc.applyDeltas(d); + assert.equal(doc.getValue(), ["14", "5678"].join("\n")); + } , + + "test: delete new line": function() { + var doc = new AceAjax.Document(["1234", "5678"]); + + var deltas = []; + doc.on("change", function (e) { deltas.push(e.data); }); + + doc.remove(new AceAjax.Range(0, 4, 1, 0)); + assert.equal(doc.getValue(), ["12345678"].join("\n")); + + var d = deltas.concat(); + doc.revertDeltas(d); + assert.equal(doc.getValue(), ["1234", "5678"].join("\n")); + + doc.applyDeltas(d); + assert.equal(doc.getValue(), ["12345678"].join("\n")); + } , + + "test: delete multi line range line": function() { + var doc = new AceAjax.Document(["1234", "5678", "abcd"]); + + var deltas = []; + doc.on("change", function (e) { deltas.push(e.data); }); + + doc.remove(new AceAjax.Range(0, 2, 2, 2)); + assert.equal(doc.getValue(), ["12cd"].join("\n")); + + var d = deltas.concat(); + doc.revertDeltas(d); + assert.equal(doc.getValue(), ["1234", "5678", "abcd"].join("\n")); + + doc.applyDeltas(d); + assert.equal(doc.getValue(), ["12cd"].join("\n")); + } , + + "test: delete full lines": function() { + var doc = new AceAjax.Document(["1234", "5678", "abcd"]); + + var deltas = []; + doc.on("change", function (e) { deltas.push(e.data); }); + + doc.remove(new AceAjax.Range(1, 0, 3, 0)); + assert.equal(doc.getValue(), ["1234", ""].join("\n")); + } , + + "test: remove lines should return the removed lines": function() { + var doc = new AceAjax.Document(["1234", "5678", "abcd"]); + + var removed = doc.removeLines(1, 2); + assert.equal(removed.join("\n"), ["5678", "abcd"].join("\n")); + } , + + "test: should handle unix style new lines": function() { + var doc = new AceAjax.Document(["1", "2", "3"]); + assert.equal(doc.getValue(), ["1", "2", "3"].join("\n")); + } , + + "test: should handle windows style new lines": function() { + var doc = new AceAjax.Document(["1", "2", "3"].join("\r\n")); + + doc.setNewLineMode("unix"); + assert.equal(doc.getValue(), ["1", "2", "3"].join("\n")); + } , + + "test: set new line mode to 'windows' should use '\\r\\n' as new lines": function() { + var doc = new AceAjax.Document(["1", "2", "3"].join("\n")); + doc.setNewLineMode("windows"); + assert.equal(doc.getValue(), ["1", "2", "3"].join("\r\n")); + } , + + "test: set new line mode to 'unix' should use '\\n' as new lines": function() { + var doc = new AceAjax.Document(["1", "2", "3"].join("\r\n")); + + doc.setNewLineMode("unix"); + assert.equal(doc.getValue(), ["1", "2", "3"].join("\n")); + } , + + "test: set new line mode to 'auto' should detect the incoming nl type": function() { + var doc = new AceAjax.Document(["1", "2", "3"].join("\n")); + + doc.setNewLineMode("auto"); + assert.equal(doc.getValue(), ["1", "2", "3"].join("\n")); + + var doc = new AceAjax.Document(["1", "2", "3"].join("\r\n")); + + doc.setNewLineMode("auto"); + assert.equal(doc.getValue(), ["1", "2", "3"].join("\r\n")); + + doc.replace(new AceAjax.Range(0, 0, 2, 1), ["4", "5", "6"].join("\n")); + assert.equal(["4", "5", "6"].join("\n"), doc.getValue()); + } , + + "test: set value": function() { + var doc = new AceAjax.Document("1"); + assert.equal("1", doc.getValue()); + + doc.setValue(doc.getValue()); + assert.equal("1", doc.getValue()); + + var doc = new AceAjax.Document("1\n2"); + assert.equal("1\n2", doc.getValue()); + + doc.setValue(doc.getValue()); + assert.equal("1\n2", doc.getValue()); + } +}; \ No newline at end of file diff --git a/ace/tests/ace-edit_session-tests.ts b/ace/tests/ace-edit_session-tests.ts new file mode 100644 index 0000000000..12a3ce5bf3 --- /dev/null +++ b/ace/tests/ace-edit_session-tests.ts @@ -0,0 +1,919 @@ +/// + +var lang: any; + +function createFoldTestSession() { + var lines = [ + "function foo(items) {", + " for (var i=0; i>", [1, 2], 1); + } , + + "test get longest line": function() { + var session = new AceAjax.EditSession(["12"]); + session.setTabSize(4); + assert.equal(session.getScreenWidth(), 2); + + session.doc.insertNewLine({ row: 0, column: Infinity }); + session.doc.insertLines(1, ["123"]); + assert.equal(session.getScreenWidth(), 3); + + session.doc.insertNewLine({ row: 0, column: Infinity }); + session.doc.insertLines(1, ["\t\t"]); + + assert.equal(session.getScreenWidth(), 8); + + session.setTabSize(2); + assert.equal(session.getScreenWidth(), 4); + } , + + "test issue 83": function() { + var session = new AceAjax.EditSession(""); + var editor = new AceAjax.Editor(null, session); + var document = session.getDocument(); + + session.setUseWrapMode(true); + + document.insertLines(0, ["a", "b"]); + document.insertLines(2, ["c", "d"]); + document.removeLines(1, 2); + } , + + "test wrapMode init has to create wrapData array": function() { + var session = new AceAjax.EditSession("foo bar\nfoo bar"); + var editor = new AceAjax.Editor(null, session); + var document = session.getDocument(); + + session.setUseWrapMode(true); + session.setWrapLimitRange(3, 3); + session.adjustWrapLimit(80); + } , + + "test first line blank with wrap": function() { + var session = new AceAjax.EditSession("\nfoo"); + session.setUseWrapMode(true); + assert.equal(session.doc.getValue(), ["", "foo"].join("\n")); + } , + + "test first line blank with wrap 2": function() { + var session = new AceAjax.EditSession(""); + session.setUseWrapMode(true); + session.setValue("\nfoo"); + + assert.equal(session.doc.getValue(), ["", "foo"].join("\n")); + } , + + "test fold getFoldDisplayLine": function() { + var session = createFoldTestSession(); + function assertDisplayLine(foldLine, str) { + var line = session.getLine(foldLine.end.row); + var displayLine = + session.getFoldDisplayLine(foldLine, foldLine.end.row, line.length); + assert.equal(displayLine, str); + } + } , + + "test foldLine idxToPosition": function() { + var session = createFoldTestSession(); + + function assertIdx2Pos(foldLineIdx, idx, row, column) { + var foldLine = null; + assert.position(foldLine.idxToPosition(idx), row, column); + } + + // "function foo(items) {", + // " for (var i=0; i + +exports = { + + setUp: function(next) { + this.session1 = new AceAjax.EditSession(["abc", "def"]); + this.session2 = new AceAjax.EditSession(["ghi", "jkl"]); + + + var editor = new AceAjax.Editor(null); + next(); + } , + + "test: change document": function() { + var editor = new AceAjax.Editor(null); + + editor.setSession(this.session1); + assert.equal(editor.getSession(), this.session1); + + editor.setSession(this.session2); + assert.equal(editor.getSession(), this.session2); + } , + + "test: only changes to the new document should have effect": function () { + var editor = new AceAjax.Editor(null); + + var called = false; + editor.onDocumentChange = function () { + called = true; + }; + + editor.setSession(this.session1); + editor.setSession(this.session2); + + this.session1.duplicateLines(0, 0); + assert.notOk(called); + + this.session2.duplicateLines(0, 0); + assert.ok(called); + } , + + "test: should use cursor of new document": function () { + var editor = new AceAjax.Editor(null); + + this.session1.getSelection().moveCursorTo(0, 1); + this.session2.getSelection().moveCursorTo(1, 0); + + editor.setSession(this.session1); + assert.position(editor.getCursorPosition(), 0, 1); + + editor.setSession(this.session2); + assert.position(editor.getCursorPosition(), 1, 0); + } , + + "test: only changing the cursor of the new doc should not have an effect": function () { + var editor = new AceAjax.Editor(null); + + editor.onCursorChange = function () { + called = true; + }; + + editor.setSession(this.session1); + editor.setSession(this.session2); + assert.position(editor.getCursorPosition(), 0, 0); + + var called = false; + this.session1.getSelection().moveCursorTo(0, 1); + assert.position(editor.getCursorPosition(), 0, 0); + assert.notOk(called); + + this.session2.getSelection().moveCursorTo(1, 1); + assert.position(editor.getCursorPosition(), 1, 1); + assert.ok(called); + } , + + "test: should use selection of new document": function () { + var editor = new AceAjax.Editor(null); + + this.session1.getSelection().selectTo(0, 1); + this.session2.getSelection().selectTo(1, 0); + + editor.setSession(this.session1); + assert.position(editor.getSelection().getSelectionLead(), 0, 1); + + editor.setSession(this.session2); + assert.position(editor.getSelection().getSelectionLead(), 1, 0); + } , + + "test: only changing the selection of the new doc should not have an effect": function () { + var editor = new AceAjax.Editor(null); + + editor.onSelectionChange = function () { + called = true; + }; + + editor.setSession(this.session1); + editor.setSession(this.session2); + assert.position(editor.getSelection().getSelectionLead(), 0, 0); + + var called = false; + this.session1.getSelection().selectTo(0, 1); + assert.position(editor.getSelection().getSelectionLead(), 0, 0); + assert.notOk(called); + + this.session2.getSelection().selectTo(1, 1); + assert.position(editor.getSelection().getSelectionLead(), 1, 1); + assert.ok(called); + } , + + "test: should use mode of new document": function () { + var editor = new AceAjax.Editor(null); + + editor.onChangeMode = function () { + called = true; + }; + editor.setSession(this.session1); + editor.setSession(this.session2); + + var called = false; + this.session1.setMode(new Text()); + assert.notOk(called); + + this.session2.setMode(null); + assert.ok(called); + } , + + "test: should use stop worker of old document": function (next) { + var editor = new AceAjax.Editor(null); + + var self = this; + + // 1. Open an editor and set the session to CssMode + self.editor.setSession(self.session1); + self.session1.setMode(null); + + // 2. Add a line or two of valid CSS. + self.session1.setValue("DIV { color: red; }"); + + // 3. Clear the session value. + self.session1.setValue(""); + + // 4. Set the session to HtmlMode + self.session1.setMode(null); + + // 5. Try to type valid HTML + self.session1.insert({ row: 0, column: 0 }, ""); + + setTimeout(function () { + assert.equal(Object.keys(self.session1.getAnnotations()).length, 0); + next(); + }, 600); + } +}; \ No newline at end of file diff --git a/ace/tests/ace-editor_highlight_selected_word-tests.ts b/ace/tests/ace-editor_highlight_selected_word-tests.ts new file mode 100644 index 0000000000..7e06c8c50c --- /dev/null +++ b/ace/tests/ace-editor_highlight_selected_word-tests.ts @@ -0,0 +1,214 @@ +/// + +var lipsum = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + + "Mauris at arcu mi, eu lobortis mauris. Quisque ut libero eget " + + "diam congue vehicula. Quisque ut odio ut mi aliquam tincidunt. " + + "Duis lacinia aliquam lorem eget eleifend. Morbi eget felis mi. " + + "Duis quam ligula, consequat vitae convallis volutpat, blandit " + + "nec neque. Nulla facilisi. Etiam suscipit lorem ac justo " + + "sollicitudin tristique. Phasellus ut posuere nunc. Aliquam " + + "scelerisque mollis felis non gravida. Vestibulum lacus sem, " + + "posuere non bibendum id, luctus non dolor. Aenean id metus " + + "lorem, vel dapibus est. Donec gravida feugiat augue nec " + + "accumsan.Lorem ipsum dolor sit amet, consectetur adipiscing " + + "elit. Nulla vulputate, velit vitae tincidunt congue, nunc " + + "augue accumsan velit, eu consequat turpis lectus ac orci. " + + "Pellentesque ornare dolor feugiat dui auctor eu varius nulla " + + "fermentum. Sed aliquam odio at velit lacinia vel fermentum " + + "felis sodales. In dignissim magna eget nunc lobortis non " + + "fringilla nibh ullamcorper. Donec facilisis malesuada elit " + + "at egestas. Etiam bibendum, diam vitae tempor aliquet, dui " + + "libero vehicula odio, eget bibendum mauris velit eu lorem.\n" + + "consectetur"; + +function callHighlighterUpdate(session: AceAjax.IEditSession, firstRow: number, lastRow: number) { + var rangeCount = 0; + var mockMarkerLayer = { drawSingleLineMarker: function () { rangeCount++; } } + return rangeCount; +} + +exports = { + setUp: function(next) { + var session = new AceAjax.EditSession(lipsum); + editor = new AceAjax.Editor(new MockRenderer(), session); + var selection = session.getSelection(); + next(); + } , + + "test: highlight selected words by default": function () { + var selection = session.getSelection(); + var session = new AceAjax.EditSession(lipsum); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + assert.equal(editor.getHighlightSelectedWord(), true); + } , + + "test: highlight a word": function () { + var selection = session.getSelection(); + var session = new AceAjax.EditSession(lipsum); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.moveCursorTo(0, 9); + selection.selectWord(); + + var highlighter = null; + assert.ok(highlighter != null); + + var range = selection.getRange(); + assert.equal(session.getTextRange(range), "ipsum"); + assert.equal(highlighter.cache.length, 0); + assert.equal(callHighlighterUpdate(session, 0, 0), 2); + } , + + "test: highlight a word and clear highlight": function () { + var selection = session.getSelection(); + var session = new AceAjax.EditSession(lipsum); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.moveCursorTo(0, 8); + selection.selectWord(); + + var range = selection.getRange(); + assert.equal(session.getTextRange(range), "ipsum"); + assert.equal(callHighlighterUpdate(session, 0, 0), 2); + + session.highlight(""); + assert.equal(callHighlighterUpdate(session, 0, 0), 0); + } , + + "test: highlight another word": function () { + var selection = session.getSelection(); + var session = new AceAjax.EditSession(lipsum); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + selection.moveCursorTo(0, 14); + selection.selectWord(); + + var range = selection.getRange(); + assert.equal(session.getTextRange(range), "dolor"); + assert.equal(callHighlighterUpdate(session, 0, 0), 4); + } , + + "test: no selection, no highlight": function () { + var selection = session.getSelection(); + var session = new AceAjax.EditSession(lipsum); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + selection.clearSelection(); + assert.equal(callHighlighterUpdate(session, 0, 0), 0); + } , + + "test: select a word, no highlight": function () { + var selection = session.getSelection(); + var session = new AceAjax.EditSession(lipsum); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + selection.moveCursorTo(0, 14); + selection.selectWord(); + + editor.setHighlightSelectedWord(false); + + var range = selection.getRange(); + assert.equal(session.getTextRange(range), "dolor"); + assert.equal(callHighlighterUpdate(session, 0, 0), 0); + } , + + "test: select a word with no matches": function () { + var selection = session.getSelection(); + var session = new AceAjax.EditSession(lipsum); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.setHighlightSelectedWord(true); + + var currentOptions = this.search.getOptions(); + var newOptions = { + wrap: true, + wholeWord: true, + caseSensitive: true, + needle: "Mauris" + }; + this.search.set(newOptions); + + var match = this.search.find(session); + assert.notEqual(match, null, "found a match for 'Mauris'"); + + this.search.set(currentOptions); + + selection.setSelectionRange(match); + + assert.equal(session.getTextRange(match), "Mauris"); + assert.equal(callHighlighterUpdate(session, 0, 0), 1); + } , + + "test: partial word selection 1": function () { + var selection = session.getSelection(); + var session = new AceAjax.EditSession(lipsum); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + selection.moveCursorTo(0, 14); + selection.selectWord(); + selection.selectLeft(); + + var range = selection.getRange(); + assert.equal(session.getTextRange(range), "dolo"); + assert.equal(callHighlighterUpdate(session, 0, 0), 0); + } , + + "test: partial word selection 2": function () { + var selection = session.getSelection(); + var session = new AceAjax.EditSession(lipsum); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + selection.moveCursorTo(0, 13); + selection.selectWord(); + selection.selectRight(); + + var range = selection.getRange(); + assert.equal(session.getTextRange(range), "dolor "); + assert.equal(callHighlighterUpdate(session, 0, 0), 0); + } , + + "test: partial word selection 3": function () { + var selection = session.getSelection(); + var session = new AceAjax.EditSession(lipsum); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + selection.moveCursorTo(0, 14); + selection.selectWord(); + selection.selectLeft(); + selection.shiftSelection(1); + + var range = selection.getRange(); + assert.equal(session.getTextRange(range), "olor"); + assert.equal(callHighlighterUpdate(session, 0, 0), 0); + } , + + "test: select last word": function () { + var selection = session.getSelection(); + var session = new AceAjax.EditSession(lipsum); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + selection.moveCursorTo(0, 1); + + var currentOptions = this.search.getOptions(); + var newOptions = { + wrap: true, + wholeWord: true, + caseSensitive: true, + backwards: true, + needle: "consectetur" + }; + this.search.set(newOptions); + + var match = this.search.find(session); + assert.notEqual(match, null, "found a match for 'consectetur'"); + assert.position(match.start, 1, 0); + + this.search.set(currentOptions); + + selection.setSelectionRange(match); + + assert.equal(session.getTextRange(match), "consectetur"); + assert.equal(callHighlighterUpdate(session, 0, 1), 3); + } +}; diff --git a/ace/tests/ace-editor_navigation-tests.ts b/ace/tests/ace-editor_navigation-tests.ts new file mode 100644 index 0000000000..c97ee0cd21 --- /dev/null +++ b/ace/tests/ace-editor_navigation-tests.ts @@ -0,0 +1,117 @@ +/// + +exports = { + createEditSession: function (rows, cols) { + var line = new Array(cols + 1).join("a"); + var text = new Array(rows).join(line + "\n") + line; + return new AceAjax.EditSession(text); + }, + + "test: navigate to end of file should scroll the last line into view": function () { + var doc = this.createEditSession(200, 10); + var editor = new AceAjax.Editor(new MockRenderer(), doc); + + editor.navigateFileEnd(); + var cursor = editor.getCursorPosition(); + + assert.ok(editor.getFirstVisibleRow() <= cursor.row); + assert.ok(editor.getLastVisibleRow() >= cursor.row); + }, + + "test: navigate to start of file should scroll the first row into view": function () { + var doc = this.createEditSession(200, 10); + var editor = new AceAjax.Editor(new MockRenderer(), doc); + + editor.moveCursorTo(editor.getLastVisibleRow() + 20); + editor.navigateFileStart(); + + assert.equal(editor.getFirstVisibleRow(), 0); + }, + + "test: goto hidden line should scroll the line into the middle of the viewport": function () { + var editor = new AceAjax.Editor(new MockRenderer(), this.createEditSession(200, 5)); + + editor.navigateTo(0, 0); + editor.gotoLine(101); + assert.position(editor.getCursorPosition(), 100, 0); + assert.equal(editor.getFirstVisibleRow(), 89); + + editor.navigateTo(100, 0); + editor.gotoLine(11); + assert.position(editor.getCursorPosition(), 10, 0); + assert.equal(editor.getFirstVisibleRow(), 0); + + editor.navigateTo(100, 0); + editor.gotoLine(6); + assert.position(editor.getCursorPosition(), 5, 0); + assert.equal(0, editor.getFirstVisibleRow(), 0); + + editor.navigateTo(100, 0); + editor.gotoLine(1); + assert.position(editor.getCursorPosition(), 0, 0); + assert.equal(editor.getFirstVisibleRow(), 0); + + editor.navigateTo(0, 0); + editor.gotoLine(191); + assert.position(editor.getCursorPosition(), 190, 0); + assert.equal(editor.getFirstVisibleRow(), 179); + + editor.navigateTo(0, 0); + editor.gotoLine(196); + assert.position(editor.getCursorPosition(), 195, 0); + assert.equal(editor.getFirstVisibleRow(), 180); + }, + + "test: goto visible line should only move the cursor and not scroll": function () { + var editor = new AceAjax.Editor(new MockRenderer(), this.createEditSession(200, 5)); + + editor.navigateTo(0, 0); + editor.gotoLine(12); + assert.position(editor.getCursorPosition(), 11, 0); + assert.equal(editor.getFirstVisibleRow(), 0); + + editor.navigateTo(30, 0); + editor.gotoLine(33); + assert.position(editor.getCursorPosition(), 32, 0); + assert.equal(editor.getFirstVisibleRow(), 30); + }, + + "test: navigate from the end of a long line down to a short line and back should maintain the curser column": function () { + var editor = new AceAjax.Editor(new MockRenderer(), new AceAjax.EditSession(["123456", "1"])); + + editor.navigateTo(0, 6); + assert.position(editor.getCursorPosition(), 0, 6); + + editor.navigateDown(); + assert.position(editor.getCursorPosition(), 1, 1); + + editor.navigateUp(); + assert.position(editor.getCursorPosition(), 0, 6); + }, + + "test: reset desired column on navigate left or right": function () { + var editor = new AceAjax.Editor(new MockRenderer(), new AceAjax.EditSession(["123456", "12"])); + + editor.navigateTo(0, 6); + assert.position(editor.getCursorPosition(), 0, 6); + + editor.navigateDown(); + assert.position(editor.getCursorPosition(), 1, 2); + + editor.navigateLeft(); + assert.position(editor.getCursorPosition(), 1, 1); + + editor.navigateUp(); + assert.position(editor.getCursorPosition(), 0, 1); + }, + + "test: typing text should update the desired column": function () { + var editor = new AceAjax.Editor(new MockRenderer(), new AceAjax.EditSession(["1234", "1234567890"])); + + editor.navigateTo(0, 3); + editor.insert("juhu"); + + editor.navigateDown(); + assert.position(editor.getCursorPosition(), 1, 7); + } +}; \ No newline at end of file diff --git a/ace/tests/ace-editor_text_edit-tests.ts b/ace/tests/ace-editor_text_edit-tests.ts new file mode 100644 index 0000000000..9d618acc67 --- /dev/null +++ b/ace/tests/ace-editor_text_edit-tests.ts @@ -0,0 +1,498 @@ +/// + +exports = { + "test: delete line from the middle": function () { + var session = new AceAjax.EditSession(["a", "b", "c", "d"].join("\n")); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.moveCursorTo(1, 1); + editor.removeLines(); + + assert.equal(session.toString(), "a\nc\nd"); + assert.position(editor.getCursorPosition(), 1, 0); + + editor.removeLines(); + + assert.equal(session.toString(), "a\nd"); + assert.position(editor.getCursorPosition(), 1, 0); + + editor.removeLines(); + + assert.equal(session.toString(), "a"); + assert.position(editor.getCursorPosition(), 0, 1); + + editor.removeLines(); + + assert.equal(session.toString(), ""); + assert.position(editor.getCursorPosition(), 0, 0); + }, + + "test: delete multiple selected lines": function () { + var session = new AceAjax.EditSession(["a", "b", "c", "d"].join("\n")); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.moveCursorTo(1, 1); + editor.getSelection().selectDown(); + + editor.removeLines(); + assert.equal(session.toString(), "a\nd"); + assert.position(editor.getCursorPosition(), 1, 0); + }, + + "test: delete first line": function () { + var session = new AceAjax.EditSession(["a", "b", "c"].join("\n")); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.removeLines(); + + assert.equal(session.toString(), "b\nc"); + assert.position(editor.getCursorPosition(), 0, 0); + }, + + "test: delete last should also delete the new line of the previous line": function () { + var session = new AceAjax.EditSession(["a", "b", "c", ""].join("\n")); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.moveCursorTo(3, 0); + + editor.removeLines(); + assert.equal(session.toString(), "a\nb\nc"); + assert.position(editor.getCursorPosition(), 2, 1); + + editor.removeLines(); + assert.equal(session.toString(), "a\nb"); + assert.position(editor.getCursorPosition(), 1, 1); + }, + + "test: indent block": function () { + var session = new AceAjax.EditSession(["a12345", "b12345", "c12345"].join("\n")); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.moveCursorTo(1, 3); + editor.getSelection().selectDown(); + + editor.indent(); + + assert.equal(["a12345", " b12345", " c12345"].join("\n"), session.toString()); + + assert.position(editor.getCursorPosition(), 2, 7); + + var range = editor.getSelectionRange(); + assert.position(range.start, 1, 7); + assert.position(range.end, 2, 7); + }, + + "test: indent selected lines": function () { + var session = new AceAjax.EditSession(["a12345", "b12345", "c12345"].join("\n")); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.moveCursorTo(1, 0); + editor.getSelection().selectDown(); + + editor.indent(); + assert.equal(["a12345", " b12345", "c12345"].join("\n"), session.toString()); + }, + + "test: no auto indent if cursor is before the {": function () { + var session = new AceAjax.EditSession("{", new JavaScriptMode()); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.moveCursorTo(0, 0); + editor.onTextInput("\n"); + assert.equal(["", "{"].join("\n"), session.toString()); + }, + + "test: outdent block": function () { + var session = new AceAjax.EditSession([" a12345", " b12345", " c12345"].join("\n")); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.moveCursorTo(0, 5); + editor.getSelection().selectDown(); + editor.getSelection().selectDown(); + + editor.blockOutdent(); + assert.equal(session.toString(), [" a12345", "b12345", " c12345"].join("\n")); + + assert.position(editor.getCursorPosition(), 2, 1); + + var range = editor.getSelectionRange(); + assert.position(range.start, 0, 1); + assert.position(range.end, 2, 1); + + editor.blockOutdent(); + assert.equal(session.toString(), ["a12345", "b12345", "c12345"].join("\n")); + + var range = editor.getSelectionRange(); + assert.position(range.start, 0, 0); + assert.position(range.end, 2, 0); + }, + + "test: outent without a selection should update cursor": function () { + var session = new AceAjax.EditSession(" 12"); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.moveCursorTo(0, 3); + editor.blockOutdent(" "); + + assert.equal(session.toString(), " 12"); + assert.position(editor.getCursorPosition(), 0, 0); + }, + + "test: comment lines should perserve selection": function () { + var session = new AceAjax.EditSession([" abc", "cde"].join("\n"), new JavaScriptMode()); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.moveCursorTo(0, 2); + editor.getSelection().selectDown(); + editor.toggleCommentLines(); + + assert.equal(["// abc", "//cde"].join("\n"), session.toString()); + + var selection = editor.getSelectionRange(); + assert.position(selection.start, 0, 4); + assert.position(selection.end, 1, 4); + }, + + "test: uncomment lines should perserve selection": function () { + var session = new AceAjax.EditSession(["// abc", "//cde"].join("\n"), new JavaScriptMode()); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.moveCursorTo(0, 1); + editor.getSelection().selectDown(); + editor.getSelection().selectRight(); + editor.getSelection().selectRight(); + + editor.toggleCommentLines(); + + assert.equal([" abc", "cde"].join("\n"), session.toString()); + assert.range(editor.getSelectionRange(), 0, 0, 1, 1); + }, + + "test: toggle comment lines twice should return the original text": function () { + var session = new AceAjax.EditSession([" abc", "cde", "fg"], new JavaScriptMode()); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.moveCursorTo(0, 0); + editor.getSelection().selectDown(); + editor.getSelection().selectDown(); + + editor.toggleCommentLines(); + editor.toggleCommentLines(); + + assert.equal([" abc", "cde", "fg"].join("\n"), session.toString()); + }, + + + "test: comment lines - if the selection end is at the line start it should stay there": function () { + //select down + var session = new AceAjax.EditSession(["abc", "cde"].join("\n"), new JavaScriptMode()); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.moveCursorTo(0, 0); + editor.getSelection().selectDown(); + + editor.toggleCommentLines(); + assert.range(editor.getSelectionRange(), 0, 2, 1, 0); + + // select up + var session = new AceAjax.EditSession(["abc", "cde"].join("\n"), new JavaScriptMode()); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.moveCursorTo(1, 0); + editor.getSelection().selectUp(); + + editor.toggleCommentLines(); + assert.range(editor.getSelectionRange(), 0, 2, 1, 0); + }, + + "test: move lines down should select moved lines": function () { + var session = new AceAjax.EditSession(["11", "22", "33", "44"].join("\n")); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.moveCursorTo(0, 1); + editor.getSelection().selectDown(); + + editor.moveLinesDown(); + assert.equal(["33", "11", "22", "44"].join("\n"), session.toString()); + assert.position(editor.getCursorPosition(), 1, 0); + assert.position(editor.getSelection().getSelectionAnchor(), 3, 0); + assert.position(editor.getSelection().getSelectionLead(), 1, 0); + + editor.moveLinesDown(); + assert.equal(["33", "44", "11", "22"].join("\n"), session.toString()); + assert.position(editor.getCursorPosition(), 2, 0); + assert.position(editor.getSelection().getSelectionAnchor(), 3, 2); + assert.position(editor.getSelection().getSelectionLead(), 2, 0); + + // moving again should have no effect + editor.moveLinesDown(); + assert.equal(["33", "44", "11", "22"].join("\n"), session.toString()); + assert.position(editor.getCursorPosition(), 2, 0); + assert.position(editor.getSelection().getSelectionAnchor(), 3, 2); + assert.position(editor.getSelection().getSelectionLead(), 2, 0); + }, + + "test: move lines up should select moved lines": function () { + var session = new AceAjax.EditSession(["11", "22", "33", "44"].join("\n")); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.moveCursorTo(2, 1); + editor.getSelection().selectDown(); + + editor.moveLinesUp(); + assert.equal(session.toString(), ["11", "33", "44", "22"].join("\n")); + assert.position(editor.getCursorPosition(), 1, 0); + assert.position(editor.getSelection().getSelectionAnchor(), 3, 0); + assert.position(editor.getSelection().getSelectionLead(), 1, 0); + + editor.moveLinesUp(); + assert.equal(session.toString(), ["33", "44", "11", "22"].join("\n")); + assert.position(editor.getCursorPosition(), 0, 0); + assert.position(editor.getSelection().getSelectionAnchor(), 2, 0); + assert.position(editor.getSelection().getSelectionLead(), 0, 0); + }, + + "test: move line without active selection should not move cursor relative to the moved line": function () { + var session = new AceAjax.EditSession(["11", "22", "33", "44"].join("\n")); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.moveCursorTo(1, 1); + editor.clearSelection(); + + editor.moveLinesDown(); + assert.equal(["11", "33", "22", "44"].join("\n"), session.toString()); + assert.position(editor.getCursorPosition(), 2, 1); + + editor.clearSelection(); + + editor.moveLinesUp(); + assert.equal(["11", "22", "33", "44"].join("\n"), session.toString()); + assert.position(editor.getCursorPosition(), 1, 1); + }, + + "test: copy lines down should select lines and place cursor at the selection start": function () { + var session = new AceAjax.EditSession(["11", "22", "33", "44"].join("\n")); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.moveCursorTo(1, 1); + editor.getSelection().selectDown(); + + editor.copyLinesDown(); + assert.equal(["11", "22", "33", "22", "33", "44"].join("\n"), session.toString()); + + assert.position(editor.getCursorPosition(), 3, 0); + assert.position(editor.getSelection().getSelectionAnchor(), 5, 0); + assert.position(editor.getSelection().getSelectionLead(), 3, 0); + }, + + "test: copy lines up should select lines and place cursor at the selection start": function () { + var session = new AceAjax.EditSession(["11", "22", "33", "44"].join("\n")); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.moveCursorTo(1, 1); + editor.getSelection().selectDown(); + + editor.copyLinesUp(); + assert.equal(["11", "22", "33", "22", "33", "44"].join("\n"), session.toString()); + + assert.position(editor.getCursorPosition(), 1, 0); + assert.position(editor.getSelection().getSelectionAnchor(), 3, 0); + assert.position(editor.getSelection().getSelectionLead(), 1, 0); + }, + + "test: input a tab with soft tab should convert it to spaces": function () { + var session = new AceAjax.EditSession(""); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + session.setTabSize(2); + session.setUseSoftTabs(true); + + editor.onTextInput("\t"); + assert.equal(session.toString(), " "); + + session.setTabSize(5); + editor.onTextInput("\t"); + assert.equal(session.toString(), " "); + }, + + "test: input tab without soft tabs should keep the tab character": function () { + var session = new AceAjax.EditSession(""); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + session.setUseSoftTabs(false); + + editor.onTextInput("\t"); + assert.equal(session.toString(), "\t"); + }, + + "test: undo/redo for delete line": function () { + var session = new AceAjax.EditSession(["111", "222", "333"]); + var undoManager = new AceAjax.UndoManager(); + session.setUndoManager(undoManager); + + var initialText = session.toString(); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + editor.removeLines(); + var step1 = session.toString(); + assert.equal(step1, "222\n333"); + + editor.removeLines(); + var step2 = session.toString(); + assert.equal(step2, "333"); + + editor.removeLines(); + var step3 = session.toString(); + assert.equal(step3, ""); + + undoManager.undo(); + assert.equal(session.toString(), step2); + + undoManager.undo(); + assert.equal(session.toString(), step1); + + undoManager.undo(); + assert.equal(session.toString(), initialText); + + undoManager.undo(); + assert.equal(session.toString(), initialText); + }, + + "test: remove left should remove character left of the cursor": function () { + var session = new AceAjax.EditSession(["123", "456"]); + + var editor = new AceAjax.Editor(new MockRenderer(), session); + editor.moveCursorTo(1, 1); + editor.remove("left"); + assert.equal(session.toString(), "123\n56"); + }, + + "test: remove left should remove line break if cursor is at line start": function () { + var session = new AceAjax.EditSession(["123", "456"]); + + var editor = new AceAjax.Editor(new MockRenderer(), session); + editor.moveCursorTo(1, 0); + editor.remove("left"); + assert.equal(session.toString(), "123456"); + }, + + "test: remove left should remove tabsize spaces if cursor is on a tab stop and preceeded by spaces": function () { + var session = new AceAjax.EditSession(["123", " 456"]); + session.setUseSoftTabs(true); + session.setTabSize(4); + + var editor = new AceAjax.Editor(new MockRenderer(), session); + editor.moveCursorTo(1, 8); + editor.remove("left"); + assert.equal(session.toString(), "123\n 456"); + }, + + "test: transpose at line start should be a noop": function () { + var session = new AceAjax.EditSession(["123", "4567", "89"]); + + var editor = new AceAjax.Editor(new MockRenderer(), session); + editor.moveCursorTo(1, 0); + editor.transposeLetters(); + + assert.equal(session.getValue(), ["123", "4567", "89"].join("\n")); + }, + + "test: transpose in line should swap the charaters before and after the cursor": function () { + var session = new AceAjax.EditSession(["123", "4567", "89"]); + + var editor = new AceAjax.Editor(new MockRenderer(), session); + editor.moveCursorTo(1, 2); + editor.transposeLetters(); + + assert.equal(session.getValue(), ["123", "4657", "89"].join("\n")); + }, + + "test: transpose at line end should swap the last two characters": function () { + var session = new AceAjax.EditSession(["123", "4567", "89"]); + + var editor = new AceAjax.Editor(new MockRenderer(), session); + editor.moveCursorTo(1, 4); + editor.transposeLetters(); + + assert.equal(session.getValue(), ["123", "4576", "89"].join("\n")); + }, + + "test: transpose with non empty selection should be a noop": function () { + var session = new AceAjax.EditSession(["123", "4567", "89"]); + + var editor = new AceAjax.Editor(new MockRenderer(), session); + editor.moveCursorTo(1, 1); + editor.getSelection().selectRight(); + editor.transposeLetters(); + + assert.equal(session.getValue(), ["123", "4567", "89"].join("\n")); + }, + + "test: transpose should move the cursor behind the last swapped character": function () { + var session = new AceAjax.EditSession(["123", "4567", "89"]); + + var editor = new AceAjax.Editor(new MockRenderer(), session); + editor.moveCursorTo(1, 2); + editor.transposeLetters(); + assert.position(editor.getCursorPosition(), 1, 3); + }, + + "test: remove to line end": function () { + var session = new AceAjax.EditSession(["123", "4567", "89"]); + + var editor = new AceAjax.Editor(new MockRenderer(), session); + editor.moveCursorTo(1, 2); + editor.removeToLineEnd(); + assert.equal(session.getValue(), ["123", "45", "89"].join("\n")); + }, + + "test: remove to line end at line end should remove the new line": function () { + var session = new AceAjax.EditSession(["123", "4567", "89"]); + + var editor = new AceAjax.Editor(new MockRenderer(), session); + editor.moveCursorTo(1, 4); + editor.removeToLineEnd(); + assert.position(editor.getCursorPosition(), 1, 4); + assert.equal(session.getValue(), ["123", "456789"].join("\n")); + }, + + "test: transform selection to uppercase": function () { + var session = new AceAjax.EditSession(["ajax", "dot", "org"]); + + var editor = new AceAjax.Editor(new MockRenderer(), session); + editor.moveCursorTo(1, 0); + editor.getSelection().selectLineEnd(); + editor.toUpperCase() + assert.equal(session.getValue(), ["ajax", "DOT", "org"].join("\n")); + }, + + "test: transform word to uppercase": function () { + var session = new AceAjax.EditSession(["ajax", "dot", "org"]); + + var editor = new AceAjax.Editor(new MockRenderer(), session); + editor.moveCursorTo(1, 0); + editor.toUpperCase() + assert.equal(session.getValue(), ["ajax", "DOT", "org"].join("\n")); + assert.position(editor.getCursorPosition(), 1, 0); + }, + + "test: transform selection to lowercase": function () { + var session = new AceAjax.EditSession(["AJAX", "DOT", "ORG"]); + + var editor = new AceAjax.Editor(new MockRenderer(), session); + editor.moveCursorTo(1, 0); + editor.getSelection().selectLineEnd(); + editor.toLowerCase() + assert.equal(session.getValue(), ["AJAX", "dot", "ORG"].join("\n")); + }, + + "test: transform word to lowercase": function () { + var session = new AceAjax.EditSession(["AJAX", "DOT", "ORG"]); + + var editor = new AceAjax.Editor(new MockRenderer(), session); + editor.moveCursorTo(1, 0); + editor.toLowerCase() + assert.equal(session.getValue(), ["AJAX", "dot", "ORG"].join("\n")); + assert.position(editor.getCursorPosition(), 1, 0); + } +}; \ No newline at end of file diff --git a/ace/tests/ace-multi_select-tests.ts b/ace/tests/ace-multi_select-tests.ts new file mode 100644 index 0000000000..ade1493e23 --- /dev/null +++ b/ace/tests/ace-multi_select-tests.ts @@ -0,0 +1,111 @@ +/// + +var exec = function (name?, times?, args?) { + do { + editor.commands.exec(name, editor, args); + } while (times-- > 1) +}; +var testRanges = function (str) { + assert.equal(editor.selection.getAllRanges() + "", str + ""); +} + +exports = { + + name: "ACE multi_select.js", + + "test: multiselect editing": function() { + var doc = new AceAjax.EditSession([ + "w1.w2", + " wtt.w", + " wtt.w" + ]); + editor = new AceAjax.Editor(new MockRenderer(), doc); + + editor.navigateFileEnd(); + exec("selectMoreBefore", 3); + assert.ok(editor.inMultiSelectMode); + assert.equal(editor.selection.getAllRanges().length, 4); + + var newLine = editor.session.getDocument().getNewLineCharacter(); + var copyText = "wwww".split("").join(newLine); + assert.equal(editor.getCopyText(), copyText); + exec("insertstring", 1, "a"); + exec("backspace", 2); + assert.equal(editor.session.getValue(), "w1.w2\ntt\ntt"); + assert.equal(editor.selection.getAllRanges().length, 4); + + exec("selectall"); + assert.ok(!editor.inMultiSelectMode); + //assert.equal(editor.selection.getAllRanges().length, 1); + } , + + "test: multiselect navigation": function() { + var doc = new AceAjax.EditSession([ + "w1.w2", + " wtt.w", + " wtt.we" + ]); + editor = new AceAjax.Editor(new MockRenderer(), doc); + + editor.selectMoreLines(1); + testRanges("Range: [0/0] -> [0/0],Range: [1/0] -> [1/0]"); + assert.ok(editor.inMultiSelectMode); + + exec("golinedown"); + exec("gotolineend"); + testRanges("Range: [1/9] -> [1/9],Range: [2/10] -> [2/10]"); + exec("selectwordleft"); + + testRanges("Range: [1/8] -> [1/9],Range: [2/8] -> [2/10]"); + exec("golinedown", 2); + assert.ok(!editor.inMultiSelectMode); + } , + + "test: multiselect session change": function() { + var doc = new AceAjax.EditSession([ + "w1.w2", + " wtt.w", + " wtt.w" + ]); + editor = new AceAjax.Editor(new MockRenderer(), doc); + + editor.selectMoreLines(1) + testRanges("Range: [0/0] -> [0/0],Range: [1/0] -> [1/0]"); + assert.ok(editor.inMultiSelectMode); + + var doc2 = new AceAjax.EditSession(["w1"]); + editor.setSession(doc2); + assert.ok(!editor.inMultiSelectMode); + + editor.setSession(doc); + assert.ok(editor.inMultiSelectMode); + } , + + "test: multiselect addRange": function() { + var doc = new AceAjax.EditSession([ + "w1.w2", + " wtt.w", + " wtt.w" + ]); + editor = new AceAjax.Editor(new MockRenderer(), doc); + + var selection = editor.selection; + + var range1 = new AceAjax.Range(0, 2, 0, 4); + editor.selection.fromOrientedRange(range1); + + var range2 = new AceAjax.Range(0, 3, 0, 4); + selection.addRange(range2); + assert.ok(!editor.inMultiSelectMode); + assert.ok(range2.isEqual(editor.selection.getRange())); + + var range3 = new AceAjax.Range(0, 1, 0, 1); + selection.addRange(range3); + assert.ok(editor.inMultiSelectMode); + testRanges([range3, range2]); + + var range4 = new AceAjax.Range(0, 0, 4, 0); + selection.addRange(range4); + assert.ok(!editor.inMultiSelectMode); + } +}; diff --git a/ace/tests/ace-placeholder-tests.ts b/ace/tests/ace-placeholder-tests.ts new file mode 100644 index 0000000000..124554cf7d --- /dev/null +++ b/ace/tests/ace-placeholder-tests.ts @@ -0,0 +1,106 @@ +/// + +exports = { + + "test: simple at the end appending of text": function () { + var session = new AceAjax.EditSession("var a = 10;\nconsole.log(a, a);", new JavaScriptMode()); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + new AceAjax.PlaceHolder(session, 1, { row: 0, column: 4 }, [{ row: 1, column: 12 }, { row: 1, column: 15 }]); + + editor.moveCursorTo(0, 5); + editor.insert('b'); + assert.equal(session.doc.getValue(), "var ab = 10;\nconsole.log(ab, ab);"); + editor.insert('cd'); + assert.equal(session.doc.getValue(), "var abcd = 10;\nconsole.log(abcd, abcd);"); + editor.remove('left'); + editor.remove('left'); + editor.remove('left'); + assert.equal(session.doc.getValue(), "var a = 10;\nconsole.log(a, a);"); + }, + + "test: inserting text outside placeholder": function () { + var session = new AceAjax.EditSession("var a = 10;\nconsole.log(a, a);\n", new JavaScriptMode()); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + new AceAjax.PlaceHolder(session, 1, { row: 0, column: 4 }, [{ row: 1, column: 12 }, { row: 1, column: 15 }]); + + editor.moveCursorTo(2, 0); + editor.insert('b'); + assert.equal(session.doc.getValue(), "var a = 10;\nconsole.log(a, a);\nb"); + }, + + "test: insertion at the beginning": function (next) { + var session = new AceAjax.EditSession("var a = 10;\nconsole.log(a, a);", new JavaScriptMode()); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + var p = new AceAjax.PlaceHolder(session, 1, { row: 0, column: 4 }, [{ row: 1, column: 12 }, { row: 1, column: 15 }]); + + editor.moveCursorTo(0, 4); + editor.insert('$'); + assert.equal(session.doc.getValue(), "var $a = 10;\nconsole.log($a, $a);"); + editor.moveCursorTo(0, 4); + // Have to put this in a setTimeout because the anchor is only fixed later. + setTimeout(function () { + editor.insert('v'); + assert.equal(session.doc.getValue(), "var v$a = 10;\nconsole.log(v$a, v$a);"); + next(); + }, 10); + }, + + "test: detaching placeholder": function () { + var session = new AceAjax.EditSession("var a = 10;\nconsole.log(a, a);", new JavaScriptMode()); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + var p = new AceAjax.PlaceHolder(session, 1, { row: 0, column: 4 }, [{ row: 1, column: 12 }, { row: 1, column: 15 }]); + + editor.moveCursorTo(0, 5); + editor.insert('b'); + assert.equal(session.doc.getValue(), "var ab = 10;\nconsole.log(ab, ab);"); + p.detach(); + editor.insert('cd'); + assert.equal(session.doc.getValue(), "var abcd = 10;\nconsole.log(ab, ab);"); + }, + + "test: events": function () { + var session = new AceAjax.EditSession("var a = 10;\nconsole.log(a, a);", new JavaScriptMode()); + var editor = new AceAjax.Editor(new MockRenderer(), session); + + var p = new AceAjax.PlaceHolder(session, 1, { row: 0, column: 4 }, [{ row: 1, column: 12 }, { row: 1, column: 15 }]); + var entered = false; + var left = false; + p.on("cursorEnter", function () { + entered = true; + }); + p.on("cursorLeave", function () { + left = true; + }); + + editor.moveCursorTo(0, 0); + editor.moveCursorTo(0, 4); + p.onCursorChange(); // Have to do this by hand because moveCursorTo doesn't trigger the event + assert.ok(entered); + editor.moveCursorTo(1, 0); + p.onCursorChange(); // Have to do this by hand because moveCursorTo doesn't trigger the event + assert.ok(left); + }, + + "test: cancel": function (next) { + var session = new AceAjax.EditSession("var a = 10;\nconsole.log(a, a);", new JavaScriptMode()); + session.setUndoManager(new AceAjax.UndoManager()); + var editor = new AceAjax.Editor(new MockRenderer(), session); + var p = new AceAjax.PlaceHolder(session, 1, { row: 0, column: 4 }, [{ row: 1, column: 12 }, { row: 1, column: 15 }]); + + editor.moveCursorTo(0, 5); + editor.insert('b'); + editor.insert('cd'); + editor.remove('left'); + assert.equal(session.doc.getValue(), "var abc = 10;\nconsole.log(abc, abc);"); + // Wait a little for the changes to enter the undo stack + setTimeout(function () { + p.cancel(); + assert.equal(session.doc.getValue(), "var a = 10;\nconsole.log(a, a);"); + next(); + }, 80); + } +}; diff --git a/ace/tests/ace-range_list-tests.ts b/ace/tests/ace-range_list-tests.ts new file mode 100644 index 0000000000..83f3c8a91c --- /dev/null +++ b/ace/tests/ace-range_list-tests.ts @@ -0,0 +1,117 @@ +/// + +function flatten(rangeList) { + var points = []; + rangeList.ranges.forEach(function (r) { + points.push(r.start.row, r.start.column, r.end.row, r.end.column) + }) + return points; +} +function testRangeList(rangeList, points) { + assert.equal("" + flatten(rangeList), "" + points); +} + +exports = { + + name: "ACE range_list.js", + + "test: rangeList pointIndex": function() { + var rangeList = new AceAjax.RangeList(); + rangeList.ranges = [ + new AceAjax.Range(1, 2, 3, 4), + new AceAjax.Range(4, 2, 5, 4), + new AceAjax.Range(8, 8, 9, 9) + ]; + + assert.equal(rangeList.pointIndex({ row: 0, column: 1 }), -1); + assert.equal(rangeList.pointIndex({ row: 1, column: 2 }), 0); + assert.equal(rangeList.pointIndex({ row: 1, column: 3 }), 0); + assert.equal(rangeList.pointIndex({ row: 3, column: 4 }), 0); + assert.equal(rangeList.pointIndex({ row: 4, column: 1 }), -2); + assert.equal(rangeList.pointIndex({ row: 5, column: 1 }), 1); + assert.equal(rangeList.pointIndex({ row: 8, column: 9 }), 2); + assert.equal(rangeList.pointIndex({ row: 18, column: 9 }), -4); + } , + + "test: rangeList add": function() { + var rangeList = new AceAjax.RangeList(); + rangeList.addList([ + new AceAjax.Range(9, 0, 9, 1), + new AceAjax.Range(1, 2, 3, 4), + new AceAjax.Range(8, 8, 9, 9), + new AceAjax.Range(4, 2, 5, 4), + new AceAjax.Range(3, 20, 3, 24), + new AceAjax.Range(6, 6, 7, 7) + ]); + assert.equal(rangeList.ranges.length, 5); + + rangeList.add(new AceAjax.Range(1, 2, 3, 5)); + assert.range(rangeList.ranges[0], 1, 2, 3, 5); + assert.equal(rangeList.ranges.length, 5); + + rangeList.add(new AceAjax.Range(7, 7, 7, 7)); + assert.range(rangeList.ranges[3], 7, 7, 7, 7); + rangeList.add(new AceAjax.Range(7, 8, 7, 8)); + assert.range(rangeList.ranges[4], 7, 8, 7, 8); + } , + + "test: rangeList add empty": function() { + var rangeList = new AceAjax.RangeList(); + rangeList.addList([ + new AceAjax.Range(7, 10, 7, 10), + new AceAjax.Range(9, 10, 9, 10), + new AceAjax.Range(8, 10, 8, 10) + ]); + assert.equal(rangeList.ranges.length, 3); + + rangeList.add(new AceAjax.Range(9, 10, 9, 10)); + testRangeList(rangeList, [7, 10, 7, 10, 8, 10, 8, 10, 9, 10, 9, 10]); + } , + + "test: rangeList merge": function() { + var rangeList = new AceAjax.RangeList(); + rangeList.addList([ + new AceAjax.Range(1, 2, 3, 4), + new AceAjax.Range(4, 2, 5, 4), + new AceAjax.Range(6, 6, 7, 7), + new AceAjax.Range(8, 8, 9, 9) + ]); + var removed = []; + + assert.equal(rangeList.ranges.length, 4); + + rangeList.ranges[1].end.row = 7; + removed = rangeList.merge(); + assert.equal(removed.length, 1); + assert.range(rangeList.ranges[1], 4, 2, 7, 7); + assert.equal(rangeList.ranges.length, 3); + + rangeList.ranges[0].end.row = 10; + removed = rangeList.merge(); + assert.range(rangeList.ranges[0], 1, 2, 10, 4); + assert.equal(removed.length, 2); + assert.equal(rangeList.ranges.length, 1); + + rangeList.ranges.push(new AceAjax.Range(10, 10, 10, 10)); + rangeList.ranges.push(new AceAjax.Range(10, 10, 10, 10)); + removed = rangeList.merge(); + assert.equal(rangeList.ranges.length, 2); + } , + + "test: rangeList remove": function() { + var rangeList = new AceAjax.RangeList(); + var list = [ + new AceAjax.Range(1, 2, 3, 4), + new AceAjax.Range(4, 2, 5, 4), + new AceAjax.Range(6, 6, 7, 7), + new AceAjax.Range(8, 8, 9, 9) + ]; + rangeList.addList(list); + assert.equal(rangeList.ranges.length, 4); + rangeList.substractPoint({ row: 1, column: 2 }); + assert.equal(rangeList.ranges.length, 3); + rangeList.substractPoint({ row: 6, column: 7 }); + assert.equal(rangeList.ranges.length, 2); + } + +};