From 503f74da9089cff4425840a5b297ed5a62a8c15b Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Fri, 8 Nov 2024 17:18:51 -0800 Subject: [PATCH] chore: allow editing aria template in recorder (tests) (#33522) --- package-lock.json | 11 +-- .../playwright-core/ThirdPartyNotices.txt | 6 +- .../src/server/injected/ariaSnapshot.ts | 11 +-- .../src/server/injected/recorder/recorder.ts | 8 +- .../src/utils/isomorphic/ariaSnapshot.ts | 2 + packages/playwright/ThirdPartyNotices.txt | 6 +- packages/recorder/src/recorder.tsx | 38 ++++---- packages/web/package.json | 2 +- .../web/src/components/codeMirrorModule.tsx | 20 ++--- .../web/src/components/codeMirrorWrapper.tsx | 11 ++- .../inspector/cli-codegen-aria.spec.ts | 87 +++++++++++++++++++ tests/library/inspector/pause.spec.ts | 19 ++-- tests/page/locator-highlight.spec.ts | 14 +-- tests/page/pageTest.ts | 12 ++- utils/generate_third_party_notice.js | 2 +- 15 files changed, 166 insertions(+), 83 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0a39fa4283..b3f2856eec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2910,10 +2910,11 @@ "periscopic": "^3.1.0" } }, - "node_modules/codemirror-shadow-1": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/codemirror-shadow-1/-/codemirror-shadow-1-0.0.1.tgz", - "integrity": "sha512-kD3OZpCCHr3LHRKfbGx5IogHTWq4Uo9jH2bXPVa7/n6ppkgI66rx4tniQY1BpqWp/JNhQmQsXhQoaZ1TH6t0xQ==" + "node_modules/codemirror": { + "version": "5.65.18", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.18.tgz", + "integrity": "sha512-Gaz4gHnkbHMGgahNt3CA5HBk5lLQBqmD/pBgeB4kQU6OedZmqMBjlRF0LSrp2tJ4wlLNPm2FfaUd1pDy0mdlpA==", + "license": "MIT" }, "node_modules/color-convert": { "version": "1.9.3", @@ -8112,7 +8113,7 @@ "packages/web": { "version": "0.0.0", "dependencies": { - "codemirror-shadow-1": "0.0.1", + "codemirror": "5.65.18", "xterm": "^5.1.0", "xterm-addon-fit": "^0.7.0" } diff --git a/packages/playwright-core/ThirdPartyNotices.txt b/packages/playwright-core/ThirdPartyNotices.txt index 71ac7d1bed..457f3e632b 100644 --- a/packages/playwright-core/ThirdPartyNotices.txt +++ b/packages/playwright-core/ThirdPartyNotices.txt @@ -10,7 +10,7 @@ This project incorporates components from the projects listed below. The origina - balanced-match@1.0.2 (https://github.com/juliangruber/balanced-match) - brace-expansion@1.1.11 (https://github.com/juliangruber/brace-expansion) - buffer-crc32@0.2.13 (https://github.com/brianloveswords/buffer-crc32) -- codemirror-shadow-1@0.0.1 (https://github.com/codemirror/CodeMirror) +- codemirror@5.65.18 (https://github.com/codemirror/CodeMirror) - colors@1.4.0 (https://github.com/Marak/colors.js) - commander@8.3.0 (https://github.com/tj/commander.js) - concat-map@0.0.1 (https://github.com/substack/node-concat-map) @@ -208,7 +208,7 @@ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEAL ========================================= END OF buffer-crc32@0.2.13 AND INFORMATION -%% codemirror-shadow-1@0.0.1 NOTICES AND INFORMATION BEGIN HERE +%% codemirror@5.65.18 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -232,7 +232,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF codemirror-shadow-1@0.0.1 AND INFORMATION +END OF codemirror@5.65.18 AND INFORMATION %% colors@1.4.0 NOTICES AND INFORMATION BEGIN HERE ========================================= diff --git a/packages/playwright-core/src/server/injected/ariaSnapshot.ts b/packages/playwright-core/src/server/injected/ariaSnapshot.ts index d1aa9ce637..06de76c820 100644 --- a/packages/playwright-core/src/server/injected/ariaSnapshot.ts +++ b/packages/playwright-core/src/server/injected/ariaSnapshot.ts @@ -204,7 +204,7 @@ export type MatcherReceived = { export function matchesAriaTree(rootElement: Element, template: AriaTemplateNode): { matches: AriaNode[], received: MatcherReceived } { const root = generateAriaTree(rootElement); - const matches = matchesNodeDeep(root, template); + const matches = matchesNodeDeep(root, template, false); return { matches, received: { @@ -215,8 +215,9 @@ export function matchesAriaTree(rootElement: Element, template: AriaTemplateNode } export function getAllByAria(rootElement: Element, template: AriaTemplateNode): Element[] { - const result = matchesAriaTree(rootElement, template); - return result.matches.map(n => n.element); + const root = generateAriaTree(rootElement); + const matches = matchesNodeDeep(root, template, true); + return matches.map(n => n.element); } function matchesNode(node: AriaNode | string, template: AriaTemplateNode, depth: number): boolean { @@ -265,12 +266,12 @@ function containsList(children: (AriaNode | string)[], template: AriaTemplateNod return true; } -function matchesNodeDeep(root: AriaNode, template: AriaTemplateNode): AriaNode[] { +function matchesNodeDeep(root: AriaNode, template: AriaTemplateNode, collectAll: boolean): AriaNode[] { const results: AriaNode[] = []; const visit = (node: AriaNode | string): boolean => { if (matchesNode(node, template, 0)) { results.push(node as AriaNode); - return true; + return !collectAll; } if (typeof node === 'string') return false; diff --git a/packages/playwright-core/src/server/injected/recorder/recorder.ts b/packages/playwright-core/src/server/injected/recorder/recorder.ts index 3bf9eeebf5..1828af3bd0 100644 --- a/packages/playwright-core/src/server/injected/recorder/recorder.ts +++ b/packages/playwright-core/src/server/injected/recorder/recorder.ts @@ -207,9 +207,9 @@ class InspectTool implements RecorderTool { class RecordActionTool implements RecorderTool { private _recorder: Recorder; private _performingActions = new Set(); - private _hoveredModel: HighlightModeWithSelector | null = null; + private _hoveredModel: HighlightModelWithSelector | null = null; private _hoveredElement: HTMLElement | null = null; - private _activeModel: HighlightModeWithSelector | null = null; + private _activeModel: HighlightModelWithSelector | null = null; private _expectProgrammaticKeyUp = false; private _pendingClickAction: { action: actions.ClickAction, timeout: number } | undefined; @@ -605,7 +605,7 @@ class RecordActionTool implements RecorderTool { class TextAssertionTool implements RecorderTool { private _recorder: Recorder; - private _hoverHighlight: HighlightModeWithSelector | null = null; + private _hoverHighlight: HighlightModelWithSelector | null = null; private _action: actions.AssertAction | null = null; private _dialog: Dialog; private _textCache = new Map(); @@ -1460,7 +1460,7 @@ type HighlightModel = HighlightOptions & { elements: Element[]; }; -type HighlightModeWithSelector = HighlightModel & { +type HighlightModelWithSelector = HighlightModel & { selector: string; }; diff --git a/packages/playwright-core/src/utils/isomorphic/ariaSnapshot.ts b/packages/playwright-core/src/utils/isomorphic/ariaSnapshot.ts index aae5fb3e03..67db465149 100644 --- a/packages/playwright-core/src/utils/isomorphic/ariaSnapshot.ts +++ b/packages/playwright-core/src/utils/isomorphic/ariaSnapshot.ts @@ -52,6 +52,8 @@ export type AriaTemplateNode = AriaTemplateRoleNode | AriaTemplateTextNode; export function parseYamlTemplate(fragment: ParsedYaml): AriaTemplateNode { const result: AriaTemplateNode = { kind: 'role', role: 'fragment' }; populateNode(result, fragment); + if (result.children && result.children.length === 1) + return result.children[0]; return result; } diff --git a/packages/playwright/ThirdPartyNotices.txt b/packages/playwright/ThirdPartyNotices.txt index 2931da55c9..c572f8daee 100644 --- a/packages/playwright/ThirdPartyNotices.txt +++ b/packages/playwright/ThirdPartyNotices.txt @@ -97,7 +97,7 @@ This project incorporates components from the projects listed below. The origina - chalk@4.1.2 (https://github.com/chalk/chalk) - chokidar@3.6.0 (https://github.com/paulmillr/chokidar) - ci-info@3.9.0 (https://github.com/watson/ci-info) -- codemirror-shadow-1@0.0.1 (https://github.com/codemirror/CodeMirror) +- codemirror@5.65.18 (https://github.com/codemirror/CodeMirror) - color-convert@1.9.3 (https://github.com/Qix-/color-convert) - color-convert@2.0.1 (https://github.com/Qix-/color-convert) - color-name@1.1.3 (https://github.com/dfcreative/color-name) @@ -3103,7 +3103,7 @@ SOFTWARE. ========================================= END OF ci-info@3.9.0 AND INFORMATION -%% codemirror-shadow-1@0.0.1 NOTICES AND INFORMATION BEGIN HERE +%% codemirror@5.65.18 NOTICES AND INFORMATION BEGIN HERE ========================================= MIT License @@ -3127,7 +3127,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ========================================= -END OF codemirror-shadow-1@0.0.1 AND INFORMATION +END OF codemirror@5.65.18 AND INFORMATION %% color-convert@1.9.3 NOTICES AND INFORMATION BEGIN HERE ========================================= diff --git a/packages/recorder/src/recorder.tsx b/packages/recorder/src/recorder.tsx index 6488883b7d..65d8fbf117 100644 --- a/packages/recorder/src/recorder.tsx +++ b/packages/recorder/src/recorder.tsx @@ -29,7 +29,6 @@ import { asLocator } from '@isomorphic/locatorGenerators'; import { toggleTheme } from '@web/theme'; import { copy } from '@web/uiUtils'; import yaml from 'yaml'; -import type { YAMLError } from 'yaml'; import { parseAriaKey } from '@isomorphic/ariaSnapshot'; import type { AriaKeyError, ParsedYaml } from '@isomorphic/ariaSnapshot'; @@ -199,7 +198,7 @@ export const Recorder: React.FC = ({ { id: 'aria', title: 'Aria snapshot', - render: () => + render: () => }, ]} selectedTab={selectedTab} @@ -211,32 +210,31 @@ export const Recorder: React.FC = ({ function parseAriaSnapshot(ariaSnapshot: string): { fragment?: ParsedYaml, errors: SourceHighlight[] } { const lineCounter = new yaml.LineCounter(); - let yamlDoc: yaml.Document; - try { - yamlDoc = yaml.parseDocument(ariaSnapshot, { - keepSourceTokens: true, - lineCounter, - }); - } catch (e) { - const error = e as YAMLError; - const pos = error.linePos?.[0]; - return { - errors: [{ - line: pos?.line || 0, - type: 'error', - message: error.message, - }], - }; - } + const yamlDoc = yaml.parseDocument(ariaSnapshot, { + keepSourceTokens: true, + lineCounter, + prettyErrors: false, + }); const errors: SourceHighlight[] = []; + for (const error of yamlDoc.errors) { + errors.push({ + line: lineCounter.linePos(error.pos[0]).line, + type: 'error', + message: error.message, + }); + } + + if (yamlDoc.errors.length) + return { errors }; + const handleKey = (key: yaml.Scalar) => { try { parseAriaKey(key.value); } catch (e) { const keyError = e as AriaKeyError; errors.push({ - message: keyError.message, + message: keyError.shortMessage, line: lineCounter.linePos(key.srcToken!.offset + keyError.pos).line, type: 'error', }); diff --git a/packages/web/package.json b/packages/web/package.json index 3898ac1bbb..0465fdf4c4 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "scripts": {}, "dependencies": { - "codemirror-shadow-1": "0.0.1", + "codemirror": "5.65.18", "xterm": "^5.1.0", "xterm-addon-fit": "^0.7.0" } diff --git a/packages/web/src/components/codeMirrorModule.tsx b/packages/web/src/components/codeMirrorModule.tsx index ea0953bf8f..e0a32772ff 100644 --- a/packages/web/src/components/codeMirrorModule.tsx +++ b/packages/web/src/components/codeMirrorModule.tsx @@ -15,17 +15,17 @@ */ // @ts-ignore -import codemirror from 'codemirror-shadow-1'; +import codemirror from 'codemirror'; import type codemirrorType from 'codemirror'; -import 'codemirror-shadow-1/lib/codemirror.css'; -import 'codemirror-shadow-1/mode/css/css'; -import 'codemirror-shadow-1/mode/htmlmixed/htmlmixed'; -import 'codemirror-shadow-1/mode/javascript/javascript'; -import 'codemirror-shadow-1/mode/python/python'; -import 'codemirror-shadow-1/mode/clike/clike'; -import 'codemirror-shadow-1/mode/markdown/markdown'; -import 'codemirror-shadow-1/addon/mode/simple'; -import 'codemirror-shadow-1/mode/yaml/yaml'; +import 'codemirror/lib/codemirror.css'; +import 'codemirror/mode/css/css'; +import 'codemirror/mode/htmlmixed/htmlmixed'; +import 'codemirror/mode/javascript/javascript'; +import 'codemirror/mode/python/python'; +import 'codemirror/mode/clike/clike'; +import 'codemirror/mode/markdown/markdown'; +import 'codemirror/addon/mode/simple'; +import 'codemirror/mode/yaml/yaml'; export type CodeMirror = typeof codemirrorType; export default codemirror; diff --git a/packages/web/src/components/codeMirrorWrapper.tsx b/packages/web/src/components/codeMirrorWrapper.tsx index 3234bf7f26..0fa4cd057d 100644 --- a/packages/web/src/components/codeMirrorWrapper.tsx +++ b/packages/web/src/components/codeMirrorWrapper.tsx @@ -115,8 +115,13 @@ export const CodeMirrorWrapper: React.FC = ({ return; let valueChanged = false; - if (codemirror.getValue() !== text) { - codemirror.setValue(text); + // CodeMirror has a bug that renders cursor poorly on a last line. + let normalizedText = text; + if (!readOnly && !wrapLines && !normalizedText.endsWith('\n')) + normalizedText = normalizedText + '\n'; + + if (codemirror.getValue() !== normalizedText) { + codemirror.setValue(normalizedText); valueChanged = true; if (focusOnChange) { codemirror.execCommand('selectAll'); @@ -170,7 +175,7 @@ export const CodeMirrorWrapper: React.FC = ({ if (changeListener) codemirror.off('change', changeListener); }; - }, [codemirror, text, highlight, revealLine, focusOnChange, onChange]); + }, [codemirror, text, highlight, revealLine, focusOnChange, onChange, readOnly]); return
; }; diff --git a/tests/library/inspector/cli-codegen-aria.spec.ts b/tests/library/inspector/cli-codegen-aria.spec.ts index 840725067b..fe8b45e60b 100644 --- a/tests/library/inspector/cli-codegen-aria.spec.ts +++ b/tests/library/inspector/cli-codegen-aria.spec.ts @@ -15,6 +15,7 @@ */ import { test, expect } from './inspectorTest'; +import { roundBox } from '../../page/pageTest'; test.describe(() => { test.skip(({ mode }) => mode !== 'default'); @@ -59,4 +60,90 @@ test.describe(() => { await expect.poll(() => recorder.text('C#')).toContain(`await Expect(page.GetByRole(AriaRole.Button)).ToMatchAriaSnapshotAsync("- button /Submit \\\\d+/");`); }); + + test('should inspect aria snapshot', async ({ openRecorder }) => { + const { recorder } = await openRecorder(); + await recorder.setContentAndWait(`
`); + await recorder.page.click('x-pw-tool-item.pick-locator'); + await recorder.page.hover('button'); + await recorder.trustedClick(); + await recorder.recorderPage.getByRole('tab', { name: 'Aria snapshot ' }).click(); + await expect(recorder.recorderPage.locator('.tab-aria .CodeMirror')).toMatchAriaSnapshot(` + - textbox + - text: '- button "Submit"' + `); + }); + + test('should update aria snapshot highlight', async ({ openRecorder }) => { + const { recorder } = await openRecorder(); + await recorder.setContentAndWait(`
+ + +
`); + + const submitButton = recorder.page.getByRole('button', { name: 'Submit' }); + const cancelButton = recorder.page.getByRole('button', { name: 'Cancel' }); + + await recorder.recorderPage.getByRole('button', { name: 'Record' }).click(); + + await recorder.page.click('x-pw-tool-item.pick-locator'); + await submitButton.hover(); + await recorder.trustedClick(); + await recorder.recorderPage.getByRole('tab', { name: 'Aria snapshot ' }).click(); + await expect(recorder.recorderPage.locator('.tab-aria .CodeMirror')).toMatchAriaSnapshot(` + - text: '- button "Submit"' + `); + + await recorder.recorderPage.locator('.tab-aria .CodeMirror').click(); + await recorder.recorderPage.keyboard.press('ArrowLeft'); + for (let i = 0; i < '"Submit"'.length; i++) + await recorder.recorderPage.keyboard.press('Backspace'); + + { + // No accessible name => two boxes. + const box11 = roundBox(await submitButton.boundingBox()); + const box12 = roundBox(await recorder.page.locator('x-pw-highlight').first().boundingBox()); + expect(box11).toEqual(box12); + + const box21 = roundBox(await cancelButton.boundingBox()); + const box22 = roundBox(await recorder.page.locator('x-pw-highlight').last().boundingBox()); + expect(box21).toEqual(box22); + } + + { + // Different button. + await recorder.recorderPage.locator('.tab-aria .CodeMirror').pressSequentially('"Cancel"'); + await expect(recorder.page.locator('x-pw-highlight')).toBeVisible(); + const box1 = roundBox(await cancelButton.boundingBox()); + const box2 = roundBox(await recorder.page.locator('x-pw-highlight').boundingBox()); + expect(box1).toEqual(box2); + } + }); + + test('should show aria snapshot error', async ({ openRecorder }) => { + const { recorder } = await openRecorder(); + await recorder.setContentAndWait(`
+ + +
`); + + const submitButton = recorder.page.getByRole('button', { name: 'Submit' }); + await recorder.recorderPage.getByRole('button', { name: 'Record' }).click(); + + await recorder.page.click('x-pw-tool-item.pick-locator'); + await submitButton.hover(); + await recorder.trustedClick(); + + await recorder.recorderPage.getByRole('tab', { name: 'Aria snapshot ' }).click(); + await expect(recorder.recorderPage.locator('.tab-aria .CodeMirror')).toMatchAriaSnapshot(` + - text: '- button "Submit"' + `); + + await recorder.recorderPage.locator('.tab-aria .CodeMirror').click(); + await recorder.recorderPage.keyboard.press('ArrowLeft'); + await recorder.recorderPage.keyboard.press('Backspace'); + await expect(recorder.recorderPage.locator('.tab-aria .CodeMirror')).toMatchAriaSnapshot(` + - text: '- button "Submit Unterminated string' + `); + }); }); diff --git a/tests/library/inspector/pause.spec.ts b/tests/library/inspector/pause.spec.ts index 647706956f..858ededfcb 100644 --- a/tests/library/inspector/pause.spec.ts +++ b/tests/library/inspector/pause.spec.ts @@ -17,7 +17,8 @@ import type { Page } from 'playwright-core'; import { test as it, expect, Recorder } from './inspectorTest'; import { waitForTestLog } from '../../config/utils'; - +import { roundBox } from '../../page/pageTest'; +import type { BoundingBox } from '../../page/pageTest'; it('should resume when closing inspector', async ({ page, recorderPageGetter, closeRecorder, mode }) => { it.skip(mode !== 'default'); @@ -385,7 +386,7 @@ it.describe('pause', () => { })(); const recorderPage = await recorderPageGetter(); - const box1Promise = waitForTestLog(page, 'Highlight box for test: '); + const box1Promise = waitForTestLog(page, 'Highlight box for test: '); await recorderPage.getByText('Locator', { exact: true }).click(); await recorderPage.locator('.tabbed-pane .CodeMirror').click(); await recorderPage.keyboard.type('getByText(\'Submit\')'); @@ -407,7 +408,7 @@ it.describe('pause', () => { })(); const recorderPage = await recorderPageGetter(); - const box1Promise = waitForTestLog(page, 'Highlight box for test: '); + const box1Promise = waitForTestLog(page, 'Highlight box for test: '); await recorderPage.getByText('Locator', { exact: true }).click(); await recorderPage.locator('.tabbed-pane .CodeMirror').click(); await recorderPage.keyboard.type('GetByText("Submit")'); @@ -472,7 +473,7 @@ it.describe('pause', () => { })(); const recorderPage = await recorderPageGetter(); - const box1Promise = waitForTestLog(page, 'Highlight box for test: '); + const box1Promise = waitForTestLog(page, 'Highlight box for test: '); await recorderPage.click('[title="Step over (F10)"]'); const box2 = roundBox((await page.locator('#target').boundingBox())!); const box1 = roundBox(await box1Promise); @@ -514,13 +515,3 @@ async function sanitizeLog(recorderPage: Page): Promise { } return results; } - -type Box = { x: number, y: number, width: number, height: number }; -function roundBox(box: Box): Box { - return { - x: Math.round(box.x * 1000), - y: Math.round(box.y * 1000), - width: Math.round(box.width * 1000), - height: Math.round(box.height * 1000), - }; -} diff --git a/tests/page/locator-highlight.spec.ts b/tests/page/locator-highlight.spec.ts index 8bc5c75085..92f338c71c 100644 --- a/tests/page/locator-highlight.spec.ts +++ b/tests/page/locator-highlight.spec.ts @@ -14,10 +14,7 @@ * limitations under the License. */ -import { test as it, expect } from './pageTest'; -import type { Locator } from 'playwright-core'; - -type BoundingBox = Awaited>; +import { test as it, expect, roundBox } from './pageTest'; it.skip(({ mode }) => mode !== 'default', 'Highlight element has a closed shadow-root on != default'); @@ -30,12 +27,3 @@ it('should highlight locator', async ({ page }) => { const box2 = roundBox(await page.locator('x-pw-highlight').boundingBox()); expect(box1).toEqual(box2); }); - -function roundBox(box: BoundingBox): BoundingBox { - return { - x: Math.round(box.x), - y: Math.round(box.y), - width: Math.round(box.width), - height: Math.round(box.height), - }; -} diff --git a/tests/page/pageTest.ts b/tests/page/pageTest.ts index 533d901037..a28984e55a 100644 --- a/tests/page/pageTest.ts +++ b/tests/page/pageTest.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { Frame, Page, TestType } from '@playwright/test'; +import type { Frame, Page, TestType, Locator } from '@playwright/test'; import type { PlatformWorkerFixtures } from '../config/platformFixtures'; import type { TestModeTestFixtures, TestModeWorkerFixtures, TestModeWorkerOptions } from '../config/testModeFixtures'; import { androidTest } from '../android/androidTest'; @@ -26,6 +26,7 @@ import type { ServerFixtures, ServerWorkerOptions } from '../config/serverFixtur export { expect } from '@playwright/test'; let impl: TestType = browserTest; +export type BoundingBox = Awaited>; if (process.env.PWPAGE_IMPL === 'android') impl = androidTest; @@ -43,3 +44,12 @@ export async function rafraf(target: Page | Frame, count = 1) { }); } } + +export function roundBox(box: BoundingBox): BoundingBox { + return { + x: Math.round(box.x), + y: Math.round(box.y), + width: Math.round(box.width), + height: Math.round(box.height), + }; +} diff --git a/utils/generate_third_party_notice.js b/utils/generate_third_party_notice.js index 27b5b4691d..d9148142f7 100644 --- a/utils/generate_third_party_notice.js +++ b/utils/generate_third_party_notice.js @@ -61,7 +61,7 @@ This project incorporates components from the projects listed below. The origina } } - const packages = await checkDir('node_modules/codemirror-shadow-1'); + const packages = await checkDir('node_modules/codemirror'); for (const [key, value] of Object.entries(packages)) { if (value.licenseText) allPackages[key] = value;