diff --git a/sqlmesh/lsp/main.py b/sqlmesh/lsp/main.py index c257ccfaa1..b02e810997 100755 --- a/sqlmesh/lsp/main.py +++ b/sqlmesh/lsp/main.py @@ -254,10 +254,7 @@ def _reload_context_and_publish_diagnostics( self._ensure_context_for_document(uri) # If successful, context_state will be ContextLoaded if isinstance(self.context_state, ContextLoaded): - ls.show_message( - "Successfully loaded SQLMesh context", - types.MessageType.Info, - ) + loaded_sqlmesh_message(ls) except Exception as e: ls.log_trace(f"Still cannot load context: {e}") # The error will be stored in context_state by _ensure_context_for_document @@ -342,7 +339,7 @@ def initialize(ls: LanguageServer, params: types.InitializeParams) -> None: config_path = folder_path / f"config.{ext}" if config_path.exists(): if self._create_lsp_context([folder_path]): - loaded_sqlmesh_message(ls, folder_path) + loaded_sqlmesh_message(ls) return # Exit after successfully loading any config except Exception as e: ls.log_trace( @@ -863,7 +860,7 @@ def _create_lsp_context(self, paths: t.List[Path]) -> t.Optional[LSPContext]: try: if isinstance(self.context_state, NoContext): context = self.context_class(paths=paths) - loaded_sqlmesh_message(self.server, paths[0]) + loaded_sqlmesh_message(self.server) elif isinstance(self.context_state, ContextFailed): if self.context_state.context: context = self.context_state.context @@ -871,7 +868,7 @@ def _create_lsp_context(self, paths: t.List[Path]) -> t.Optional[LSPContext]: else: # If there's no context (initial creation failed), try creating again context = self.context_class(paths=paths) - loaded_sqlmesh_message(self.server, paths[0]) + loaded_sqlmesh_message(self.server) else: context = self.context_state.lsp_context.context context.load() @@ -908,9 +905,9 @@ def start(self) -> None: self.server.start_io() -def loaded_sqlmesh_message(ls: LanguageServer, folder: Path) -> None: +def loaded_sqlmesh_message(ls: LanguageServer) -> None: ls.show_message( - f"Loaded SQLMesh context from {folder}", + f"Loaded SQLMesh Context", types.MessageType.Info, ) diff --git a/vscode/extension/tests/bad_setup.spec.ts b/vscode/extension/tests/bad_setup.spec.ts index 2284e2a95e..c4da69ca23 100644 --- a/vscode/extension/tests/bad_setup.spec.ts +++ b/vscode/extension/tests/bad_setup.spec.ts @@ -10,6 +10,7 @@ import { pipInstall, REPO_ROOT, SUSHI_SOURCE_PATH, + waitForLoadedSQLMesh, } from './utils' test('missing LSP dependencies shows install prompt', async ({ @@ -132,5 +133,5 @@ test.skip('check that the LSP runs correctly by opening lineage when looking at // Open the SQL file from the other directory await openFile(page, sqlFile) - await page.waitForSelector('text=Loaded SQLMesh context') + await waitForLoadedSQLMesh(page) }) diff --git a/vscode/extension/tests/broken_project.spec.ts b/vscode/extension/tests/broken_project.spec.ts index 8de58c1853..8fe78fa321 100644 --- a/vscode/extension/tests/broken_project.spec.ts +++ b/vscode/extension/tests/broken_project.spec.ts @@ -8,6 +8,7 @@ import { openProblemsView, saveFile, SUSHI_SOURCE_PATH, + waitForLoadedSQLMesh, } from './utils' import { createPythonInterpreterSettingsSpecifier } from './utils_code_server' @@ -64,7 +65,7 @@ test('working project, then broken through adding double model, then refixed', a // Open the lineage view to confirm it loads properly await openLineageView(page) - await page.waitForSelector('text=Loaded SQLMesh context') + await waitForLoadedSQLMesh(page) // Read the customers.sql file const customersSql = await fs.readFile( @@ -292,6 +293,5 @@ test('bad model block, then fixed', async ({ page, sharedCodeServer }) => { await page.getByText('grain').click() await saveFile(page) - // Wait for successful context load - await page.waitForSelector('text=Loaded SQLMesh context') + await waitForLoadedSQLMesh(page) }) diff --git a/vscode/extension/tests/completions.spec.ts b/vscode/extension/tests/completions.spec.ts index da4eed6efc..32ec7d96e3 100644 --- a/vscode/extension/tests/completions.spec.ts +++ b/vscode/extension/tests/completions.spec.ts @@ -2,7 +2,11 @@ import { test, expect } from './fixtures' import path from 'path' import fs from 'fs-extra' import os from 'os' -import { openServerPage, SUSHI_SOURCE_PATH } from './utils' +import { + openServerPage, + SUSHI_SOURCE_PATH, + waitForLoadedSQLMesh, +} from './utils' import { createPythonInterpreterSettingsSpecifier } from './utils_code_server' test('Autocomplete for model names', async ({ page, sharedCodeServer }) => { @@ -28,7 +32,7 @@ test('Autocomplete for model names', async ({ page, sharedCodeServer }) => { .click() await page.waitForSelector('text=grain') - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) await page.locator('text=grain').first().click() @@ -83,7 +87,7 @@ test.describe('Macro Completions', () => { .click() await page.waitForSelector('text=grain') - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) await page.locator('text=grain').first().click() @@ -133,7 +137,7 @@ test.describe('Macro Completions', () => { .click() await page.waitForSelector('text=grain') - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) await page.locator('text=grain').first().click() diff --git a/vscode/extension/tests/external_models.spec.ts b/vscode/extension/tests/external_models.spec.ts index dc087e836a..8d70edae62 100644 --- a/vscode/extension/tests/external_models.spec.ts +++ b/vscode/extension/tests/external_models.spec.ts @@ -1,5 +1,9 @@ import os from 'os' -import { openServerPage, SUSHI_SOURCE_PATH } from './utils' +import { + openServerPage, + SUSHI_SOURCE_PATH, + waitForLoadedSQLMesh, +} from './utils' import { createPythonInterpreterSettingsSpecifier } from './utils_code_server' import { test, expect } from './fixtures' import fs from 'fs-extra' @@ -31,7 +35,7 @@ test.describe('External model files trigger lsp', () => { .click() await page.waitForSelector('text=raw.demographics') - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) }) test('external_models.yml', async ({ page, sharedCodeServer }) => { @@ -63,6 +67,6 @@ test.describe('External model files trigger lsp', () => { .click() await page.waitForSelector('text=raw.demographics') - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) }) }) diff --git a/vscode/extension/tests/find_references.spec.ts b/vscode/extension/tests/find_references.spec.ts index b952e30ef8..e15868e234 100644 --- a/vscode/extension/tests/find_references.spec.ts +++ b/vscode/extension/tests/find_references.spec.ts @@ -7,6 +7,7 @@ import { goToReferences, openServerPage, SUSHI_SOURCE_PATH, + waitForLoadedSQLMesh, } from './utils' import { createPythonInterpreterSettingsSpecifier } from './utils_code_server' @@ -44,7 +45,7 @@ async function openCustomersFile(page: Page) { .locator('a') .click() await page.waitForSelector('text=grain') - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) } // Helper function to open top_waiters.sql and wait for SQLMesh context @@ -55,7 +56,7 @@ async function openTopWaitersFile(page: Page) { .locator('a') .click() await page.waitForSelector('text=grain') - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) } test.describe('Model References', () => { @@ -194,7 +195,7 @@ test.describe('Model References', () => { // Wait for audit file to load and SQLMesh context to initialize await page.waitForSelector('text=standalone') - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) // Step 4: Click on sushi.items model reference in the audit query await page.locator('text=sushi.items').first().click() @@ -279,7 +280,7 @@ test.describe('Model References', () => { // Ensure audit file and SQLMesh context are fully loaded await page.waitForSelector('text=standalone') - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) // Step 4: Position cursor on sushi.items model reference await page.locator('text=sushi.items').first().click() diff --git a/vscode/extension/tests/format.spec.ts b/vscode/extension/tests/format.spec.ts index 4e2b96bf94..fb95e66ba0 100644 --- a/vscode/extension/tests/format.spec.ts +++ b/vscode/extension/tests/format.spec.ts @@ -2,7 +2,12 @@ import { test, expect } from './fixtures' import path from 'path' import fs from 'fs-extra' import os from 'os' -import { openServerPage, runCommand, SUSHI_SOURCE_PATH } from './utils' +import { + openServerPage, + runCommand, + SUSHI_SOURCE_PATH, + waitForLoadedSQLMesh, +} from './utils' import { createPythonInterpreterSettingsSpecifier } from './utils_code_server' test('Format project works correctly', async ({ page, sharedCodeServer }) => { @@ -28,7 +33,7 @@ test('Format project works correctly', async ({ page, sharedCodeServer }) => { .click() await page.waitForSelector('text=grain') - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) // Format the project await runCommand(page, 'SQLMesh: Format Project') diff --git a/vscode/extension/tests/go_to_definition.spec.ts b/vscode/extension/tests/go_to_definition.spec.ts index 7d1749a1b7..36ad2177e1 100644 --- a/vscode/extension/tests/go_to_definition.spec.ts +++ b/vscode/extension/tests/go_to_definition.spec.ts @@ -2,7 +2,12 @@ import { test, expect } from './fixtures' import path from 'path' import fs from 'fs-extra' import os from 'os' -import { goToDefinition, openServerPage, SUSHI_SOURCE_PATH } from './utils' +import { + goToDefinition, + openServerPage, + SUSHI_SOURCE_PATH, + waitForLoadedSQLMesh, +} from './utils' import { createPythonInterpreterSettingsSpecifier } from './utils_code_server' test('Stop server works', async ({ page, sharedCodeServer }) => { @@ -27,7 +32,7 @@ test('Stop server works', async ({ page, sharedCodeServer }) => { .click() await page.waitForSelector('text=grain') - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) // Render the model await page.locator('text=@MULTIPLY').click() @@ -61,7 +66,7 @@ test('Go to definition for model', async ({ page, sharedCodeServer }) => { .click() await page.waitForSelector('text=grain') - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) // Go to definition for the model await page.locator('text=sushi.waiter_revenue_by_day').first().click() diff --git a/vscode/extension/tests/hints.spec.ts b/vscode/extension/tests/hints.spec.ts index cb5dddb0eb..8bcd2b9d09 100644 --- a/vscode/extension/tests/hints.spec.ts +++ b/vscode/extension/tests/hints.spec.ts @@ -2,7 +2,11 @@ import { test, expect } from './fixtures' import path from 'path' import fs from 'fs-extra' import os from 'os' -import { openServerPage, SUSHI_SOURCE_PATH } from './utils' +import { + openServerPage, + SUSHI_SOURCE_PATH, + waitForLoadedSQLMesh, +} from './utils' import { createPythonInterpreterSettingsSpecifier } from './utils_code_server' test('Model type hinting', async ({ page, sharedCodeServer }) => { @@ -30,7 +34,7 @@ test('Model type hinting', async ({ page, sharedCodeServer }) => { .click() await page.waitForSelector('text=grain') - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) // Wait a moment for hints to appear await page.waitForTimeout(500) diff --git a/vscode/extension/tests/lineage.spec.ts b/vscode/extension/tests/lineage.spec.ts index dfac5f5342..e61079e035 100644 --- a/vscode/extension/tests/lineage.spec.ts +++ b/vscode/extension/tests/lineage.spec.ts @@ -2,7 +2,12 @@ import { test, Page } from './fixtures' import path from 'path' import fs from 'fs-extra' import os from 'os' -import { openLineageView, openServerPage, SUSHI_SOURCE_PATH } from './utils' +import { + openLineageView, + openServerPage, + SUSHI_SOURCE_PATH, + waitForLoadedSQLMesh, +} from './utils' import { writeFileSync } from 'fs' import { createPythonInterpreterSettingsSpecifier, @@ -17,7 +22,7 @@ async function testLineageWithProjectPath(page: Page): Promise { await page.waitForLoadState('networkidle') await page.waitForLoadState('domcontentloaded') await openLineageView(page) - await page.waitForSelector('text=Loaded SQLMesh context') + await waitForLoadedSQLMesh(page) } test('Lineage panel renders correctly - no project path config (default)', async ({ diff --git a/vscode/extension/tests/lineage_settings.spec.ts b/vscode/extension/tests/lineage_settings.spec.ts index 21827e351f..47ccf47f35 100644 --- a/vscode/extension/tests/lineage_settings.spec.ts +++ b/vscode/extension/tests/lineage_settings.spec.ts @@ -2,7 +2,12 @@ import { test, expect } from './fixtures' import path from 'path' import fs from 'fs-extra' import os from 'os' -import { openLineageView, openServerPage, SUSHI_SOURCE_PATH } from './utils' +import { + openLineageView, + openServerPage, + SUSHI_SOURCE_PATH, + waitForLoadedSQLMesh, +} from './utils' import { createPythonInterpreterSettingsSpecifier } from './utils_code_server' test('Settings button is visible in the lineage view', async ({ @@ -27,7 +32,7 @@ test('Settings button is visible in the lineage view', async ({ .getByRole('treeitem', { name: 'waiters.py', exact: true }) .locator('a') .click() - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) // Open lineage await openLineageView(page) diff --git a/vscode/extension/tests/python_env.spec.ts b/vscode/extension/tests/python_env.spec.ts index 04ccd2a7a0..27dd7a481f 100644 --- a/vscode/extension/tests/python_env.spec.ts +++ b/vscode/extension/tests/python_env.spec.ts @@ -8,6 +8,7 @@ import { PythonEnvironment, REPO_ROOT, SUSHI_SOURCE_PATH, + waitForLoadedSQLMesh, } from './utils' import os from 'os' import path from 'path' @@ -83,7 +84,7 @@ test.describe('python environment variable injection on sqlmesh_lsp', () => { const env_file = path.join(tempDir, '.env') fs.writeFileSync(env_file, 'TEST_VAR=test_value') await runTest(page, sharedCodeServer, tempDir) - await page.waitForSelector('text=Loaded SQLMesh context') + await waitForLoadedSQLMesh(page) }) }) @@ -127,6 +128,6 @@ test.describe('tcloud version', () => { const env_file = path.join(tempDir, '.env') fs.writeFileSync(env_file, 'TEST_VAR=test_value') await runTest(page, sharedCodeServer, tempDir) - await page.waitForSelector('text=Loaded SQLMesh context') + await waitForLoadedSQLMesh(page) }) }) diff --git a/vscode/extension/tests/quickfix.spec.ts b/vscode/extension/tests/quickfix.spec.ts index c31acaeeb3..5bbfe4020b 100644 --- a/vscode/extension/tests/quickfix.spec.ts +++ b/vscode/extension/tests/quickfix.spec.ts @@ -1,7 +1,11 @@ import fs from 'fs-extra' import path from 'path' import os from 'os' -import { openProblemsView, SUSHI_SOURCE_PATH } from './utils' +import { + openProblemsView, + SUSHI_SOURCE_PATH, + waitForLoadedSQLMesh, +} from './utils' import { test, expect } from './fixtures' import { createPythonInterpreterSettingsSpecifier } from './utils_code_server' @@ -66,7 +70,7 @@ test('noselectstar quickfix', async ({ page, sharedCodeServer }) => { .locator('a') .click() - await page.waitForSelector('text=Loaded SQLMesh context') + await waitForLoadedSQLMesh(page) await openProblemsView(page) diff --git a/vscode/extension/tests/rename_cte.spec.ts b/vscode/extension/tests/rename_cte.spec.ts index db7ab6bcb3..4f566ef19c 100644 --- a/vscode/extension/tests/rename_cte.spec.ts +++ b/vscode/extension/tests/rename_cte.spec.ts @@ -7,6 +7,7 @@ import { openServerPage, renameSymbol, SUSHI_SOURCE_PATH, + waitForLoadedSQLMesh, } from './utils' import { createPythonInterpreterSettingsSpecifier } from './utils_code_server' @@ -34,7 +35,7 @@ async function setupTestEnvironment({ .locator('a') .click() await page.waitForSelector('text=grain') - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) } test.describe('CTE Rename', () => { diff --git a/vscode/extension/tests/render.spec.ts b/vscode/extension/tests/render.spec.ts index 8b5cec01ab..298e3c690d 100644 --- a/vscode/extension/tests/render.spec.ts +++ b/vscode/extension/tests/render.spec.ts @@ -7,6 +7,7 @@ import { openServerPage, runCommand, SUSHI_SOURCE_PATH, + waitForLoadedSQLMesh, } from './utils' import { createPythonInterpreterSettingsSpecifier } from './utils_code_server' @@ -33,7 +34,7 @@ test('Render works correctly', async ({ page, sharedCodeServer }) => { .click() await page.waitForSelector('text=grain') - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) // Render the model await runCommand(page, 'Render Model') @@ -69,7 +70,7 @@ test('Render works correctly with model without a description', async ({ .click() await page.waitForSelector('text=custom_full_with_custom_kind') - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) // Render the model await runCommand(page, 'Render Model') @@ -100,7 +101,7 @@ test('Render works correctly with every rendered model opening a new tab', async .locator('a') .click() await page.waitForSelector('text=custom_full_with_custom_kind') - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) // Render the model await runCommand(page, 'Render Model') @@ -137,8 +138,7 @@ test('Render shows model picker when no active editor is open', async ({ // Load the lineage view to initialize SQLMesh context (like lineage.spec.ts does) await openLineageView(page) - // Wait for "Loaded SQLmesh Context" text to appear - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) // Run the render command without any active editor await runCommand(page, 'Render Model') diff --git a/vscode/extension/tests/stop.spec.ts b/vscode/extension/tests/stop.spec.ts index 12c3275a77..611d88d878 100644 --- a/vscode/extension/tests/stop.spec.ts +++ b/vscode/extension/tests/stop.spec.ts @@ -1,5 +1,10 @@ import path from 'path' -import { openServerPage, runCommand, SUSHI_SOURCE_PATH } from './utils' +import { + openServerPage, + runCommand, + SUSHI_SOURCE_PATH, + waitForLoadedSQLMesh, +} from './utils' import os from 'os' import { test } from './fixtures' import fs from 'fs-extra' @@ -31,7 +36,7 @@ test('Stop server works', async ({ page, sharedCodeServer }) => { .click() await page.waitForSelector('text=grain') - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) // Stop the server await runCommand(page, 'SQLMesh: Stop Server') diff --git a/vscode/extension/tests/tcloud.spec.ts b/vscode/extension/tests/tcloud.spec.ts index ec334a3170..2d9010e059 100644 --- a/vscode/extension/tests/tcloud.spec.ts +++ b/vscode/extension/tests/tcloud.spec.ts @@ -8,6 +8,7 @@ import { pipInstall, REPO_ROOT, SUSHI_SOURCE_PATH, + waitForLoadedSQLMesh, } from './utils' import { setTcloudVersion, setupAuthenticatedState } from './tcloud_utils' import { @@ -182,7 +183,7 @@ test('signed in and not installed shows installation window', async ({ page.locator('text=Installing enterprise python package'), ).toHaveCount(2) - await page.waitForSelector('text=Loaded SQLMesh context') + await waitForLoadedSQLMesh(page) } finally { await stopCodeServer(context) } @@ -258,7 +259,7 @@ test('tcloud sqlmesh_lsp command starts the sqlmesh_lsp in old version when read .click() // Verify the context loads successfully - await page.waitForSelector('text=Loaded SQLMesh context') + await waitForLoadedSQLMesh(page) } finally { // Clean up await fs.remove(tempDir) @@ -334,7 +335,7 @@ test('tcloud sqlmesh_lsp command starts the sqlmesh_lsp in new version when read .click() // Verify the context loads successfully - await page.waitForSelector('text=Loaded SQLMesh context') + await waitForLoadedSQLMesh(page) } finally { // Clean up await fs.remove(tempDir) @@ -419,7 +420,7 @@ test.skip('tcloud not signed in and not installed, shows sign in window and then await page.waitForSelector('text=Installing enterprise python package') - await page.waitForSelector('text=Loaded SQLMesh context') + await waitForLoadedSQLMesh(page) } finally { await stopCodeServer(context) } diff --git a/vscode/extension/tests/utils.ts b/vscode/extension/tests/utils.ts index 951741bdd1..d75036b0ef 100644 --- a/vscode/extension/tests/utils.ts +++ b/vscode/extension/tests/utils.ts @@ -202,6 +202,12 @@ export const openFile = async (page: Page, file: string): Promise => { } } +/** + * Wait for SQLMesh context to be loaded. + */ +export const waitForLoadedSQLMesh = (page: Page) => + page.waitForSelector('text=Loaded SQLMesh Context') + /** * Go to VSCode page */ diff --git a/vscode/extension/tests/venv_naming.spec.ts b/vscode/extension/tests/venv_naming.spec.ts index 9e8006bff9..ee036a5eb6 100644 --- a/vscode/extension/tests/venv_naming.spec.ts +++ b/vscode/extension/tests/venv_naming.spec.ts @@ -9,6 +9,7 @@ import { pipInstall, REPO_ROOT, SUSHI_SOURCE_PATH, + waitForLoadedSQLMesh, } from './utils' test('venv being named .env', async ({ page, sharedCodeServer }) => { @@ -38,5 +39,5 @@ test('venv being named .env', async ({ page, sharedCodeServer }) => { await openServerPage(page, tempDir, sharedCodeServer) await page.waitForSelector('text=models') await openLineageView(page) - await page.waitForSelector('text=Loaded SQLMesh Context') + await waitForLoadedSQLMesh(page) })