11import {
22 CucumberExpressionGenerator ,
33 Group ,
4- ParameterTypeRegistry ,
54 RegularExpression ,
65} from "@cucumber/cucumber-expressions" ;
76import * as messages from "@cucumber/messages" ;
@@ -18,6 +17,7 @@ import {
1817import {
1918 ITaskFrontendTrackingError ,
2019 ITaskSpecEnvelopes ,
20+ ITaskSuggestion ,
2121 ITaskTestCaseFinished ,
2222 ITaskTestCaseStarted ,
2323 ITaskTestRunHookFinished ,
@@ -26,6 +26,7 @@ import {
2626 ITaskTestStepStarted ,
2727 TASK_FRONTEND_TRACKING_ERROR ,
2828 TASK_SPEC_ENVELOPES ,
29+ TASK_SUGGESTION ,
2930 TASK_TEST_CASE_FINISHED ,
3031 TASK_TEST_CASE_STARTED ,
3132 TASK_TEST_RUN_HOOK_FINISHED ,
@@ -273,6 +274,12 @@ function taskFrontEndTrackingError(error: CypressCucumberAssertionError) {
273274 ) ;
274275}
275276
277+ function taskSuggestion ( suggestion : messages . Suggestion ) {
278+ return cy . task ( TASK_SUGGESTION , suggestion satisfies ITaskSuggestion , {
279+ log : false ,
280+ } ) ;
281+ }
282+
276283function emitSkippedPickle (
277284 context : CompositionContext ,
278285 pickle : messages . Pickle ,
@@ -862,60 +869,94 @@ function createPickle(context: CompositionContext, pickle: messages.Pickle) {
862869
863870 return beforeHooksChain ( )
864871 . then ( ( beforeStepHookResults ) => {
865- try {
866- return runStepWithLogGroup ( {
867- keyword : ensure (
868- "keyword" in scenarioStep && scenarioStep . keyword ,
869- "Expected to find a keyword in the scenario step" ,
870- ) ,
871- argument,
872- text,
873- fn : ( ) => {
874- try {
875- return registry . runStepDefinition (
876- this ,
877- text ,
878- dryRun ,
879- argument ,
880- ) ;
881- } catch ( e ) {
882- if (
883- e instanceof MissingDefinitionError ||
884- e instanceof MultipleDefinitionsError
885- ) {
886- ( this . test as any ) . _retries = (
887- this . test as any
888- ) . _currentRetry ;
872+ return runStepWithLogGroup ( {
873+ keyword : ensure (
874+ "keyword" in scenarioStep && scenarioStep . keyword ,
875+ "Expected to find a keyword in the scenario step" ,
876+ ) ,
877+ argument,
878+ text,
879+ fn : ( ) => {
880+ try {
881+ return registry . runStepDefinition (
882+ this ,
883+ text ,
884+ dryRun ,
885+ argument ,
886+ ) ;
887+ } catch ( e ) {
888+ if (
889+ e instanceof MissingDefinitionError ||
890+ e instanceof MultipleDefinitionsError
891+ ) {
892+ ( this . test as any ) . _retries = (
893+ this . test as any
894+ ) . _currentRetry ;
895+ }
896+
897+ if ( e instanceof MissingDefinitionError ) {
898+ let parameterType : "dataTable" | "docString" | null =
899+ null ;
900+
901+ if ( pickleStep . argument ?. dataTable ) {
902+ parameterType = "dataTable" ;
903+ } else if ( pickleStep . argument ?. docString ) {
904+ parameterType = "docString" ;
889905 }
906+
907+ const snippets = new CucumberExpressionGenerator (
908+ ( ) =>
909+ context . registry . parameterTypeRegistry
910+ . parameterTypes ,
911+ )
912+ . generateExpressions ( pickleStep . text )
913+ . map ( ( expression ) =>
914+ generateSnippet (
915+ expression ,
916+ ensure (
917+ pickleStep . type ,
918+ "Expected pickleStep to have a type" ,
919+ ) ,
920+ parameterType ,
921+ ) ,
922+ ) ;
923+
924+ return taskSuggestion ( {
925+ id : context . newId ( ) ,
926+ pickleStepId : pickleStep . id ,
927+ snippets : snippets . map ( ( code ) => {
928+ return {
929+ language : "javascript" ,
930+ code,
931+ } ;
932+ } ) ,
933+ } ) . then ( ( ) => {
934+ throw new Error (
935+ createMissingStepDefinitionMessage (
936+ context ,
937+ pickleStep ,
938+ snippets ,
939+ ) ,
940+ ) ;
941+ } ) ;
942+ } else {
890943 throw e ;
891944 }
892- } ,
893- } )
894- . then ( convertReturnValueToTestStepResultStatus )
895- . then ( ( status ) => {
896- const testStepResult = {
897- status,
898- duration : duration ( start , createTimestamp ( ) ) ,
899- } ;
900-
901- return {
902- beforeStepHookResults,
903- testStepResult,
904- } ;
905- } ) ;
906- } catch ( e ) {
907- if ( e instanceof MissingDefinitionError ) {
908- throw new Error (
909- createMissingStepDefinitionMessage (
910- context ,
911- pickleStep ,
912- context . registry . parameterTypeRegistry ,
913- ) ,
914- ) ;
915- } else {
916- throw e ;
917- }
918- }
945+ }
946+ } ,
947+ } )
948+ . then ( convertReturnValueToTestStepResultStatus )
949+ . then ( ( status ) => {
950+ const testStepResult = {
951+ status,
952+ duration : duration ( start , createTimestamp ( ) ) ,
953+ } ;
954+
955+ return {
956+ beforeStepHookResults,
957+ testStepResult,
958+ } ;
959+ } ) ;
919960 } )
920961 . then ( ( { beforeStepHookResults, testStepResult } ) => {
921962 return afterStepHooksChain ( ) . then ( ( afterStepHookResults ) => {
@@ -1574,7 +1615,7 @@ function strictIsTextTerminal(): boolean {
15741615function createMissingStepDefinitionMessage (
15751616 context : CompositionContext ,
15761617 pickleStep : messages . PickleStep ,
1577- parameterTypeRegistry : ParameterTypeRegistry ,
1618+ snippets : string [ ] ,
15781619) {
15791620 const noStepDefinitionPathsTemplate = `
15801621 Step implementation missing for "<text>".
@@ -1629,28 +1670,6 @@ function createMissingStepDefinitionMessage(
16291670 const prettyPrintList = ( items : string [ ] ) =>
16301671 items . map ( ( item ) => " - " + maybeEscape ( item ) ) . join ( "\n" ) ;
16311672
1632- let parameter : "dataTable" | "docString" | null = null ;
1633-
1634- if ( pickleStep . argument ?. dataTable ) {
1635- parameter = "dataTable" ;
1636- } else if ( pickleStep . argument ?. docString ) {
1637- parameter = "docString" ;
1638- }
1639-
1640- const snippets = new CucumberExpressionGenerator (
1641- ( ) => parameterTypeRegistry . parameterTypes ,
1642- )
1643- . generateExpressions ( pickleStep . text )
1644- . map ( ( expression ) =>
1645- generateSnippet (
1646- expression ,
1647- ensure ( pickleStep . type , "Expected pickleStep to have a type" ) ,
1648- parameter ,
1649- ) ,
1650- )
1651- . map ( ( snippet ) => indent ( snippet , { count : 2 } ) )
1652- . join ( "\n\n" ) ;
1653-
16541673 return stripIndent ( template )
16551674 . replaceAll ( "<text>" , pickleStep . text )
16561675 . replaceAll (
@@ -1665,7 +1684,10 @@ function createMissingStepDefinitionMessage(
16651684 "<step-definition-paths>" ,
16661685 prettyPrintList ( stepDefinitionHints . stepDefinitionPaths ) ,
16671686 )
1668- . replaceAll ( "<snippets>" , snippets ) ;
1687+ . replaceAll (
1688+ "<snippets>" ,
1689+ snippets . map ( ( snippet ) => indent ( snippet , { count : 2 } ) ) . join ( "\n\n" ) ,
1690+ ) ;
16691691}
16701692
16711693function mapArgumentGroup ( group : Group ) : messages . Group {
0 commit comments