testomatio-editor-blocks 0.4.19 → 0.4.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -237,7 +237,7 @@ function serializeBlock(block, ctx, orderedIndex, stepIndex) {
237
237
  }
238
238
  case "bulletListItem": {
239
239
  const text = inlineToMarkdown(block.content);
240
- lines.push(`${indent}- ${text}`.trimEnd());
240
+ lines.push(`${indent}* ${text}`.trimEnd());
241
241
  lines.push(...serializeChildren(block, ctx));
242
242
  return lines;
243
243
  }
@@ -624,13 +624,11 @@ function parseList(lines, startIndex, listType, indentLevel, allowEmptySteps = f
624
624
  break;
625
625
  }
626
626
  // Only try to parse as testStep for top-level items (indentLevel === 0)
627
- // when we're under a Steps heading AND the list type is bullet
628
- // Numbered lists under Steps heading are only parsed as test steps if they look like test steps
629
- if (indentLevel === 0 && (allowEmptySteps || listType === "bullet")) {
630
- // For bullet lists, always try to parse as test steps
631
- // For numbered lists, only try if they have step-like characteristics
627
+ // Under a Steps heading (allowEmptySteps=true): always try for both bullet and numbered
628
+ // Outside Steps heading: only if the item looks like a test step (has Expected markers or indented data)
629
+ if (indentLevel === 0 && (allowEmptySteps || isLikelyStep(lines, index))) {
632
630
  const looksLikeTestStep = listType === "bullet" ||
633
- (listType === "numbered" && (isLikelyStep(lines, index)));
631
+ (listType === "numbered" && (allowEmptySteps || isLikelyStep(lines, index)));
634
632
  if (looksLikeTestStep) {
635
633
  const nextStep = parseTestStep(lines, index, allowEmptySteps);
636
634
  if (nextStep) {
@@ -678,20 +676,28 @@ function parseList(lines, startIndex, listType, indentLevel, allowEmptySteps = f
678
676
  }
679
677
  function isLikelyStep(lines, index) {
680
678
  // Look ahead to see if there's indented content or expected result
681
- if (index + 1 >= lines.length)
682
- return false;
683
- const nextLine = lines[index + 1];
684
- const hasIndent = /^\s{2,}/.test(nextLine);
685
- // Check if the next line contains expected result markers
686
- const nextTrimmed = nextLine.trim();
687
- const hasExpectedResult = EXPECTED_LABEL_REGEX.test(nextTrimmed);
688
- // Only consider it a test step if:
689
- // 1. It has an expected result, OR
690
- // 2. The next line is indented but doesn't start with a numbered or bullet list
691
- if (hasExpectedResult)
692
- return true;
693
- if (hasIndent && !/^\d+[.)]/.test(nextTrimmed) && !/^[-*+]/.test(nextTrimmed))
694
- return true;
679
+ // Look ahead through subsequent lines for expected result markers or indented content
680
+ for (let i = index + 1; i < lines.length; i++) {
681
+ const line = lines[i];
682
+ const trimmed = line.trim();
683
+ // Stop at blank lines
684
+ if (!trimmed)
685
+ break;
686
+ // Check for indented content (step data) first — indented lines indicate a test step
687
+ const hasIndent = /^\s{2,}/.test(line);
688
+ if (hasIndent)
689
+ return true;
690
+ // Stop at new list items, headings, or other block-level elements (only if not indented)
691
+ if (/^[-*+]\s/.test(trimmed) || /^\d+[.)]\s/.test(trimmed))
692
+ break;
693
+ if (trimmed.startsWith("#") || trimmed.startsWith(">") || trimmed.startsWith("|") || trimmed.startsWith("```") || trimmed.startsWith(":::"))
694
+ break;
695
+ // Check for expected result markers
696
+ if (EXPECTED_LABEL_REGEX.test(trimmed))
697
+ return true;
698
+ if (trimmed.match(/^\*[^*]*expected/i))
699
+ return true;
700
+ }
695
701
  return false;
696
702
  }
697
703
  function parseTestStep(lines, index, allowEmpty = false, snippetId) {
@@ -1145,7 +1151,9 @@ export function markdownToBlocks(markdown) {
1145
1151
  index = snippetWrapper.nextIndex;
1146
1152
  continue;
1147
1153
  }
1148
- const stepLikeBlock = parseTestStep(lines, index, stepsHeadingLevel !== null);
1154
+ const stepLikeBlock = (stepsHeadingLevel !== null || isLikelyStep(lines, index))
1155
+ ? parseTestStep(lines, index, stepsHeadingLevel !== null)
1156
+ : null;
1149
1157
  if (stepLikeBlock) {
1150
1158
  blocks.push(stepLikeBlock.block);
1151
1159
  index = stepLikeBlock.nextIndex;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testomatio-editor-blocks",
3
- "version": "0.4.19",
3
+ "version": "0.4.20",
4
4
  "description": "Custom BlockNote schema, markdown conversion helpers, and UI for Testomatio-style test cases and steps.",
5
5
  "type": "module",
6
6
  "main": "./package/index.js",
@@ -485,37 +485,9 @@ describe("markdownToBlocks", () => {
485
485
  const blocks = markdownToBlocks(markdown);
486
486
  const stepBlocks = blocks.filter((block) => block.type === "testStep");
487
487
 
488
+ // Preconditions and Postconditions bullets are now parsed as bulletListItem (not testStep)
489
+ // Only items under the "Steps" heading with Expected markers remain as testSteps
488
490
  expect(stepBlocks).toEqual([
489
- {
490
- type: "testStep",
491
- props: {
492
- stepTitle: "The user is logged into the application.",
493
- stepData: "",
494
- expectedResult: "",
495
- listStyle: "bullet",
496
- },
497
- children: [],
498
- },
499
- {
500
- type: "testStep",
501
- props: {
502
- stepTitle: "The user has the necessary permissions to receive notifications.",
503
- stepData: "",
504
- expectedResult: "",
505
- listStyle: "bullet",
506
- },
507
- children: [],
508
- },
509
- {
510
- type: "testStep",
511
- props: {
512
- stepTitle: "The application is configured to send real-time notifications.",
513
- stepData: "",
514
- expectedResult: "",
515
- listStyle: "bullet",
516
- },
517
- children: [],
518
- },
519
491
  {
520
492
  type: "testStep",
521
493
  props: {
@@ -556,26 +528,6 @@ describe("markdownToBlocks", () => {
556
528
  },
557
529
  children: [],
558
530
  },
559
- {
560
- type: "testStep",
561
- props: {
562
- stepTitle: "The user has received and viewed the notifications.",
563
- stepData: "",
564
- expectedResult: "",
565
- listStyle: "bullet",
566
- },
567
- children: [],
568
- },
569
- {
570
- type: "testStep",
571
- props: {
572
- stepTitle: "The application continues to function as expected after receiving and processing the notifications.",
573
- stepData: "",
574
- expectedResult: "",
575
- listStyle: "bullet",
576
- },
577
- children: [],
578
- },
579
531
  ]);
580
532
  });
581
533
 
@@ -674,33 +626,21 @@ describe("markdownToBlocks", () => {
674
626
  children: [],
675
627
  },
676
628
  {
677
- type: "testStep",
678
- props: {
679
- stepTitle: "The user is logged into the application.",
680
- stepData: "",
681
- expectedResult: "",
682
- listStyle: "bullet",
683
- },
629
+ type: "bulletListItem",
630
+ props: baseProps,
631
+ content: [{ type: "text", text: "The user is logged into the application.", styles: {} }],
684
632
  children: [],
685
633
  },
686
634
  {
687
- type: "testStep",
688
- props: {
689
- stepTitle: "The user has the necessary permissions to receive notifications.",
690
- stepData: "",
691
- expectedResult: "",
692
- listStyle: "bullet",
693
- },
635
+ type: "bulletListItem",
636
+ props: baseProps,
637
+ content: [{ type: "text", text: "The user has the necessary permissions to receive notifications.", styles: {} }],
694
638
  children: [],
695
639
  },
696
640
  {
697
- type: "testStep",
698
- props: {
699
- stepTitle: "The application is configured to send real-time notifications.",
700
- stepData: "",
701
- expectedResult: "",
702
- listStyle: "bullet",
703
- },
641
+ type: "bulletListItem",
642
+ props: baseProps,
643
+ content: [{ type: "text", text: "The application is configured to send real-time notifications.", styles: {} }],
704
644
  children: [],
705
645
  },
706
646
  ]);
@@ -1008,13 +948,9 @@ describe("markdownToBlocks", () => {
1008
948
  children: [],
1009
949
  },
1010
950
  {
1011
- type: "testStep",
1012
- props: {
1013
- stepTitle: "Bullet",
1014
- stepData: "",
1015
- expectedResult: "",
1016
- listStyle: "bullet",
1017
- },
951
+ type: "bulletListItem",
952
+ props: baseProps,
953
+ content: [{ type: "text", text: "Bullet", styles: {} }],
1018
954
  children: [],
1019
955
  },
1020
956
  ]);
@@ -314,7 +314,7 @@ function serializeBlock(
314
314
  }
315
315
  case "bulletListItem": {
316
316
  const text = inlineToMarkdown(block.content);
317
- lines.push(`${indent}- ${text}`.trimEnd());
317
+ lines.push(`${indent}* ${text}`.trimEnd());
318
318
  lines.push(...serializeChildren(block, ctx));
319
319
  return lines;
320
320
  }
@@ -777,14 +777,12 @@ function parseList(
777
777
  }
778
778
 
779
779
  // Only try to parse as testStep for top-level items (indentLevel === 0)
780
- // when we're under a Steps heading AND the list type is bullet
781
- // Numbered lists under Steps heading are only parsed as test steps if they look like test steps
782
- if (indentLevel === 0 && (allowEmptySteps || listType === "bullet")) {
783
- // For bullet lists, always try to parse as test steps
784
- // For numbered lists, only try if they have step-like characteristics
780
+ // Under a Steps heading (allowEmptySteps=true): always try for both bullet and numbered
781
+ // Outside Steps heading: only if the item looks like a test step (has Expected markers or indented data)
782
+ if (indentLevel === 0 && (allowEmptySteps || isLikelyStep(lines, index))) {
785
783
  const looksLikeTestStep = listType === "bullet" ||
786
784
  (listType === "numbered" && (
787
- isLikelyStep(lines, index)
785
+ allowEmptySteps || isLikelyStep(lines, index)
788
786
  ));
789
787
 
790
788
  if (looksLikeTestStep) {
@@ -836,20 +834,26 @@ function parseList(
836
834
 
837
835
  function isLikelyStep(lines: string[], index: number): boolean {
838
836
  // Look ahead to see if there's indented content or expected result
839
- if (index + 1 >= lines.length) return false;
837
+ // Look ahead through subsequent lines for expected result markers or indented content
838
+ for (let i = index + 1; i < lines.length; i++) {
839
+ const line = lines[i];
840
+ const trimmed = line.trim();
841
+
842
+ // Stop at blank lines
843
+ if (!trimmed) break;
840
844
 
841
- const nextLine = lines[index + 1];
842
- const hasIndent = /^\s{2,}/.test(nextLine);
845
+ // Check for indented content (step data) first — indented lines indicate a test step
846
+ const hasIndent = /^\s{2,}/.test(line);
847
+ if (hasIndent) return true;
843
848
 
844
- // Check if the next line contains expected result markers
845
- const nextTrimmed = nextLine.trim();
846
- const hasExpectedResult = EXPECTED_LABEL_REGEX.test(nextTrimmed);
849
+ // Stop at new list items, headings, or other block-level elements (only if not indented)
850
+ if (/^[-*+]\s/.test(trimmed) || /^\d+[.)]\s/.test(trimmed)) break;
851
+ if (trimmed.startsWith("#") || trimmed.startsWith(">") || trimmed.startsWith("|") || trimmed.startsWith("```") || trimmed.startsWith(":::")) break;
847
852
 
848
- // Only consider it a test step if:
849
- // 1. It has an expected result, OR
850
- // 2. The next line is indented but doesn't start with a numbered or bullet list
851
- if (hasExpectedResult) return true;
852
- if (hasIndent && !/^\d+[.)]/.test(nextTrimmed) && !/^[-*+]/.test(nextTrimmed)) return true;
853
+ // Check for expected result markers
854
+ if (EXPECTED_LABEL_REGEX.test(trimmed)) return true;
855
+ if (trimmed.match(/^\*[^*]*expected/i)) return true;
856
+ }
853
857
 
854
858
  return false;
855
859
  }
@@ -1377,7 +1381,9 @@ export function markdownToBlocks(markdown: string): CustomPartialBlock[] {
1377
1381
  continue;
1378
1382
  }
1379
1383
 
1380
- const stepLikeBlock = parseTestStep(lines, index, stepsHeadingLevel !== null);
1384
+ const stepLikeBlock = (stepsHeadingLevel !== null || isLikelyStep(lines, index))
1385
+ ? parseTestStep(lines, index, stepsHeadingLevel !== null)
1386
+ : null;
1381
1387
  if (stepLikeBlock) {
1382
1388
  blocks.push(stepLikeBlock.block);
1383
1389
  index = stepLikeBlock.nextIndex;