Skip to content

Commit

Permalink
test: golden-layout playwright tests (#1317)
Browse files Browse the repository at this point in the history
Adds some base test coverage for golden-layout. Intent is to add
coverage for visual regressions when consolidating golden layout css and
preparing it for theming in an upcoming pr.

Relies on importing layouts and the component placeholder fallback as
part of test.
  • Loading branch information
dsmmcken authored May 25, 2023
1 parent 860e4c5 commit 485c7cc
Show file tree
Hide file tree
Showing 30 changed files with 389 additions and 3 deletions.
2 changes: 2 additions & 0 deletions packages/dashboard/src/PanelPlaceholder.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@
justify-content: center;
padding: $spacer-3;
min-height: 100%;
max-height: 100%;
text-align: center;
overflow: hidden;
}
2 changes: 1 addition & 1 deletion packages/golden-layout/src/controls/Tab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default class Tab {
'<li class="lm_tab">',
'<span class="lm_title_before"></span>',
'<span class="lm_title"></span>',
'<div class="lm_close_tab"></div>',
'<div class="lm_close_tab" aria-label="Close tab"></div>',
'</li>',
].join('');

Expand Down
238 changes: 238 additions & 0 deletions tests/deephaven-app-layout.test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
{
"filterSets": [],
"layoutConfig": [
{
"type": "column",
"isClosable": true,
"isFocusOnShow": true,
"reorderEnabled": true,
"title": "",
"content": [
{
"type": "row",
"content": [
{
"type": "column",
"width": 61.803,
"content": [
{
"type": "stack",
"isClosable": true,
"isFocusOnShow": true,
"reorderEnabled": true,
"title": "",
"height": 61.803,
"activeItemIndex": 0,
"content": [
{
"type": "react-component",
"component": "test-a",
"title": "test-a"
},
{
"type": "react-component",
"component": "test-b",
"title": "test-b"
},
{
"type": "react-component",
"component": "test-c",
"title": "test-c"
},
{
"type": "react-component",
"component": "test-d",
"title": "test-d"
},
{
"type": "react-component",
"component": "test-e",
"title": "test-e"
},
{
"type": "react-component",
"component": "test-f",
"title": "test-f"
},
{
"type": "react-component",
"component": "test-g",
"title": "test-g"
},
{
"type": "react-component",
"component": "test-h",
"title": "test-h"
},
{
"type": "react-component",
"component": "test-i",
"title": "test-i"
},
{
"type": "react-component",
"component": "test-j",
"title": "test-j"
},
{
"type": "react-component",
"component": "test-k",
"title": "test-k"
},
{
"type": "react-component",
"component": "test-l",
"title": "test-l"
},
{
"type": "react-component",
"component": "test-m",
"title": "test-m"
},
{
"type": "react-component",
"component": "test-n",
"title": "test-n"
},
{
"type": "react-component",
"component": "test-o",
"title": "test-o"
},
{
"type": "react-component",
"component": "test-p",
"title": "test-p"
},
{
"type": "react-component",
"component": "test-q",
"title": "test-q"
},
{
"type": "react-component",
"component": "test-r",
"title": "test-r"
},
{
"type": "react-component",
"component": "test-s",
"title": "test-s"
},
{
"type": "react-component",
"component": "test-t",
"title": "test-t"
},
{
"type": "react-component",
"component": "test-u",
"title": "test-u"
},
{
"type": "react-component",
"component": "test-v",
"title": "test-v"
},
{
"type": "react-component",
"component": "test-w",
"title": "test-w"
},
{
"type": "react-component",
"component": "test-x",
"title": "test-x"
},
{
"type": "react-component",
"component": "test-y",
"title": "test-y"
},
{
"type": "react-component",
"component": "test-z",
"title": "test-z"
}
]
},
{
"type": "react-component",
"component": "test"
}
]
},
{
"type": "column",
"width": 38.197,
"content": [
{
"type": "react-component",
"component": "test",
"height": 61.803
},
{
"type": "row",
"content": [
{
"type": "column",
"width": 61.803,
"content": [
{
"type": "row",
"content": [
{
"type": "react-component",
"component": "test",
"width": 61.803
},
{
"type": "column",
"content": [
{
"type": "react-component",
"component": "test",
"height": 61.803
},
{
"type": "row",
"content": [
{
"type": "react-component",
"component": "test"
},
{
"type": "react-component",
"component": "test",
"width": 61.803
}
]
}
]
}
]
},
{
"type": "react-component",
"component": "test",
"height": 38.197
}
]
},
{
"type": "react-component",
"component": "test",
"width": 61.803
}
]
}
]
}
]
}
]
}
],
"links": [],
"version": 2
}
143 changes: 143 additions & 0 deletions tests/golden-layout.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import { test, expect, Page } from '@playwright/test';

