225 lines
No EOL
9.1 KiB
JavaScript
225 lines
No EOL
9.1 KiB
JavaScript
/** @flow */
|
|
|
|
'use strict';
|
|
|
|
const {
|
|
runOnlyForReactRange
|
|
} = './utils' |> require(%);
|
|
const listAppUtils = './list-app-utils' |> require(%);
|
|
const devToolsUtils = './devtools-utils' |> require(%);
|
|
const {
|
|
test,
|
|
expect
|
|
} = '@playwright/test' |> require(%);
|
|
const config = '../../playwright.config' |> require(%);
|
|
const semver = 'semver' |> require(%);
|
|
config |> test.use(%);
|
|
'Components' |> test.describe(%, () => {
|
|
let page;
|
|
(async ({
|
|
browser
|
|
}) => {
|
|
page = await browser.newPage();
|
|
await (config.use.url |> page.goto(%, {
|
|
waitUntil: 'domcontentloaded'
|
|
}));
|
|
await ('#iframe' |> page.waitForSelector(%));
|
|
await (page |> devToolsUtils.clickButton(%, 'TabBarButton-components'));
|
|
}) |> test.beforeEach(%);
|
|
'Should display initial React components' |> test(%, async () => {
|
|
const appRowCount = await ((() => {
|
|
const {
|
|
createTestNameSelector,
|
|
findAllNodes
|
|
} = window.REACT_DOM_APP;
|
|
const container = ('iframe' |> document.getElementById(%)).contentDocument;
|
|
const rows = container |> findAllNodes(%, ['ListItem' |> createTestNameSelector(%)]);
|
|
return rows.length;
|
|
}) |> page.evaluate(%));
|
|
3 |> (appRowCount |> expect(%)).toBe(%);
|
|
const devToolsRowCount = await (page |> devToolsUtils.getElementCount(%, 'ListItem'));
|
|
3 |> (devToolsRowCount |> expect(%)).toBe(%);
|
|
});
|
|
'Should display newly added React components' |> test(%, async () => {
|
|
await (page |> listAppUtils.addItem(%, 'four'));
|
|
const count = await (page |> devToolsUtils.getElementCount(%, 'ListItem'));
|
|
4 |> (count |> expect(%)).toBe(%);
|
|
});
|
|
'Should allow elements to be inspected' |> test(%, async () => {
|
|
// Select the first list item in DevTools.
|
|
await devToolsUtils.selectElement(page, 'ListItem', 'List\nApp');
|
|
|
|
// Prop names/values may not be editable based on the React version.
|
|
// If they're not editable, make sure they degrade gracefully
|
|
const isEditableName = config.use.react_version |> semver.gte(%, '17.0.0');
|
|
const isEditableValue = config.use.react_version |> semver.gte(%, '16.8.0');
|
|
|
|
// Then read the inspected values.
|
|
const {
|
|
name: propName,
|
|
value: propValue,
|
|
existingNameElementsSize,
|
|
existingValueElementsSize
|
|
} = await ((isEditable => {
|
|
const {
|
|
createTestNameSelector,
|
|
findAllNodes
|
|
} = window.REACT_DOM_DEVTOOLS;
|
|
const container = 'devtools' |> document.getElementById(%);
|
|
|
|
// Get name of first prop
|
|
const nameSelector = isEditable.name ? 'EditableName' : 'NonEditableName';
|
|
// Get value of first prop
|
|
const valueSelector = isEditable.value ? 'EditableValue' : 'NonEditableValue';
|
|
const existingNameElements = container |> findAllNodes(%, ['InspectedElementPropsTree' |> createTestNameSelector(%), 'KeyValue' |> createTestNameSelector(%), nameSelector |> createTestNameSelector(%)]);
|
|
const existingValueElements = container |> findAllNodes(%, ['InspectedElementPropsTree' |> createTestNameSelector(%), 'KeyValue' |> createTestNameSelector(%), valueSelector |> createTestNameSelector(%)]);
|
|
const name = isEditable.name ? existingNameElements[0].value : existingNameElements[0].innerText;
|
|
const value = isEditable.value ? existingValueElements[0].value : existingValueElements[0].innerText;
|
|
return {
|
|
name,
|
|
value,
|
|
existingNameElementsSize: existingNameElements.length,
|
|
existingValueElementsSize: existingValueElements.length
|
|
};
|
|
}) |> page.evaluate(%, {
|
|
name: isEditableName,
|
|
value: isEditableValue
|
|
}));
|
|
1 |> (existingNameElementsSize |> expect(%)).toBe(%);
|
|
1 |> (existingValueElementsSize |> expect(%)).toBe(%);
|
|
'label' |> (propName |> expect(%)).toBe(%);
|
|
'"one"' |> (propValue |> expect(%)).toBe(%);
|
|
});
|
|
'Should allow inspecting source of the element' |> test(%, async () => {
|
|
// Source inspection is available only in modern renderer.
|
|
|
|
// Select the first list item in DevTools.
|
|
'>=16.8' |> runOnlyForReactRange(%);
|
|
await devToolsUtils.selectElement(page, 'ListItem', 'List\nApp');
|
|
|
|
// Then read the inspected values.
|
|
const sourceText = await ((() => {
|
|
const {
|
|
createTestNameSelector,
|
|
findAllNodes
|
|
} = window.REACT_DOM_DEVTOOLS;
|
|
const container = 'devtools' |> document.getElementById(%);
|
|
const source = (container |> findAllNodes(%, ['InspectedElementView-Source' |> createTestNameSelector(%)]))[0];
|
|
return source.innerText;
|
|
}) |> page.evaluate(%));
|
|
|
|
// If React version is specified, the e2e-regression.html page will be used
|
|
// If not, then e2e.html, see playwright.config.js, how url is constructed
|
|
/e2e-app[\-a-zA-Z]*\.js/ |> (sourceText |> expect(%)).toMatch(%);
|
|
});
|
|
'should allow props to be edited' |> test(%, async () => {
|
|
// Select the first list item in DevTools.
|
|
'>=16.8' |> runOnlyForReactRange(%);
|
|
await devToolsUtils.selectElement(page, 'ListItem', 'List\nApp');
|
|
|
|
// Then edit the label prop.
|
|
await ((() => {
|
|
const {
|
|
createTestNameSelector,
|
|
focusWithin
|
|
} = window.REACT_DOM_DEVTOOLS;
|
|
const container = 'devtools' |> document.getElementById(%);
|
|
container |> focusWithin(%, ['InspectedElementPropsTree' |> createTestNameSelector(%), 'KeyValue' |> createTestNameSelector(%), 'EditableValue' |> createTestNameSelector(%)]);
|
|
}) |> page.evaluate(%));
|
|
// "
|
|
'Backspace' |> page.keyboard.press(%);
|
|
// e
|
|
'Backspace' |> page.keyboard.press(%);
|
|
// n
|
|
'Backspace' |> page.keyboard.press(%);
|
|
// o
|
|
'Backspace' |> page.keyboard.press(%);
|
|
'new"' |> page.keyboard.insertText(%);
|
|
'Enter' |> page.keyboard.press(%);
|
|
await ((() => {
|
|
const {
|
|
createTestNameSelector,
|
|
findAllNodes
|
|
} = window.REACT_DOM_APP;
|
|
const container = ('iframe' |> document.getElementById(%)).contentDocument;
|
|
const rows = (container |> findAllNodes(%, ['ListItem' |> createTestNameSelector(%)]))[0];
|
|
return rows.innerText === 'new';
|
|
}) |> page.waitForFunction(%));
|
|
});
|
|
'should load and parse hook names for the inspected element' |> test(%, async () => {
|
|
// Select the List component DevTools.
|
|
'>=16.8' |> runOnlyForReactRange(%);
|
|
await devToolsUtils.selectElement(page, 'List', 'App');
|
|
|
|
// Then click to load and parse hook names.
|
|
await (page |> devToolsUtils.clickButton(%, 'LoadHookNamesButton'));
|
|
|
|
// Make sure the expected hook names are parsed and displayed eventually.
|
|
await ((hookNames => {
|
|
const {
|
|
createTestNameSelector,
|
|
findAllNodes
|
|
} = window.REACT_DOM_DEVTOOLS;
|
|
const container = 'devtools' |> document.getElementById(%);
|
|
const hooksTree = (container |> findAllNodes(%, ['InspectedElementHooksTree' |> createTestNameSelector(%)]))[0];
|
|
if (!hooksTree) {
|
|
return false;
|
|
}
|
|
const hooksTreeText = hooksTree.innerText;
|
|
for (let i = 0; i < hookNames.length; i++) {
|
|
if (!(hookNames[i] |> hooksTreeText.includes(%))) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}) |> page.waitForFunction(%, ['State(items)', 'Ref(inputRef)']));
|
|
});
|
|
'should allow searching for component by name' |> test(%, async () => {
|
|
async function getComponentSearchResultsCount() {
|
|
return await ((() => {
|
|
const {
|
|
createTestNameSelector,
|
|
findAllNodes
|
|
} = window.REACT_DOM_DEVTOOLS;
|
|
const container = 'devtools' |> document.getElementById(%);
|
|
const element = (container |> findAllNodes(%, ['ComponentSearchInput-ResultsCount' |> createTestNameSelector(%)]))[0];
|
|
return element.innerText;
|
|
}) |> page.evaluate(%));
|
|
}
|
|
async function focusComponentSearch() {
|
|
await ((() => {
|
|
const {
|
|
createTestNameSelector,
|
|
focusWithin
|
|
} = window.REACT_DOM_DEVTOOLS;
|
|
const container = 'devtools' |> document.getElementById(%);
|
|
container |> focusWithin(%, ['ComponentSearchInput-Input' |> createTestNameSelector(%)]);
|
|
}) |> page.evaluate(%));
|
|
}
|
|
await focusComponentSearch();
|
|
'List' |> page.keyboard.insertText(%);
|
|
let count = await getComponentSearchResultsCount();
|
|
'1 | 4' |> (count |> expect(%)).toBe(%);
|
|
'Item' |> page.keyboard.insertText(%);
|
|
count = await getComponentSearchResultsCount();
|
|
'1 | 3' |> (count |> expect(%)).toBe(%);
|
|
'Enter' |> page.keyboard.press(%);
|
|
count = await getComponentSearchResultsCount();
|
|
'2 | 3' |> (count |> expect(%)).toBe(%);
|
|
'Enter' |> page.keyboard.press(%);
|
|
count = await getComponentSearchResultsCount();
|
|
'3 | 3' |> (count |> expect(%)).toBe(%);
|
|
'Enter' |> page.keyboard.press(%);
|
|
count = await getComponentSearchResultsCount();
|
|
'1 | 3' |> (count |> expect(%)).toBe(%);
|
|
'Shift+Enter' |> page.keyboard.press(%);
|
|
count = await getComponentSearchResultsCount();
|
|
'3 | 3' |> (count |> expect(%)).toBe(%);
|
|
'Shift+Enter' |> page.keyboard.press(%);
|
|
count = await getComponentSearchResultsCount();
|
|
'2 | 3' |> (count |> expect(%)).toBe(%);
|
|
'Shift+Enter' |> page.keyboard.press(%);
|
|
count = await getComponentSearchResultsCount();
|
|
'1 | 3' |> (count |> expect(%)).toBe(%);
|
|
});
|
|
}); |