diff --git a/README.md b/README.md index 1545092..19b80cc 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,10 @@ Before you create a pull request, please check whether your commits comply with - refactor: any code related change that is not a fix nor a feature - chore: all changes to the repository that do not fit into any of the above categories +### Test + +To run the test, execute the command `pnpm test` + ### Release - Checkout from the latest main branch. diff --git a/packages/core/src/test/cache.test.ts b/packages/core/src/test/cache.test.ts index da23f4a..a842f81 100644 --- a/packages/core/src/test/cache.test.ts +++ b/packages/core/src/test/cache.test.ts @@ -1,26 +1,36 @@ import { createSQLEditorInstance, EditorCache } from '..' -test('editor instance cache works fine', () => { +describe('editor instance cache works fine', () => { const cache = new EditorCache() const editorInst = createSQLEditorInstance({ editorId: '111', doc: 'select * from test;' }) - expect(cache.getEditor('111')).toBe(undefined) + test('no cache added', () => { + expect(cache.getEditor('111')).toBe(undefined) + }) - cache.addEditor('111', editorInst) - expect(cache.getEditor('111')).toBe(editorInst) + test('add one instance 111 to cache', () => { + cache.addEditor('111', editorInst) + expect(cache.getEditor('111')).toBe(editorInst) + }) - cache.deleteEditor('222') - expect(cache.getEditor('111')).toBe(editorInst) + test('remove instance 222 from cache', () => { + cache.deleteEditor('222') + expect(cache.getEditor('111')).toBe(editorInst) + }) - cache.deleteEditor('111') - expect(cache.getEditor('111')).toBe(undefined) + test('remove instance 111 from cache', () => { + cache.deleteEditor('111') + expect(cache.getEditor('111')).toBe(undefined) + }) - cache.addEditor('111', editorInst) - expect(cache.getEditor('111')).toBe(editorInst) + test('clear cache', () => { + cache.addEditor('111', editorInst) + expect(cache.getEditor('111')).toBe(editorInst) - cache.clearEditors() - expect(cache.getEditor('111')).toBe(undefined) + cache.clearEditors() + expect(cache.getEditor('111')).toBe(undefined) + }) }) diff --git a/packages/core/src/test/instance.test.ts b/packages/core/src/test/instance.test.ts index 80b4f6a..2753902 100644 --- a/packages/core/src/test/instance.test.ts +++ b/packages/core/src/test/instance.test.ts @@ -9,56 +9,94 @@ ORDER BY sector, companies DESC;` const DOC = `\n${LINE_1}\n\n${LINE_2}\n\n` -test('editor instance works fine', () => { - const editorInst = createSQLEditorInstance({ - editorId: '111', - doc: DOC +describe('editor instance works fine', () => { + let editorInst + + beforeAll(() => { + editorInst = createSQLEditorInstance({ + editorId: '111', + doc: DOC + }) }) - expect(editorInst.editorId).toBe('111') + test('editorId should be correct', () => + expect(editorInst.editorId).toBe('111')) - editorInst.editorView.dispatch({ selection: { anchor: 0, head: 0 } }) + describe('dispatch a empty selection action', () => { + let curSql, nearbySql, allSql - const allSql = editorInst.getAllStatements() - expect(allSql.length).toBe(2) - expect(allSql[0].content).toBe(LINE_1) - expect(allSql[1].content).toBe(LINE_2) + beforeAll(() => { + editorInst.editorView.dispatch({ selection: { anchor: 0, head: 0 } }) + curSql = editorInst.getCurStatements() + nearbySql = editorInst.getNearbyStatement() + allSql = editorInst.getAllStatements() + }) - let curSql = editorInst.getCurStatements() - expect(curSql[0].content).toBe('') + test('the content and length of statement is correct', () => { + expect(allSql.length).toBe(2) + expect(allSql[0].content).toBe(LINE_1) + expect(allSql[1].content).toBe(LINE_2) + }) - let nearbySql = editorInst.getNearbyStatement() - expect(nearbySql?.content).toBe(LINE_1) + test('current sql is empty', () => { + expect(curSql[0].content).toBe('') + }) - editorInst.editorView.dispatch({ - selection: { anchor: 1, head: 2 } + test('nearby sql is line1', () => { + expect(nearbySql?.content).toBe(LINE_1) + }) }) - curSql = editorInst.getCurStatements() - expect(curSql[0].content).toBe(LINE_1) - - nearbySql = editorInst.getNearbyStatement() - expect(nearbySql?.content).toBe(LINE_1) - - editorInst.editorView.dispatch({ - selection: { anchor: DOC.length, head: DOC.length } + describe('dispatch a selection action', () => { + let curSql, nearbySql + + beforeAll(() => { + editorInst.editorView.dispatch({ + selection: { anchor: 1, head: 2 } + }) + curSql = editorInst.getCurStatements() + nearbySql = editorInst.getNearbyStatement() + }) + + test('current sql is line1, nearby sql is line1', () => { + expect(curSql[0].content).toBe(LINE_1) + expect(nearbySql?.content).toBe(LINE_1) + }) }) - curSql = editorInst.getCurStatements() - expect(curSql[0].content).toBe('') - - nearbySql = editorInst.getNearbyStatement() - expect(nearbySql?.content).toBe(LINE_2) - - editorInst.editorView.dispatch({ - selection: { anchor: 2, head: 2 + LINE_1.length + 5 } + describe('dispatch a selection action', () => { + let curSql, nearbySql + + beforeAll(() => { + editorInst.editorView.dispatch({ + selection: { anchor: DOC.length, head: DOC.length } + }) + curSql = editorInst.getCurStatements() + nearbySql = editorInst.getNearbyStatement() + }) + + test('current sql is empty, nearby sql is line2', () => { + expect(curSql[0].content).toBe('') + expect(nearbySql?.content).toBe(LINE_2) + }) }) - curSql = editorInst.getCurStatements() - expect(curSql.length).toBe(2) - expect(curSql[0].content).toBe(LINE_1) - expect(curSql[1].content).toBe(LINE_2) - - nearbySql = editorInst.getNearbyStatement() - expect(nearbySql?.content).toBe(LINE_1) + describe('dispatch a selection action', () => { + let curSql, nearbySql + + beforeAll(() => { + editorInst.editorView.dispatch({ + selection: { anchor: 2, head: 2 + LINE_1.length + 5 } + }) + curSql = editorInst.getCurStatements() + nearbySql = editorInst.getNearbyStatement() + }) + + test('current sql length is 2, nearby sql is line1', () => { + expect(curSql.length).toBe(2) + expect(curSql[0].content).toBe(LINE_1) + expect(curSql[1].content).toBe(LINE_2) + expect(nearbySql?.content).toBe(LINE_1) + }) + }) }) diff --git a/packages/extensions/cur-sql/src/test/cursql.test.ts b/packages/extensions/cur-sql/src/test/cursql.test.ts index b29dea6..c331a98 100644 --- a/packages/extensions/cur-sql/src/test/cursql.test.ts +++ b/packages/extensions/cur-sql/src/test/cursql.test.ts @@ -16,22 +16,31 @@ LIMIT const DOC = `${LINE_1}\n${LINE_2}` -test('test getCurStatements', () => { - const editorView = new EditorView({ - state: EditorState.create({ - doc: DOC, - extensions: [sqlParser(), sql({ dialect: MySQL }), curSql()] +describe('test getCurStatements', () => { + let editorView: EditorView = new EditorView() + + beforeAll(() => { + editorView = new EditorView({ + state: EditorState.create({ + doc: DOC, + extensions: [sqlParser(), sql({ dialect: MySQL }), curSql()] + }) }) }) - editorView.dispatch({ selection: { anchor: 0, head: 0 } }) + test('select 0 to 0, the firstSqlStatement should to be LINE_1', () => { + editorView.dispatch({ selection: { anchor: 0, head: 0 } }) - const firstSqlStatement = getCurStatements(editorView.state) - expect(firstSqlStatement[0].content).toBe(LINE_1) + const firstSqlStatement = getCurStatements(editorView.state) + expect(firstSqlStatement[0].content).toBe(LINE_1) + }) + + test('select from DOC.length to DOC.length, the lastSqlStatement should to be LINE_2', () => { + editorView.dispatch({ + selection: { anchor: DOC.length, head: DOC.length } + }) - editorView.dispatch({ - selection: { anchor: DOC.length, head: DOC.length } + const lastSqlStatement = getCurStatements(editorView.state) + expect(lastSqlStatement[0].content).toBe(LINE_2) }) - const lastSqlStatement = getCurStatements(editorView.state) - expect(lastSqlStatement[0].content).toBe(LINE_2) }) diff --git a/packages/extensions/events/src/test/doc-change.test.ts b/packages/extensions/events/src/test/doc-change.test.ts index 225a0c5..988ed67 100644 --- a/packages/extensions/events/src/test/doc-change.test.ts +++ b/packages/extensions/events/src/test/doc-change.test.ts @@ -13,25 +13,50 @@ LIMIT const DOC = `${LINE_1}\n${LINE_2}` -test('test change event', () => { - let doc = '' - - const editorView = new EditorView({ - state: EditorState.create({ - doc: '', - extensions: [ - onDocChange((_view, content) => { - doc = content +describe('test change event', () => { + describe('a empty doc, insert LINE_1', () => { + let doc = '', + editorView: EditorView = new EditorView() + + beforeAll(() => { + editorView = new EditorView({ + state: EditorState.create({ + doc: '', + extensions: [ + onDocChange((_view, content) => { + doc = content + }) + ] }) - ] + }) + + editorView.dispatch({ changes: { from: 0, insert: LINE_1 } }) }) + + test('doc should to be LINE_1', () => expect(doc).toBe(LINE_1)) }) - editorView.dispatch({ changes: { from: 0, insert: LINE_1 } }) - expect(doc).toBe(LINE_1) + describe('a doc has LINE_1 and insert LINE_2 after LINE_1', () => { + let doc = '', + editorView: EditorView = new EditorView() + + beforeAll(() => { + editorView = new EditorView({ + state: EditorState.create({ + doc: LINE_1, + extensions: [ + onDocChange((_view, content) => { + doc = content + }) + ] + }) + }) + + editorView.dispatch({ + changes: { from: LINE_1.length, insert: `\n${LINE_2}` } + }) + }) - editorView.dispatch({ - changes: { from: LINE_1.length, insert: `\n${LINE_2}` } + test('doc should to be DOC', () => expect(doc).toBe(DOC)) }) - expect(doc).toBe(DOC) }) diff --git a/packages/extensions/events/src/test/selection-change.test.ts b/packages/extensions/events/src/test/selection-change.test.ts index e242c4d..15e7399 100644 --- a/packages/extensions/events/src/test/selection-change.test.ts +++ b/packages/extensions/events/src/test/selection-change.test.ts @@ -3,8 +3,6 @@ import { EditorState } from '@codemirror/state' import { onSelectionChange, SelectionRange } from '..' -jest.useFakeTimers() - const LINE_1 = 'USE game;' const LINE_2 = `SELECT * @@ -15,31 +13,44 @@ LIMIT const DOC = `${LINE_1}\n${LINE_2}` -test('test selection change event', async () => { +describe('test selection change event', () => { let selRanges: SelectionRange[] = [] - - const editorView = new EditorView({ - state: EditorState.create({ - doc: '', - extensions: [ - onSelectionChange((_view, ranges) => { - selRanges = ranges - }) - ] + let editorView: EditorView = new EditorView() + + beforeAll(() => { + jest.useFakeTimers() + + editorView = new EditorView({ + state: EditorState.create({ + doc: '', + extensions: [ + onSelectionChange((_view, ranges) => { + selRanges = ranges + }) + ] + }) }) + + editorView.dispatch({ changes: { from: 0, insert: DOC } }) }) - editorView.dispatch({ changes: { from: 0, insert: DOC } }) + afterAll(() => jest.useRealTimers()) + + test('select 0 to LINE_1.length, the selectionRange is correct', async () => { + editorView.dispatch({ selection: { anchor: 0, head: LINE_1.length } }) + await jest.advanceTimersByTime(100) - editorView.dispatch({ selection: { anchor: 0, head: LINE_1.length } }) - await jest.advanceTimersByTime(100) - expect(selRanges[0].from).toBe(0) - expect(selRanges[0].to).toBe(LINE_1.length) + expect(selRanges[0].from).toBe(0) + expect(selRanges[0].to).toBe(LINE_1.length) + }) + + test('select LINE_1.length to DOC.length, the selectionRange is correct', async () => { + editorView.dispatch({ + selection: { anchor: LINE_1.length, head: DOC.length } + }) + await jest.advanceTimersByTime(100) - editorView.dispatch({ - selection: { anchor: LINE_1.length, head: DOC.length } + expect(selRanges[0].from).toBe(LINE_1.length) + expect(selRanges[0].to).toBe(DOC.length) }) - await jest.advanceTimersByTime(100) - expect(selRanges[0].from).toBe(LINE_1.length) - expect(selRanges[0].to).toBe(DOC.length) }) diff --git a/packages/extensions/linters/src/test/full-width-char-linter.test.ts b/packages/extensions/linters/src/test/full-width-char-linter.test.ts index 26c5977..f5f14d1 100644 --- a/packages/extensions/linters/src/test/full-width-char-linter.test.ts +++ b/packages/extensions/linters/src/test/full-width-char-linter.test.ts @@ -7,36 +7,49 @@ import { sqlParser } from '@tidbcloud/codemirror-extension-sql-parser' import { fullWidthCharLinter } from '..' -jest.useFakeTimers() - const LINE_1 = 'SELECT * from test LIMIT 1;\n' const LINE_2 = 'USE game;\n' -test('test full width char linter', async () => { - const container = document.createElement('div') - container.style.height = '100px' - const editorView = new EditorView({ - state: EditorState.create({ - doc: '', - extensions: [sql({ dialect: MySQL }), sqlParser(), fullWidthCharLinter()] - }), - parent: container +describe('test full width char linter', () => { + let container: HTMLDivElement, + editorView: EditorView = new EditorView() + + beforeAll(() => { + jest.useFakeTimers() + + container = document.createElement('div') + container.style.height = '100px' + + editorView = new EditorView({ + state: EditorState.create({ + doc: '', + extensions: [ + sql({ dialect: MySQL }), + sqlParser(), + fullWidthCharLinter() + ] + }), + parent: container + }) + }) + + afterAll(() => jest.useRealTimers()) + + test('add LINE_1', async () => { + editorView.dispatch({ changes: { from: 0, insert: LINE_1 } }) + await jest.advanceTimersByTime(1000) + expect(diagnosticCount(editorView.state)).toBe(0) }) - editorView.dispatch({ changes: { from: 0, insert: LINE_1 } }) - await jest.advanceTimersByTime(1000) - expect(diagnosticCount(editorView.state)).toBe(0) - - // dispatch changes transaction to make `diagnosticCount(editorView.state)` update - editorView.dispatch({ changes: { from: LINE_1.length, insert: LINE_2 } }) - await jest.advanceTimersByTime(1000) - // TODO: fix - // don't why, diagnosticCount should expect to be 1, but always get 0 - // expect(diagnosticCount(editorView.state)).toBe(1) - expect(diagnosticCount(editorView.state)).toBe(0) - forEachDiagnostic(editorView.state, (d, from, to) => { - expect(d.severity).toBe('error') - expect(from).toBe(26) - expect(to).toBe(27) + test('add LINE_2 after LINE_1', async () => { + // dispatch changes transaction to make `diagnosticCount(editorView.state)` update + editorView.dispatch({ changes: { from: LINE_1.length, insert: LINE_2 } }) + await jest.advanceTimersByTime(1000) + expect(diagnosticCount(editorView.state)).toBe(1) + forEachDiagnostic(editorView.state, (d, from, to) => { + expect(d.severity).toBe('error') + expect(from).toBe(26) + expect(to).toBe(27) + }) }) }) diff --git a/packages/extensions/linters/src/test/use-db-linter.test.ts b/packages/extensions/linters/src/test/use-db-linter.test.ts index 0d49660..f3dfb94 100644 --- a/packages/extensions/linters/src/test/use-db-linter.test.ts +++ b/packages/extensions/linters/src/test/use-db-linter.test.ts @@ -7,36 +7,48 @@ import { sqlParser } from '@tidbcloud/codemirror-extension-sql-parser' import { useDbLinter } from '..' -jest.useFakeTimers() - const LINE_1 = 'SELECT * from test LIMIT 1;\n' const LINE_2 = 'USE game;\n' -test('test usb db linter', async () => { - const container = document.createElement('div') - container.style.height = '100px' - const editorView = new EditorView({ - state: EditorState.create({ - doc: '', - extensions: [sql({ dialect: MySQL }), sqlParser(), useDbLinter()] - }), - parent: container +describe('test usb db linter', () => { + let container: HTMLDivElement, + editorView: EditorView = new EditorView() + + beforeAll(() => { + jest.useFakeTimers() + + container = document.createElement('div') + container.style.height = '100px' + + editorView = new EditorView({ + state: EditorState.create({ + doc: '', + extensions: [sql({ dialect: MySQL }), sqlParser(), useDbLinter()] + }), + parent: container + }) }) - editorView.dispatch({ changes: { from: 0, insert: LINE_1 } }) - await jest.advanceTimersByTime(1000) - expect(diagnosticCount(editorView.state)).toBe(0) - - // dispatch changes transaction to make `diagnosticCount(editorView.state)` update - editorView.dispatch({ changes: { from: LINE_1.length, insert: LINE_2 } }) - await jest.advanceTimersByTime(1000) - // TODO: fix - // don't why, diagnosticCount should expect to be 1, but always get 0 - // expect(diagnosticCount(editorView.state)).toBe(1) - expect(diagnosticCount(editorView.state)).toBe(0) - forEachDiagnostic(editorView.state, (d, from, to) => { - expect(d.severity).toBe('warning') - expect(from).toBe(0) - expect(to).toBe(LINE_1.length) + afterAll(() => jest.useRealTimers()) + + test('add LINE_1', async () => { + editorView.dispatch({ changes: { from: 0, insert: LINE_1 } }) + await jest.advanceTimersByTime(1000) + + expect(diagnosticCount(editorView.state)).toBe(0) + }) + + test('add LINE_2 after LINE_1', async () => { + // dispatch changes transaction to make `diagnosticCount(editorView.state)` update + editorView.dispatch({ changes: { from: LINE_1.length, insert: LINE_2 } }) + await jest.advanceTimersByTime(1000) + + expect(diagnosticCount(editorView.state)).toBe(1) + forEachDiagnostic(editorView.state, (d, from, to) => { + expect(d.severity).toBe('warning') + expect(from).toBe(0) + // i feel the length shouldn't inlcude '\n' + expect(to).toBe(LINE_1.length - 1) + }) }) }) diff --git a/packages/extensions/save-helper/src/test/1.test.ts b/packages/extensions/save-helper/src/test/1.test.ts deleted file mode 100644 index 1fdd31d..0000000 --- a/packages/extensions/save-helper/src/test/1.test.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { EditorView } from '@codemirror/view' -import { EditorState } from '@codemirror/state' - -import { saveHelper } from '..' - -const LINE_1 = `USE sp500insight;` -const LINE_2 = `SELECT * from companies LIMIT 10;` - -const INIT_DOC = `\n${LINE_1}\n\n` - -jest.useFakeTimers() - -test('test auto save after content changes without any delay', async () => { - let latestContent = '' - const editorView = new EditorView({ - state: EditorState.create({ - doc: INIT_DOC, - extensions: [ - saveHelper({ - save(view) { - latestContent = view.state.doc.toString() - }, - delay: 0 - }) - ] - }) - }) - - // dispatch a change transaction to update the content - editorView.dispatch({ changes: { from: 0, insert: LINE_2 } }) - - expect(latestContent).toBe(``) - - await jest.advanceTimersByTime(0) - expect(latestContent).toBe(`${LINE_2}${INIT_DOC}`) -}) - -test('test auto save after content changes without 1s delay', async () => { - let latestContent = '' - const editorView = new EditorView({ - state: EditorState.create({ - doc: INIT_DOC, - extensions: [ - saveHelper({ - save(view) { - latestContent = view.state.doc.toString() - }, - delay: 1000 - }) - ] - }) - }) - - // dispatch a change transaction to update the content - editorView.dispatch({ changes: { from: 0, insert: LINE_2 } }) - - expect(latestContent).toBe(``) - - await jest.advanceTimersByTime(100) - expect(latestContent).toBe(``) - - await jest.advanceTimersByTime(1000) - expect(latestContent).toBe(`${LINE_2}${INIT_DOC}`) -}) - -test('test turn off auto save', async () => { - let latestContent = '' - const editorView = new EditorView({ - state: EditorState.create({ - doc: INIT_DOC, - extensions: [ - saveHelper({ - auto: false, - save(view) { - latestContent = view.state.doc.toString() - }, - delay: 0 - }) - ] - }) - }) - - // dispatch a change transaction to update the content - editorView.dispatch({ changes: { from: 0, insert: LINE_2 } }) - - await jest.advanceTimersByTime(100) - expect(latestContent).toBe(``) -}) - -test('test manual save with default hotkey', () => { - let latestContent = '' - const editorView = new EditorView({ - state: EditorState.create({ - doc: INIT_DOC, - extensions: [ - saveHelper({ - auto: false, - save(view) { - latestContent = view.state.doc.toString() - } - }) - ] - }) - }) - - // dispatch a change transaction to update the content - editorView.dispatch({ changes: { from: 0, insert: LINE_2 } }) - - // TODO - // press Mod-s - - expect(latestContent).toBe(``) -}) - -test('test manual save with a non-default hotkey', () => { - let latestContent = '' - const editorView = new EditorView({ - state: EditorState.create({ - doc: INIT_DOC, - extensions: [ - saveHelper({ - auto: false, - hotkey: 'Mod-i', - save(view) { - latestContent = view.state.doc.toString() - } - }) - ] - }) - }) - - // dispatch a change transaction to update the content - editorView.dispatch({ changes: { from: 0, insert: LINE_2 } }) - - // TODO - // press Mod-i - - expect(latestContent).toBe(``) -}) - -test('test turn off manual save', () => { - let latestContent = '' - const editorView = new EditorView({ - state: EditorState.create({ - doc: INIT_DOC, - extensions: [ - saveHelper({ - auto: false, - hotkey: '', - save(view) { - latestContent = view.state.doc.toString() - } - }) - ] - }) - }) - - // dispatch a change transaction to update the content - editorView.dispatch({ changes: { from: 0, insert: LINE_2 } }) - - // TODO - // press Mod-i - - expect(latestContent).toBe(``) -}) diff --git a/packages/extensions/save-helper/src/test/save.test.ts b/packages/extensions/save-helper/src/test/save.test.ts new file mode 100644 index 0000000..65dc857 --- /dev/null +++ b/packages/extensions/save-helper/src/test/save.test.ts @@ -0,0 +1,89 @@ +import { EditorView } from '@codemirror/view' +import { EditorState } from '@codemirror/state' + +import { saveHelper } from '..' + +const LINE_1 = `USE sp500insight;` +const LINE_2 = `SELECT * from companies LIMIT 10;` + +const INIT_DOC = `\n${LINE_1}\n\n` + +describe.each([ + { delay: 0, auto: true, expected: `${LINE_2}${INIT_DOC}` }, + { delay: 1000, auto: true, expected: `${LINE_2}${INIT_DOC}` }, + { delay: 0, auto: false, expected: '' } +])('test auto save', ({ delay, auto, expected }) => { + let latestContent = '', + editorView + + beforeAll(() => { + jest.useFakeTimers() + editorView = new EditorView({ + state: EditorState.create({ + doc: INIT_DOC, + extensions: [ + saveHelper({ + auto, + save(view) { + latestContent = view.state.doc.toString() + }, + delay + }) + ] + }) + }) + + editorView.dispatch({ changes: { from: 0, insert: LINE_2 } }) + }) + + afterAll(() => { + jest.useRealTimers() + }) + + test('content should be empty', () => { + expect(latestContent).toBe('') + }) + + if (delay > 0) { + test('wait for half specfic millseconds, content should be empty', async () => { + await jest.advanceTimersByTime(delay / 2) + expect(latestContent).toBe('') + }) + } + + test('wait for specfic millseconds, content should be equal to expected value', async () => { + await jest.advanceTimersByTime(delay) + expect(latestContent).toBe(expected) + }) +}) + +describe.each([{ hotkey: undefined }, { hotkey: 'Mod-i' }, { hotkey: '' }])( + 'test manual save', + ({ hotkey }) => { + let latestContent = '', + editorView + + beforeAll(() => { + editorView = new EditorView({ + state: EditorState.create({ + doc: INIT_DOC, + extensions: [ + saveHelper({ + auto: false, + hotkey, + save(view) { + latestContent = view.state.doc.toString() + } + }) + ] + }) + }) + + editorView.dispatch({ changes: { from: 0, insert: LINE_2 } }) + }) + + test('content should be empty', () => { + expect(latestContent).toBe(``) + }) + } +) diff --git a/packages/extensions/sql-parser/src/test/1.test.ts b/packages/extensions/sql-parser/src/test/1.test.ts deleted file mode 100644 index 703eb6b..0000000 --- a/packages/extensions/sql-parser/src/test/1.test.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { EditorView } from '@codemirror/view' -import { EditorState } from '@codemirror/state' -import { MySQL, sql } from '@codemirror/lang-sql' - -import { sqlParser, getSqlStatements, getNearbyStatement } from '..' - -const LINE_1 = `USE sp500insight;` -const LINE_2 = `SELECT sector, industry, COUNT(*) AS companies -FROM companies c -WHERE c.stock_symbol IN (SELECT stock_symbol FROM index_compositions WHERE index_symbol = "SP500") -GROUP BY sector, industry -ORDER BY sector, companies DESC;` - -const DOC = `\n${LINE_1}\n\n${LINE_2}\n\n` - -test('test getSqlStatements', () => { - const editorView = new EditorView({ - state: EditorState.create({ - doc: DOC, - extensions: [sql({ dialect: MySQL }), sqlParser()] - }) - }) - - // dispatch any a transaction to trigger update event for editor - editorView.dispatch({ selection: { anchor: 0, head: 0 } }) - - const allStatements = getSqlStatements(editorView.state) - expect(allStatements.length).toBe(2) - - const firstStatement = allStatements[0] - expect(firstStatement.content).toBe(LINE_1) - expect(firstStatement.database).toBe('sp500insight') - expect(firstStatement.type).toBe('use') - expect(firstStatement.from).toBe(1) - expect(firstStatement.to).toBe(1 + LINE_1.length) - expect(firstStatement.lineFrom).toBe(2) - expect(firstStatement.lineTo).toBe(2) - - const secondStatement = allStatements[1] - expect(secondStatement.content).toBe(LINE_2) - expect(secondStatement.database).toBe('sp500insight') - expect(secondStatement.type).toBe('other') - expect(secondStatement.from).toBe(1 + LINE_1.length + 2) - expect(secondStatement.to).toBe(1 + LINE_1.length + 2 + LINE_2.length) - expect(secondStatement.lineFrom).toBe(4) - expect(secondStatement.lineTo).toBe(8) -}) - -test('test getNearbyStatement', () => { - const editorView = new EditorView({ - state: EditorState.create({ - doc: DOC, - extensions: [sql({ dialect: MySQL }), sqlParser()] - }) - }) - - // dispatch any a transaction to trigger update event for editor - editorView.dispatch({ selection: { anchor: 0, head: 0 } }) - - let nearestStatement = getNearbyStatement(editorView.state, 0) - expect(nearestStatement?.content).toBe(LINE_1) - - nearestStatement = getNearbyStatement(editorView.state, 10) - expect(nearestStatement?.content).toBe(LINE_1) - - nearestStatement = getNearbyStatement(editorView.state, 1 + LINE_1.length) // 18 - expect(nearestStatement?.content).toBe(LINE_1) - - nearestStatement = getNearbyStatement(editorView.state, 1 + LINE_1.length + 1) // 19 - expect(nearestStatement?.content).toBe(LINE_1) - - nearestStatement = getNearbyStatement( - editorView.state, - 1 + LINE_1.length + 10 - ) // 28 - expect(nearestStatement?.content).toBe(LINE_1) - - nearestStatement = getNearbyStatement( - editorView.state, - 1 + LINE_1.length + 2 + LINE_2.length - ) // 241 - expect(nearestStatement?.content).toBe(LINE_2) - - nearestStatement = getNearbyStatement( - editorView.state, - 1 + LINE_1.length + 2 + LINE_2.length - ) // 241 - expect(nearestStatement?.content).toBe(LINE_2) - - nearestStatement = getNearbyStatement( - editorView.state, - 1 + LINE_1.length + 2 + LINE_2.length + 2 - ) // 243 - expect(nearestStatement?.content).toBe(LINE_2) -}) diff --git a/packages/extensions/sql-parser/src/test/statement.test.ts b/packages/extensions/sql-parser/src/test/statement.test.ts new file mode 100644 index 0000000..eef7a6e --- /dev/null +++ b/packages/extensions/sql-parser/src/test/statement.test.ts @@ -0,0 +1,122 @@ +import { EditorState } from '@codemirror/state' +import { MySQL, sql } from '@codemirror/lang-sql' + +import { + sqlParser, + getSqlStatements, + getNearbyStatement, + SqlStatement +} from '..' +import { EditorView } from '@codemirror/view' + +const LINE_1 = `USE sp500insight;` +const LINE_2 = `SELECT sector, industry, COUNT(*) AS companies +FROM companies c +WHERE c.stock_symbol IN (SELECT stock_symbol FROM index_compositions WHERE index_symbol = "SP500") +GROUP BY sector, industry +ORDER BY sector, companies DESC;` + +const DOC = `\n${LINE_1}\n\n${LINE_2}\n\n` + +describe('test getSqlStatements', () => { + let editorView: EditorView, + allStatements: SqlStatement[], + firstStatement: SqlStatement, + secondStatement: SqlStatement + + beforeAll(() => { + editorView = new EditorView({ + state: EditorState.create({ + doc: DOC, + extensions: [sql({ dialect: MySQL }), sqlParser()] + }) + }) + + // dispatch any a transaction to trigger update event for editor + editorView.dispatch({ selection: { anchor: 0, head: 0 } }) + allStatements = getSqlStatements(editorView.state) + firstStatement = allStatements[0] + secondStatement = allStatements[1] + }) + + test('getSqlStatements works well', () => { + expect(allStatements.length).toBe(2) + + expect(firstStatement.content).toBe(LINE_1) + expect(firstStatement.database).toBe('sp500insight') + expect(firstStatement.type).toBe('use') + expect(firstStatement.from).toBe(1) + expect(firstStatement.to).toBe(1 + LINE_1.length) + expect(firstStatement.lineFrom).toBe(2) + expect(firstStatement.lineTo).toBe(2) + + expect(secondStatement.content).toBe(LINE_2) + expect(secondStatement.database).toBe('sp500insight') + expect(secondStatement.type).toBe('other') + expect(secondStatement.from).toBe(1 + LINE_1.length + 2) + expect(secondStatement.to).toBe(1 + LINE_1.length + 2 + LINE_2.length) + expect(secondStatement.lineFrom).toBe(4) + expect(secondStatement.lineTo).toBe(8) + }) +}) + +describe('test getNearbyStatement', () => { + let editorView: EditorView = new EditorView() + + beforeAll(() => { + editorView = new EditorView({ + state: EditorState.create({ + doc: DOC, + extensions: [sql({ dialect: MySQL }), sqlParser()] + }) + }) + + // dispatch any a transaction to trigger update event for editor + editorView.dispatch({ selection: { anchor: 0, head: 0 } }) + }) + + test('getNearbyStatement works well', () => { + expect(getNearbyStatement(editorView.state, 0)?.content).toBe(LINE_1) + + expect(getNearbyStatement(editorView.state, 10)?.content).toBe(LINE_1) + + // 18 + expect( + getNearbyStatement(editorView.state, 1 + LINE_1.length)?.content + ).toBe(LINE_1) + + // 19 + expect( + getNearbyStatement(editorView.state, 1 + LINE_1.length + 1)?.content + ).toBe(LINE_1) + + // 28 + expect( + getNearbyStatement(editorView.state, 1 + LINE_1.length + 10)?.content + ).toBe(LINE_1) + + // 241 + expect( + getNearbyStatement( + editorView.state, + 1 + LINE_1.length + 2 + LINE_2.length + )?.content + ).toBe(LINE_2) + + // 241 + expect( + getNearbyStatement( + editorView.state, + 1 + LINE_1.length + 2 + LINE_2.length + )?.content + ).toBe(LINE_2) + + // 243 + expect( + getNearbyStatement( + editorView.state, + 1 + LINE_1.length + 2 + LINE_2.length + 2 + )?.content + ).toBe(LINE_2) + }) +})