// Run tests serially
test.describe.configure({ mode: 'serial' });

test.describe('tests golden-layout operations', () => {
let page: Page;

test.beforeAll(async ({ browser }) => {
page = await browser.newPage();
await page.goto('');

// reset the layout before each test
await page.getByTestId('app-main-panels-button').click();
// start listener before click
const fileChooserPromise = page.waitForEvent('filechooser');
await page.locator('button:has-text("Import Layout")').click();
const fileChooser = await fileChooserPromise;
// load a test layout that uses the panel placeholder
await fileChooser.setFiles('tests/deephaven-app-layout.test.json');

// expect a tab "test-a" to have been successfully loaded
await expect(
page.locator('.lm_tab').filter({ has: page.getByText('test-a') })
).toHaveCount(1);
});

test.afterAll(async () => {
// reset layout
await page.getByTestId('app-main-panels-button').click();
await page.getByLabel('Reset Layout').click();

await expect(
page.locator('.lm_tab').filter({ has: page.getByText('test-a') })
).toHaveCount(0);
});

test('golden-layout can import a layout', async () => {
// general overall visual check of layout
await expect(page.locator('.lm_root')).toHaveScreenshot();
});

test('golden-layout can maximize the first stack', async () => {
await page.getByTitle('Maximize').first().click();
// visual check for maximized tab
await expect(page.locator('.lm_root')).toHaveScreenshot();

// minimize it again for next test
await page.getByTitle('Minimize').first().click();
await expect(page.getByTitle('Minimize')).toHaveCount(0);
});

test('golden-layout can use additional tabs menu', async () => {
// open the first additional tab drop down
await page.getByTitle('Additional tabs').first().click();

// check snapshot
await expect(
page.locator('.lm_tabdropdown_list').locator('visible=true')
).toHaveScreenshot();

// test search
await page
.getByPlaceholder('Find tab...')
.locator('visible=true')
.fill('test-z');

// check that drop-down is filtered screenshot
await expect(
page.locator('.lm_tabdropdown_list').locator('visible=true')
).toHaveScreenshot();

await page
.locator('.lm_tabdropdown_list')
.locator('visible=true')
.getByText('test-z')
.click();

// check that it is shown in header as expected
// and visuals are styled correctly, scrolled into view etc
await expect(page.locator('.lm_header').first()).toHaveScreenshot();

// check that the selected panel is open
await expect(
page.locator('.test-z-component').locator('.panel-placeholder')
).toHaveText('Component "test-z" is not registered.');
});

test('golden-layout can close a tab', async () => {
await page
.locator('.lm_tab')
.filter({ has: page.getByText('test-y') })
.getByLabel('Close tab')
.click();

// check that the selected panel is open
await expect(page.getByText('test-y')).toHaveCount(0);

// check middle click closes tab
await page
.locator('.lm_tab')
.filter({ has: page.getByText('test-x') })
.getByLabel('Close tab')
.click({ button: 'middle' });

// check that the selected panel is open
await expect(page.getByText('test-x')).toHaveCount(0);
});

test('golden-layout can drag tab to left edge', async () => {
const dragTab = await page
.locator('.lm_tab')
.filter({ has: page.getByText('test-z') });

const dropTargetIndicator = page.locator('.lm_dropTargetIndicator');

// manual drag so we can take screenshot of indicator
await dragTab.hover();
await page.mouse.down();
await page.mouse.move(10, 100);

// check that the drop target indicator is visible
await expect(dropTargetIndicator).toBeVisible();

// remove the marching ants animation so we can take consistent screen shot
await dropTargetIndicator.evaluate(element => {
// eslint-disable-next-line no-param-reassign
element.style.animation = 'none';
});

// check the drop indicator
await expect(dropTargetIndicator).toHaveScreenshot();

// check the drag proxy
await expect(page.locator('.lm_dragProxy')).toHaveScreenshot();

// drop item
await page.mouse.up();

// check new layout
await expect(page.locator('.lm_root')).toHaveScreenshot();
});
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 485c7cc

Please sign in to comment.