Repository: facebook/react
Pull request: Proof of Concept for E2E tests using playwright

<!--
  Thanks for submitting a pull request!
  We appreciate you spending the time to work on these changes. Please provide enough information so that others can review your pull request. The three fields below are mandatory.

  Before submitting a pull request, please make sure the following is done:

  1. Fork [the repository](https://github.com/facebook/react) and create your branch from `main`.
  2. Run `yarn` in the repository root.
  3. If you've fixed a bug or added code that should be tested, add tests!
  4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch TestName` is helpful in development.
  5. Run `yarn test --prod` to test in the production environment. It supports the same options as `yarn test`.
  6. If you need a debugger, run `yarn debug-test --watch TestName`, open `chrome://inspect`, and press "Inspect".
  7. Format your code with [prettier](https://github.com/prettier/prettier) (`yarn prettier`).
  8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only check changed files.
  9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
  10. If you haven't already, complete the CLA.

  Learn more about contributing: https://reactjs.org/docs/how-to-contribute.html
-->

## Summary
Detailed discussion here : #22646 
This PR is just a starting point for writing E2E tests for inline package with playwright.

## What does the test do ?
It checks the components(ToDo List) and emulates it in the devtools by clicking and inspecting.
Then it matches the props with component props.

## How did you test this change?
run `yarn test` in `react-devtools-inline` package.

## Quick Demo 👀
https://user-images.githubusercontent.com/51379307/141653443-85d0eb8f-1f43-47c9-8f09-7f2ff63c2ca4.mp4

## Description of some other changes
Removed hashing on CSS styles to write tests easily. This has no impact on the Styling or any visual changes on test apps in `react-devtools-shell`.

Changed files:
filename: packages/react-devtools-inline/__tests__/__e2e__/inspecting-props.test.js
patch: @@ -0,0 +1,50 @@
+'use strict';
+
+const {test, expect} = require('@playwright/test');
+const config = require('../../playwright.config');
+test.use(config);
+
+test.describe('Testing Todo-List App', () => {
+  let page, frameElementHandle, frame;
+  test.beforeAll(async ({browser}) => {
+    page = await browser.newPage();
+    await page.goto('http://localhost:8080/', {waitUntil: 'domcontentloaded'});
+    await page.waitForSelector('iframe#target');
+    frameElementHandle = await page.$('#target');
+    frame = await frameElementHandle.contentFrame();
+  });
+
+  test('The Todo List should contain 3 items by default', async () => {
+    const list = frame.locator('.listitem');
+    await expect(list).toHaveCount(3);
+  });
+
+  test('Add another item Fourth to list', async () => {
+    await frame.type('.input', 'Fourth');
+    await frame.click('button.iconbutton');
+    const listItems = await frame.locator('.label');
+    await expect(listItems).toHaveText(['First', 'Second', 'Third', 'Fourth']);
+  });
+
+  test('Inspecting list elements with devtools', async () => {
+    // Component props are used as string in devtools.
+    const listItemsProps = [
+      '',
+      '{id: 1, isComplete: true, text: "First"}',
+      '{id: 2, isComplete: true, text: "Second"}',
+      '{id: 3, isComplete: false, text: "Third"}',
+      '{id: 4, isComplete: false, text: "Fourth"}',
+    ];
+    const countOfItems = await frame.$$eval('.listitem', el => el.length);
+    // For every item in list click on devtools inspect icon
+    // click on the list item to quickly navigate to the list item component in devtools
+    // comparing displayed props with the array of props.
+    for (let i = 1; i <= countOfItems; ++i) {
+      await page.click('[class^=ToggleContent]', {delay: 100});
+      await frame.click(`.listitem:nth-child(${i})`, {delay: 50});
+      await page.waitForSelector('span.Value___tNzum');
+      const text = await page.innerText('span[class^=Value]');
+      await expect(text).toEqual(listItemsProps[i]);
+    }
+  });
+});

filename: packages/react-devtools-inline/package.json
patch: @@ -19,7 +19,8 @@
   "scripts": {
     "build": "cross-env NODE_ENV=production webpack --config webpack.config.js",
     "prepublish": "yarn run build",
-    "start": "cross-env NODE_ENV=development webpack --config webpack.config.js --watch"
+    "start": "cross-env NODE_ENV=development webpack --config webpack.config.js --watch",
+    "test:e2e": "playwright test --config=playwright.config.js"
   },
   "dependencies": {
     "source-map-js": "^0.6.2",
@@ -33,6 +34,7 @@
     "@babel/preset-env": "^7.11.0",
     "@babel/preset-flow": "^7.10.4",
     "@babel/preset-react": "^7.10.4",
+    "@playwright/test": "^1.16.3",
     "babel-core": "^7.0.0-bridge",
     "babel-eslint": "^9.0.0",
     "babel-loader": "^8.0.4",

filename: packages/react-devtools-inline/playwright.config.js
patch: @@ -0,0 +1,11 @@
+const config = {
+  use: {
+    headless: false,
+    browserName: 'chromium',
+    launchOptions: {
+      slowMo: 100,
+    },
+  },
+};
+
+module.exports = config;

filename: packages/react-devtools-shell/webpack.config.js
patch: @@ -107,7 +107,7 @@ const config = {
             options: {
               sourceMap: true,
               modules: true,
-              localIdentName: '[local]___[hash:base64:5]',
+              localIdentName: '[local]',
             },
           },
         ],