Skip to content

Commit 69ccece

Browse files
Add e2e test for references; address comments
1 parent 122bb6f commit 69ccece

2 files changed

Lines changed: 173 additions & 8 deletions

File tree

sqlmesh/lsp/main.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -382,14 +382,7 @@ def find_references(
382382
cte_references = get_cte_references(self.lsp_context, uri, params.position)
383383

384384
# Convert references to Location objects
385-
locations = []
386-
for ref in cte_references:
387-
locations.append(
388-
types.Location(
389-
uri=ref.uri,
390-
range=ref.range,
391-
)
392-
)
385+
locations = [types.Location(uri=ref.uri, range=ref.range) for ref in cte_references]
393386

394387
return locations if locations else None
395388
except Exception as e:
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
import { test, expect } from '@playwright/test'
2+
import path from 'path'
3+
import fs from 'fs-extra'
4+
import os from 'os'
5+
import { startVSCode, SUSHI_SOURCE_PATH } from './utils'
6+
7+
// Consistent keyboard shortcuts
8+
const GO_TO_REFERENCES_KEY = 'Shift+F12'
9+
const FIND_ALL_REFERENCES_KEY = process.platform === 'darwin' ? 'Alt+Shift+F12' : 'Ctrl+Shift+F12'
10+
11+
test.describe('CTE References', () => {
12+
let tempDir: string
13+
let window: any
14+
let close: () => Promise<void>
15+
16+
test.beforeEach(async () => {
17+
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'vscode-test-sushi-'))
18+
await fs.copy(SUSHI_SOURCE_PATH, tempDir)
19+
const vscode = await startVSCode(tempDir)
20+
window = vscode.window
21+
close = vscode.close
22+
23+
// Common setup: navigate to customers.sql
24+
await window.waitForSelector('text=models')
25+
await window
26+
.getByRole('treeitem', { name: 'models', exact: true })
27+
.locator('a')
28+
.click()
29+
await window
30+
.getByRole('treeitem', { name: 'customers.sql', exact: true })
31+
.locator('a')
32+
.click()
33+
await window.waitForSelector('text=grain')
34+
await window.waitForSelector('text=Loaded SQLMesh Context')
35+
})
36+
37+
test.afterEach(async () => {
38+
await close()
39+
fs.removeSync(tempDir)
40+
})
41+
42+
test('Go to references from definition of CTE', async () => {
43+
// Click on the CTE definition "current_marketing_outer" at line 20 to position cursor
44+
await window.locator('text=current_marketing_outer').first().click()
45+
46+
// Use keyboard shortcut to find all references
47+
await window.keyboard.press(GO_TO_REFERENCES_KEY)
48+
49+
// Wait for the references to appear
50+
await window.waitForSelector('text=References')
51+
52+
// Wait for reference panel to populate
53+
await window.waitForFunction(() => {
54+
const referenceElements = document.querySelectorAll('.reference-item, .monaco-list-row, .references-view .tree-row')
55+
return referenceElements.length >= 2
56+
}, { timeout: 5000 })
57+
58+
// Verify that the customers.sql file is shown in results
59+
await expect(window.locator('text=customers.sql').first()).toBeVisible()
60+
61+
// Check that both CTE definition and usage are listed in references
62+
await window.waitForSelector('text=References')
63+
await window.waitForSelector('text=WITH current_marketing_outer AS')
64+
await window.waitForSelector('text=FROM current_marketing_outer')
65+
})
66+
67+
test('Go to references from usage of CTE', async () => {
68+
// Click on the CTE usage this time for "current_marketing_outer"
69+
await window.locator('text=FROM current_marketing_outer').click({
70+
position: { x: 80, y: 5 } // Clicks on the usage rather than first which was definition
71+
})
72+
73+
// Use keyboard shortcut to go to references
74+
await window.keyboard.press(GO_TO_REFERENCES_KEY)
75+
76+
// Wait for the references to appear
77+
await window.waitForSelector('text=References')
78+
79+
// Better assertions: wait for reference panel to populate
80+
await window.waitForFunction(() => {
81+
const referenceElements = document.querySelectorAll('.reference-item, .monaco-list-row, .references-view .tree-row')
82+
return referenceElements.length >= 2
83+
}, { timeout: 5000 })
84+
85+
await window.waitForSelector('text=References')
86+
await window.waitForSelector('text=WITH current_marketing_outer AS')
87+
await window.waitForSelector('text=FROM current_marketing_outer')
88+
89+
// Verify that the customers.sql file is shown in results
90+
await expect(window.locator('text=customers.sql').first()).toBeVisible()
91+
})
92+
93+
test('Go to references for nested CTE', async () => {
94+
// Click on the nested CTE "current_marketing"
95+
await window.locator('text=WITH current_marketing AS').click({
96+
position: { x: 100, y: 5 } // Click on the CTE name part
97+
})
98+
99+
// Use keyboard shortcut to find all references
100+
await window.keyboard.press(GO_TO_REFERENCES_KEY)
101+
102+
// Wait for the references to appear
103+
await window.waitForSelector('text=References')
104+
105+
// Wait for reference panel to populate
106+
await window.waitForFunction(() => {
107+
const referenceElements = document.querySelectorAll('.reference-item, .monaco-list-row, .references-view .tree-row')
108+
return referenceElements.length >= 2
109+
}, { timeout: 5000 })
110+
111+
// Verify that the customers.sql file is shown in results
112+
await expect(window.locator('text=customers.sql').first()).toBeVisible()
113+
114+
// Check that both CTE definition and usage are listed in references
115+
await window.waitForSelector('text=References')
116+
await window.waitForSelector('text=WITH current_marketing AS')
117+
await window.waitForSelector('text=FROM current_marketing')
118+
119+
})
120+
121+
test('Find all references for CTE', async () => {
122+
// Click on the CTE definition "current_marketing_outer"
123+
await window.locator('text=current_marketing_outer').first().click()
124+
125+
// Use keyboard shortcut to find all references
126+
await window.keyboard.press(FIND_ALL_REFERENCES_KEY)
127+
128+
// Verify references contains expected content
129+
await window.waitForSelector('text=References')
130+
await window.waitForSelector('text=WITH current_marketing_outer AS')
131+
await window.waitForSelector('text=FROM current_marketing_outer')
132+
133+
// Verify that the customers.sql file is shown in results
134+
await expect(window.locator('text=customers.sql').first()).toBeVisible()
135+
})
136+
137+
test('Find all references from usage for CTE', async () => {
138+
// Click on the CTE usage of "current_marketing_outer" using last
139+
await window.locator('text=current_marketing_outer').last().click()
140+
141+
// Use keyboard shortcut to find all references
142+
await window.keyboard.press(FIND_ALL_REFERENCES_KEY)
143+
144+
// Verify references contains expected content
145+
await window.waitForSelector('text=References')
146+
await window.waitForSelector('text=WITH current_marketing_outer AS')
147+
await window.waitForSelector('text=FROM current_marketing_outer')
148+
149+
// Verify that the customers.sql file is shown in results
150+
await expect(window.locator('text=customers.sql').first()).toBeVisible()
151+
})
152+
153+
test('Find all references for nested CTE', async () => {
154+
// Click on the nested CTE "current_marketing" at line 33
155+
// We need to be more specific to get the inner one
156+
await window.locator('text=WITH current_marketing AS').click({
157+
position: { x: 100, y: 5 } // Click on the CTE name part
158+
})
159+
160+
// Use keyboard shortcut to find all references
161+
await window.keyboard.press(FIND_ALL_REFERENCES_KEY)
162+
163+
// Verify references contains expected content
164+
await window.waitForSelector('text=References')
165+
await window.waitForSelector('text=WITH current_marketing AS')
166+
await window.waitForSelector('text=FROM current_marketing')
167+
168+
// Verify that the customers.sql file is shown in results
169+
await expect(window.locator('text=customers.sql').first()).toBeVisible()
170+
})
171+
172+
})

0 commit comments

Comments
 (0)