diff --git a/scripts/eslint_rules/lib/ban_screenshot_test_outside_perf_panel.js b/scripts/eslint_rules/lib/ban_screenshot_test_outside_perf_panel.js new file mode 100644 index 0000000000..ec99c2baca --- /dev/null +++ b/scripts/eslint_rules/lib/ban_screenshot_test_outside_perf_panel.js @@ -0,0 +1,44 @@ +// Copyright 2023 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +'use strict'; + +const path = require('path'); +const PERFOMANCE_PANEL_INTERACTION_TESTS_PATH = + path.join(__dirname, '..', '..', '..', 'test', 'interactions', 'panels', 'performance'); +module.exports = { + meta : { + type : 'problem', + + docs : { + description : 'Bans writting screenshot tests outside the directory for the Performance Panel interaction tests.', + category : 'Possible Errors', + }, + fixable : 'code', + messages : { + invalidScreenshotTest : 'It is banned to write screenshot tests outside the directory of the Performance Panel interaction tests.', + }, + schema : [] + }, + create : function(context) { + const fileName = path.resolve(context.getFilename()); + function reportPathIfInvalid(node) { + if(!fileName.includes(PERFOMANCE_PANEL_INTERACTION_TESTS_PATH)) { + context.report({ + node, + messageId: 'invalidScreenshotTest' + }); + } + } + + return { + 'CallExpression[callee.type="Identifier"][callee.name="itScreenshot"], MemberExpression'(node) { + const isScreenshotTest = node.type === 'CallExpression'; + const isSkippedScreenshotTest = (node.property?.name === 'skip' && node.object?.name === 'itScreenshot' ); + if (isScreenshotTest || isSkippedScreenshotTest) { + reportPathIfInvalid(node); + } + }, + }; + } +}; diff --git a/scripts/eslint_rules/tests/ban_screenshot_test_outside_perf_panel_test.js b/scripts/eslint_rules/tests/ban_screenshot_test_outside_perf_panel_test.js new file mode 100644 index 0000000000..c723ccbabf --- /dev/null +++ b/scripts/eslint_rules/tests/ban_screenshot_test_outside_perf_panel_test.js @@ -0,0 +1,100 @@ +// Copyright 2023 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +'use strict'; + +const rule = require('../lib/ban_screenshot_test_outside_perf_panel.js'); +const ruleTester = new (require('eslint').RuleTester)({ + parserOptions: {ecmaVersion: 9, sourceType: 'module'}, +}); + +const EXPECTED_ERROR_MESSAGE = + 'It is banned to write screenshot tests outside the directory of the Performance Panel interaction tests.'; + +const enabledTestCode = `describe('Performance panel', () => { + itScreenshot('renders the timeline correctly', async () => { + await loadComponentDocExample('performance_panel/basic.html?trace=animation'); + await waitFor('#timeline-overview-panel'); + const panel = await waitFor('body'); + await assertElementScreenshotUnchanged(panel, 'performance/timeline.png'); + }); + });`; + +const disabledTestCode = `describe('Performance panel', () => { + // Disabled until screenshot tests infrastructure is available in DevTools bots. + itScreenshot.skip('[crbug.com/1407638] renders the timeline correctly', async () => { + await waitFor('#timeline-overview-panel'); + const panel = await waitFor('body'); + await assertElementScreenshotUnchanged(panel, 'performance/timeline.png'); + }); + });`; + +const notAScreenshotTestCode = `describe('Performance panel', () => { + it('renders the timeline correctly', async () => { + await waitFor('#timeline-overview-panel'); + const panel = await waitFor('body'); + await assertElementScreenshotUnchanged(panel, 'performance/timeline.png'); + }); + });`; + +const notAScreenshotTestDisabledCode = `describe('Performance panel', () => { + // This is disabled. + it.skip('[crbug.com/1407638] renders the timeline correctly', async () => { + await waitFor('#timeline-overview-panel'); + const panel = await waitFor('body'); + await assertElementScreenshotUnchanged(panel, 'performance/timeline.png'); + }); +});`; + +const perfPanelInteractionTestsPath = 'test/interactions/panels/performance/'; +const notPerfPanelTestPath = 'test/interactions/data_grid/data_grid_test.ts'; + +ruleTester.run('ban_screenshot_test_outside_perf_panel', rule, { + valid: [ + { + code: enabledTestCode, + filename: `${perfPanelInteractionTestsPath}timeline/timeline_test.ts`, + }, + { + code: disabledTestCode, + filename: `${perfPanelInteractionTestsPath}timeline/timeline_test.ts`, + }, + { + code: enabledTestCode, + filename: `${perfPanelInteractionTestsPath}user_timings/user_imings_test.ts`, + }, + { + code: disabledTestCode, + filename: `${perfPanelInteractionTestsPath}user_timings/user_imings_test.ts`, + }, + { + code: notAScreenshotTestCode, + filename: notPerfPanelTestPath, + }, + { + code: notAScreenshotTestDisabledCode, + filename: notPerfPanelTestPath, + }, + { + code: notAScreenshotTestDisabledCode, + filename: `${perfPanelInteractionTestsPath}timeline/timeline_test.ts`, + }, + ], + invalid: [ + { + code: enabledTestCode, + filename: notPerfPanelTestPath, + errors: [{message: EXPECTED_ERROR_MESSAGE}], + }, + { + code: disabledTestCode, + filename: notPerfPanelTestPath, + errors: [{message: EXPECTED_ERROR_MESSAGE}], + }, + { + code: enabledTestCode, + filename: 'test/unittests/front_end/panels/performance/timeline_test.ts', + errors: [{message: EXPECTED_ERROR_MESSAGE}], + }, + ] +}); diff --git a/test/.eslintrc.js b/test/.eslintrc.js index b05a0dd249..ea05567448 100644 --- a/test/.eslintrc.js +++ b/test/.eslintrc.js @@ -17,6 +17,7 @@ module.exports = { 'rulesdir/avoid_assert_equal' : 2, 'rulesdir/no_repeated_tests' : 2, 'rulesdir/compare_arrays_with_assert_deepequal' : 2, + 'rulesdir/ban_screenshot_test_outside_perf_panel' : 2, }, 'overrides' : [{ 'files' : ['*.ts'],