From 321a4daa802d92b8b896278ba04082a020214f7d Mon Sep 17 00:00:00 2001 From: Jonas Amundsen Date: Fri, 4 Oct 2024 17:05:33 +0200 Subject: [PATCH] Cache requested source maps This fixes #1245 [1]. [1] https://github.com/badeball/cypress-cucumber-preprocessor/issues/1245 --- CHANGELOG.md | 4 ++++ features/issues/1245.feature | 22 ++++++++++++++++++++++ features/step_definitions/cli_steps.ts | 11 +++++++++++ lib/helpers/source-map.ts | 14 +++++++++++++- 4 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 features/issues/1245.feature diff --git a/CHANGELOG.md b/CHANGELOG.md index 788ae824..c72b43e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this project will be documented in this file. +## Unreleased + +- Cache requested source maps, fixes [#1245](https://github.com/badeball/cypress-cucumber-preprocessor/discussions/1245). + ## v21.0.1 - Support config file locations other than project root, fixes [#1243](https://github.com/badeball/cypress-cucumber-preprocessor/discussions/1243). diff --git a/features/issues/1245.feature b/features/issues/1245.feature new file mode 100644 index 00000000..2259a543 --- /dev/null +++ b/features/issues/1245.feature @@ -0,0 +1,22 @@ +Feature: cached source maps + Scenario: + Given a file named "cypress/e2e/a.feature" with: + """ + Feature: a feature name + Scenario: a scenario name + Given a step + """ + And a file named "cypress/support/step_definitions/steps.ts" with: + """ + import { Given } from "@badeball/cypress-cucumber-preprocessor"; + Given("a step", function(this: Mocha.Context) {}); + for (let i = 0; i < 10; i++) { + Given(`an unused step (${i + 1})`, function(this: Mocha.Context) {}); + }; + """ + When I run cypress with environment variables + | name | value | + | DEBUG | cypress:server:preprocessor | + Then it passes + # Why two? Who knows. Cypress requests this file twice and the library once. + And I should see exactly 2 instances of "headless and already processed" in stderr diff --git a/features/step_definitions/cli_steps.ts b/features/step_definitions/cli_steps.ts index dd6a90e9..0907df38 100644 --- a/features/step_definitions/cli_steps.ts +++ b/features/step_definitions/cli_steps.ts @@ -249,3 +249,14 @@ Then( assert.match(expectLastRun(this).stdout, pendingScenarioExpr(scenarioName)); }, ); + +Then( + "I should see exactly {int} instance(s) of {string} in stderr", + function (this: ICustomWorld, expectedOccurences: number, output: string) { + const actualyOccurences = + expectLastRun(this).stderr.match(new RegExp(rescape(output), "g")) + ?.length ?? 0; + + assert.equal(actualyOccurences, expectedOccurences); + }, +); diff --git a/lib/helpers/source-map.ts b/lib/helpers/source-map.ts index eeb3e006..b5f8853e 100644 --- a/lib/helpers/source-map.ts +++ b/lib/helpers/source-map.ts @@ -21,6 +21,8 @@ function sourceMapWarn(message: string) { isSourceMapWarned = true; } +const cache = new Map(); + /** * Taken from https://github.com/evanw/node-source-map-support/blob/v0.5.21/source-map-support.js#L148-L177. */ @@ -61,6 +63,16 @@ export function retrieveSourceMapURL(source: string) { return lastMatch[1]; } +export function cachedRetrieveSourceMapURL(source: string): string | undefined { + if (cache.has(source)) { + return cache.get(source); + } else { + const result = retrieveSourceMapURL(source); + cache.set(source, result); + return result; + } +} + export function maybeRetrievePositionFromSourceMap(): Position | undefined { const stack = ErrorStackParser.parse(new Error()); @@ -68,7 +80,7 @@ export function maybeRetrievePositionFromSourceMap(): Position | undefined { return; } - const sourceMappingURL = retrieveSourceMapURL(stack[0].fileName); + const sourceMappingURL = cachedRetrieveSourceMapURL(stack[0].fileName); if (!sourceMappingURL) { return;