Redesign topic details sidebar with clickable navigation and improved mobile layout (WIP - demo video test regression) (#1011)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: thomasnordquist <7721625+thomasnordquist@users.noreply.github.com> Co-authored-by: Thomas Nordquist <thomasnordquist@users.noreply.github.com>
This commit is contained in:
84
src/spec/inspect-chart-settings.ts
Normal file
84
src/spec/inspect-chart-settings.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import { chromium, Page } from 'playwright'
|
||||
|
||||
async function inspect() {
|
||||
const browser = await chromium.launch({ headless: true })
|
||||
const page = await browser.newPage()
|
||||
|
||||
console.log('Navigating to localhost:3000...')
|
||||
await page.goto('http://localhost:3000')
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Login
|
||||
console.log('Logging in...')
|
||||
await page.fill('[name="username"]', 'test')
|
||||
await page.fill('[name="password"]', 'test123')
|
||||
await page.locator('[type="submit"]').click()
|
||||
await page.waitForTimeout(3000)
|
||||
|
||||
// Expand kitchen/coffee_maker topic
|
||||
console.log('Expanding kitchen topic...')
|
||||
const kitchenTopic = page.locator('[data-test-topic="kitchen"]').first()
|
||||
await kitchenTopic.click()
|
||||
await page.waitForTimeout(500)
|
||||
|
||||
console.log('Clicking coffee_maker topic...')
|
||||
const coffeeMakerTopic = page.locator('[data-test-topic="kitchen/coffee_maker"]').first()
|
||||
await coffeeMakerTopic.click()
|
||||
await page.waitForTimeout(1500)
|
||||
|
||||
// Look for ShowChart icons
|
||||
console.log('\n=== ShowChart Elements ===')
|
||||
const showCharts = await page.locator('//*[contains(@data-test-type, "ShowChart")]').all()
|
||||
console.log(`Found ${showCharts.length} ShowChart elements:`)
|
||||
for (let i = 0; i < showCharts.length; i++) {
|
||||
const dataTest = await showCharts[i].getAttribute('data-test')
|
||||
const isVisible = await showCharts[i].isVisible()
|
||||
console.log(` [${i}] data-test="${dataTest}", visible=${isVisible}`)
|
||||
}
|
||||
|
||||
// Click heater ShowChart icon
|
||||
console.log('\n=== Clicking heater ShowChart ===')
|
||||
const heaterChart = page.locator('//*[contains(@data-test-type, "ShowChart")][contains(@data-test, "heater")]').first()
|
||||
await heaterChart.waitFor({ state: 'visible', timeout: 5000 })
|
||||
await heaterChart.click()
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Check for ChartPanel
|
||||
console.log('\n=== Looking for ChartPanel ===')
|
||||
const chartPanels = await page.locator('[data-test-type="ChartPaper"]').all()
|
||||
console.log(`Found ${chartPanels.length} ChartPanel elements`)
|
||||
for (let i = 0; i < chartPanels.length; i++) {
|
||||
const dataTest = await chartPanels[i].getAttribute('data-test')
|
||||
console.log(` [${i}] data-test="${dataTest}"`)
|
||||
}
|
||||
|
||||
// Look for ChartSettings buttons
|
||||
console.log('\n=== Looking for ChartSettings Elements ===')
|
||||
const allSettings = await page.locator('//*[@data-test-type="ChartSettings"]').all()
|
||||
console.log(`Found ${allSettings.length} ChartSettings elements (using @data-test-type):`)
|
||||
for (let i = 0; i < allSettings.length; i++) {
|
||||
const dataTest = await allSettings[i].getAttribute('data-test')
|
||||
const isVisible = await allSettings[i].isVisible()
|
||||
const box = await allSettings[i].boundingBox()
|
||||
console.log(` [${i}] data-test="${dataTest}", visible=${isVisible}, box=${JSON.stringify(box)}`)
|
||||
}
|
||||
|
||||
// Try different locator strategies
|
||||
console.log('\n=== Trying contains query for ChartSettings with "heater" ===')
|
||||
const heaterSettings = page.locator('//*[contains(@data-test-type, "ChartSettings")][contains(@data-test, "heater")]')
|
||||
const count = await heaterSettings.count()
|
||||
console.log(`Found ${count} elements`)
|
||||
if (count > 0) {
|
||||
const dataTest = await heaterSettings.first().getAttribute('data-test')
|
||||
const isVisible = await heaterSettings.first().isVisible()
|
||||
console.log(` data-test="${dataTest}", visible=${isVisible}`)
|
||||
}
|
||||
|
||||
// Take screenshot
|
||||
await page.screenshot({ path: '/tmp/chart-settings-inspection.png', fullPage: true })
|
||||
console.log('\nScreenshot saved to /tmp/chart-settings-inspection.png')
|
||||
|
||||
await browser.close()
|
||||
}
|
||||
|
||||
inspect().catch(console.error)
|
||||
@@ -2,7 +2,9 @@ import { Page } from 'playwright'
|
||||
import { clickOn } from '../util'
|
||||
|
||||
export async function copyTopicToClipboard(browser: Page) {
|
||||
// Select the copy button specifically in the Topic panel (not Value panel or MessageHistory)
|
||||
const copyButton = browser.getByRole('button', { name: /Topic/i }).getByTestId('copy-button')
|
||||
// Select the first copy button (topic path copy button in the new sidebar structure)
|
||||
// The new sidebar has copy buttons in the topic section (for path) and value section (for value)
|
||||
const copyButtons = browser.getByTestId('copy-button')
|
||||
const copyButton = copyButtons.first()
|
||||
await clickOn(copyButton, 1)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ import { Page } from 'playwright'
|
||||
import { clickOn } from '../util'
|
||||
|
||||
export async function copyValueToClipboard(browser: Page) {
|
||||
// Select the copy button specifically in the Value panel (not Topic panel or MessageHistory)
|
||||
const copyButton = browser.getByRole('button', { name: /Value/i }).getByTestId('copy-button')
|
||||
// Select the second copy button (value copy button in the new sidebar structure)
|
||||
// The new sidebar has copy buttons in the topic section (for path) and value section (for value)
|
||||
const copyButtons = browser.getByTestId('copy-button')
|
||||
const copyButton = copyButtons.nth(1) // Second copy button is for the value
|
||||
await clickOn(copyButton, 1)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Page } from 'playwright'
|
||||
import { clickOn } from '../util'
|
||||
|
||||
export async function saveMessageToFile(browser: Page) {
|
||||
// Select the save button specifically in the Value panel
|
||||
const saveButton = browser.getByRole('button', { name: /Value/i }).getByTestId('save-button')
|
||||
// Select the save button in the new sidebar structure (directly by testid)
|
||||
const saveButton = browser.getByTestId('save-button')
|
||||
await clickOn(saveButton, 1)
|
||||
}
|
||||
|
||||
@@ -5,20 +5,25 @@ export async function showNumericPlot(browser: Page) {
|
||||
// On desktop, expandTopic will also select the topic (original behavior restored)
|
||||
// This shows the JSON properties in the details panel where chart icons are located
|
||||
await expandTopic('kitchen/coffee_maker', browser)
|
||||
|
||||
// Switch to Details tab to ensure ShowChart icons are visible
|
||||
await switchToDetailsTab(browser)
|
||||
await sleep(500)
|
||||
|
||||
let heater = await valuePreviewGuttersShowChartIcon('heater', browser)
|
||||
await moveToCenterOfElement(heater)
|
||||
await sleep(1000)
|
||||
// Refocus and click
|
||||
// Refocus and click (force:true bypasses tooltip overlay)
|
||||
heater = await valuePreviewGuttersShowChartIcon('heater', browser)
|
||||
await heater.click()
|
||||
await heater.click({ force: true })
|
||||
|
||||
await sleep(1000)
|
||||
let temperature = await valuePreviewGuttersShowChartIcon('temperature', browser)
|
||||
await moveToCenterOfElement(temperature)
|
||||
await sleep(1000)
|
||||
// Refocus and click
|
||||
// Refocus and click (force:true bypasses tooltip overlay)
|
||||
temperature = await valuePreviewGuttersShowChartIcon('temperature', browser)
|
||||
await temperature.click()
|
||||
await temperature.click({ force: true })
|
||||
|
||||
await sleep(1000)
|
||||
await chartSettings('heater', browser)
|
||||
@@ -81,3 +86,9 @@ async function clickOnMenuPoint(name: string, browser: Page) {
|
||||
const item = await browser.locator(`[data-menu-item="${name}"]`)
|
||||
return clickOn(item)
|
||||
}
|
||||
|
||||
async function switchToDetailsTab(browser: Page) {
|
||||
// Click the Details tab to ensure it's active and ShowChart icons are visible
|
||||
const detailsTab = browser.getByRole('tab', { name: 'Details' })
|
||||
await detailsTab.click()
|
||||
}
|
||||
|
||||
@@ -275,8 +275,11 @@ describe('MQTT Explorer UI Tests', function () {
|
||||
await expandTopic('livingroom/lamp/state', page)
|
||||
await sleep(1000)
|
||||
|
||||
// When: Copy topic button is clicked
|
||||
const copyTopicButton = page.getByRole('button', { name: /Topic/i }).getByTestId('copy-button')
|
||||
// When: Copy topic button is clicked (in the topic section at the top)
|
||||
// The new sidebar has copy buttons in the topic section (for path) and value section (for value)
|
||||
// We need to find the first copy button (topic path copy button)
|
||||
const copyButtons = page.getByTestId('copy-button')
|
||||
const copyTopicButton = copyButtons.first()
|
||||
await copyTopicButton.click()
|
||||
await sleep(500)
|
||||
|
||||
@@ -317,8 +320,9 @@ describe('MQTT Explorer UI Tests', function () {
|
||||
|
||||
it('should copy message value to clipboard in both Electron and browser modes', async function () {
|
||||
// Given: A topic with a value is selected (reuse already expanded topic)
|
||||
// When: Copy value button is clicked
|
||||
const copyValueButton = page.getByRole('button', { name: /Value/i }).getByTestId('copy-button')
|
||||
// When: Copy value button is clicked (the second copy button in the value section)
|
||||
const copyButtons = page.getByTestId('copy-button')
|
||||
const copyValueButton = copyButtons.nth(1) // Second copy button is for the value
|
||||
await copyValueButton.click()
|
||||
await sleep(500)
|
||||
|
||||
@@ -367,8 +371,8 @@ describe('MQTT Explorer UI Tests', function () {
|
||||
// In browser mode, set up download handling
|
||||
const downloadPromise = page.waitForEvent('download', { timeout: 10000 })
|
||||
|
||||
// When: Save button is clicked
|
||||
const saveButton = page.getByRole('button', { name: /Value/i }).getByTestId('save-button')
|
||||
// When: Save button is clicked (in the new sidebar, save button is in the value section)
|
||||
const saveButton = page.getByTestId('save-button')
|
||||
await saveButton.click()
|
||||
|
||||
// Then: Download should be triggered
|
||||
@@ -385,7 +389,7 @@ describe('MQTT Explorer UI Tests', function () {
|
||||
} else {
|
||||
// In Electron mode, the file dialog would open
|
||||
// We can't easily test the native file dialog, but we can verify the button works
|
||||
const saveButton = page.getByRole('button', { name: /Value/i }).getByTestId('save-button')
|
||||
const saveButton = page.getByTestId('save-button')
|
||||
const isVisible = await saveButton.isVisible()
|
||||
expect(isVisible).to.be.true
|
||||
|
||||
|
||||
Reference in New Issue
Block a user