/ test / PandocReaderTest.hs
PandocReaderTest.hs
  1  {-# LANGUAGE OverloadedStrings #-}
  2  
  3  module PandocReaderTest (tests) where
  4  
  5  import Automerge as A (BlockType (..), Mark (..))
  6  import AutomergeTestUtils as Automerge (blockQuoteSpan, codeTextSpan, emphasisTextSpan, heading1Span, heading2Span, heading4Span, linkTextSpan, noteContentSpan, noteRefSpan, orderedListItemSpan, paragraphSpan, strongTextSpan, textSpan, textSpanWithMarks, unorderedListItemSpan)
  7  import PandocReader (toPandoc)
  8  import Test.Hspec (Spec, describe, expectationFailure, it, shouldBe)
  9  import Test.Tasty (TestTree, testGroup)
 10  import Test.Tasty.Hspec (testSpec)
 11  import Text.Pandoc.Builder as Pandoc (blockQuote, bulletList, code, doc, emph, fromList, header, link, note, orderedList, para, plain, str, strong, toList)
 12  import Text.Pandoc.Class (runIO)
 13  
 14  tests :: IO TestTree
 15  tests = do
 16    hspecTests <- testSpec "hspec" spec
 17    return $ testGroup "Reader" [hspecTests]
 18  
 19  spec :: Spec
 20  spec = do
 21    it "handles a list of empty automerge spans" $ do
 22      let input = []
 23          expected = fromList []
 24  
 25      result <- runIO $ toPandoc input
 26      case result of
 27        Left err -> expectationFailure ("toPandoc failed: " <> show err)
 28        Right actual -> actual `shouldBe` Pandoc.doc expected
 29  
 30    it "handles a simple document with headings and plain text paragraphs" $ do
 31      let input =
 32            [ Automerge.heading1Span [],
 33              Automerge.textSpan "A Heading 1",
 34              Automerge.paragraphSpan [],
 35              Automerge.textSpan "A paragraph",
 36              Automerge.paragraphSpan [],
 37              Automerge.textSpan "Another paragraph"
 38            ]
 39  
 40          expected =
 41            fromList $
 42              concat
 43                [ toList $ Pandoc.header 1 $ Pandoc.str "A Heading 1",
 44                  toList $ Pandoc.para $ Pandoc.str "A paragraph",
 45                  toList $ Pandoc.para $ Pandoc.str "Another paragraph"
 46                ]
 47  
 48      result <- runIO $ toPandoc input
 49      case result of
 50        Left err -> expectationFailure ("toPandoc failed: " <> show err)
 51        Right actual -> actual `shouldBe` Pandoc.doc expected
 52  
 53    describe "Marks" $ do
 54      it "handles strong text" $ do
 55        let input =
 56              [ Automerge.paragraphSpan [],
 57                Automerge.strongTextSpan "Strong text"
 58              ]
 59  
 60            expected =
 61              fromList $
 62                concat
 63                  [ toList $ Pandoc.para $ Pandoc.strong $ Pandoc.str "Strong text"
 64                  ]
 65  
 66        result <- runIO $ toPandoc input
 67        case result of
 68          Left err -> expectationFailure ("toPandoc failed: " <> show err)
 69          Right actual -> actual `shouldBe` Pandoc.doc expected
 70  
 71      it "handles emphasized text" $ do
 72        let input =
 73              [ Automerge.paragraphSpan [],
 74                Automerge.emphasisTextSpan "Emphasized text"
 75              ]
 76  
 77            expected =
 78              fromList $
 79                concat
 80                  [ toList $ Pandoc.para $ Pandoc.emph $ Pandoc.str "Emphasized text"
 81                  ]
 82  
 83        result <- runIO $ toPandoc input
 84        case result of
 85          Left err -> expectationFailure ("toPandoc failed: " <> show err)
 86          Right actual -> actual `shouldBe` Pandoc.doc expected
 87  
 88      it "handles the combination of strong and emphasized text" $ do
 89        let input =
 90              [ Automerge.paragraphSpan [],
 91                Automerge.textSpanWithMarks "Both strong and emphasized text" [A.Strong, A.Emphasis]
 92              ]
 93  
 94            expected =
 95              fromList $
 96                concat
 97                  -- TODO: There is no order in automerge marks but here the marks are inverted and it should be
 98                  -- understood and investigated why this happens.
 99                  [ toList $ Pandoc.para $ Pandoc.emph $ Pandoc.strong $ Pandoc.str "Both strong and emphasized text"
100                  ]
101  
102        result <- runIO $ toPandoc input
103        case result of
104          Left err -> expectationFailure ("toPandoc failed: " <> show err)
105          Right actual -> actual `shouldBe` Pandoc.doc expected
106  
107      it "handles links" $ do
108        let input =
109              [ Automerge.paragraphSpan [],
110                Automerge.linkTextSpan "Automerge" "https://automerge.org/" "Automerge"
111              ]
112  
113            expected =
114              fromList $
115                concat
116                  -- TODO: There is no order in automerge marks but here the marks are inverted and it should be
117                  -- understood and investigated why this happens.
118                  [ toList $ Pandoc.para $ Pandoc.link "https://automerge.org/" "Automerge" $ Pandoc.str "Automerge"
119                  ]
120  
121        result <- runIO $ toPandoc input
122        case result of
123          Left err -> expectationFailure ("toPandoc failed: " <> show err)
124          Right actual -> actual `shouldBe` Pandoc.doc expected
125  
126      it "handles inline code" $ do
127        let input =
128              [ Automerge.paragraphSpan [],
129                Automerge.codeTextSpan "func1"
130              ]
131  
132            expected =
133              fromList $
134                concat
135                  [ toList $ Pandoc.para $ Pandoc.code "func1"
136                  ]
137  
138        result <- runIO $ toPandoc input
139        case result of
140          Left err -> expectationFailure ("toPandoc failed: " <> show err)
141          Right actual -> actual `shouldBe` Pandoc.doc expected
142  
143      it "handles text that is partially covered with marks" $ do
144        let input =
145              [ Automerge.paragraphSpan [],
146                Automerge.textSpan "Some plain text followed by ",
147                Automerge.strongTextSpan "strong text",
148                Automerge.textSpan " and a link: ",
149                Automerge.linkTextSpan "Automerge" "https://automerge.org/" "Automerge"
150              ]
151  
152            expected =
153              fromList $
154                concat
155                  [ toList $
156                      Pandoc.para $
157                        fromList $
158                          concat
159                            [ toList $ Pandoc.str "Some plain text followed by ",
160                              toList $ Pandoc.strong $ Pandoc.str "strong text",
161                              toList $ Pandoc.str " and a link: ",
162                              toList $ Pandoc.link "https://automerge.org/" "Automerge" $ Pandoc.str "Automerge"
163                            ]
164                  ]
165  
166        result <- runIO $ toPandoc input
167        case result of
168          Left err -> expectationFailure ("toPandoc failed: " <> show err)
169          Right actual -> actual `shouldBe` Pandoc.doc expected
170  
171    describe "Lists" $ do
172      it "handles unordered lists with plain text children" $ do
173        let input =
174              [ Automerge.heading1Span [],
175                Automerge.textSpan "A Heading 1",
176                Automerge.paragraphSpan [],
177                Automerge.textSpan "Paragraph above the list",
178                Automerge.unorderedListItemSpan [],
179                Automerge.textSpan "List item 1",
180                Automerge.unorderedListItemSpan [],
181                Automerge.textSpan "List item 2",
182                Automerge.paragraphSpan [],
183                Automerge.textSpan "Paragraph below the list"
184              ]
185  
186            expected =
187              fromList $
188                concat
189                  [ toList $ Pandoc.header 1 $ Pandoc.str "A Heading 1",
190                    toList $ Pandoc.para $ Pandoc.str "Paragraph above the list",
191                    -- using `Plain` pandoc blocks for list item text spans
192                    toList $ Pandoc.bulletList [Pandoc.plain $ Pandoc.str "List item 1", Pandoc.plain $ Pandoc.str "List item 2"],
193                    toList $ Pandoc.para $ Pandoc.str "Paragraph below the list"
194                  ]
195  
196        result <- runIO $ toPandoc input
197        case result of
198          Left err -> expectationFailure ("toPandoc failed: " <> show err)
199          Right actual -> actual `shouldBe` Pandoc.doc expected
200  
201      it "handles ordered lists with plain text children" $ do
202        let input =
203              [ Automerge.heading1Span [],
204                Automerge.textSpan "A Heading 1",
205                Automerge.paragraphSpan [],
206                Automerge.textSpan "Paragraph above the list",
207                Automerge.orderedListItemSpan [],
208                Automerge.textSpan "List item 1",
209                Automerge.orderedListItemSpan [],
210                Automerge.textSpan "List item 2",
211                Automerge.paragraphSpan [],
212                Automerge.textSpan "Paragraph below the list"
213              ]
214  
215            expected =
216              fromList $
217                concat
218                  [ toList $ Pandoc.header 1 $ Pandoc.str "A Heading 1",
219                    toList $ Pandoc.para $ Pandoc.str "Paragraph above the list",
220                    -- using `Plain` pandoc blocks for list item text spans
221                    toList $ Pandoc.orderedList [Pandoc.plain $ Pandoc.str "List item 1", Pandoc.plain $ Pandoc.str "List item 2"],
222                    toList $ Pandoc.para $ Pandoc.str "Paragraph below the list"
223                  ]
224  
225        result <- runIO $ toPandoc input
226        case result of
227          Left err -> expectationFailure ("toPandoc failed: " <> show err)
228          Right actual -> actual `shouldBe` Pandoc.doc expected
229  
230      it "returns list item text that includes marks in a single Pandoc `Plain` block" $ do
231        let input =
232              [ Automerge.heading1Span [],
233                Automerge.textSpan "A Heading 1",
234                Automerge.paragraphSpan [],
235                Automerge.textSpan "Paragraph above the list",
236                Automerge.unorderedListItemSpan [],
237                Automerge.textSpan "List item 1 with some ",
238                Automerge.strongTextSpan "strong text",
239                Automerge.unorderedListItemSpan [],
240                Automerge.textSpan "List item 2 with a ",
241                Automerge.linkTextSpan "link" "https://automerge.org/" "Automerge",
242                Automerge.paragraphSpan [],
243                Automerge.textSpan "Paragraph below the list"
244              ]
245  
246            expected =
247              fromList $
248                concat
249                  [ toList $ Pandoc.header 1 $ Pandoc.str "A Heading 1",
250                    toList $ Pandoc.para $ Pandoc.str "Paragraph above the list",
251                    toList $
252                      Pandoc.bulletList
253                        [ Pandoc.plain (Pandoc.str "List item 1 with some " <> (Pandoc.strong $ Pandoc.str "strong text")),
254                          Pandoc.plain (Pandoc.str "List item 2 with a " <> (Pandoc.link "https://automerge.org/" "Automerge" $ str "link"))
255                        ],
256                    toList $ Pandoc.para $ Pandoc.str "Paragraph below the list"
257                  ]
258  
259        result <- runIO $ toPandoc input
260        case result of
261          Left err -> expectationFailure ("toPandoc failed: " <> show err)
262          Right actual -> actual `shouldBe` Pandoc.doc expected
263  
264      it "handles nested lists with plain text children" $ do
265        let input =
266              [ Automerge.heading1Span [],
267                Automerge.textSpan "A Heading 1",
268                Automerge.paragraphSpan [],
269                Automerge.textSpan "Paragraph above the list",
270                Automerge.unorderedListItemSpan [],
271                Automerge.textSpan "List item 1",
272                Automerge.unorderedListItemSpan [A.UnorderedListItemType],
273                Automerge.textSpan "List item 1.1",
274                Automerge.unorderedListItemSpan [A.UnorderedListItemType],
275                Automerge.textSpan "List item 1.2",
276                Automerge.unorderedListItemSpan [],
277                Automerge.textSpan "List item 2",
278                Automerge.unorderedListItemSpan [A.UnorderedListItemType],
279                Automerge.textSpan "List item 2.1",
280                Automerge.paragraphSpan [],
281                Automerge.textSpan "Paragraph below the list"
282              ]
283  
284            expected =
285              fromList $
286                concat
287                  [ toList $ Pandoc.header 1 $ Pandoc.str "A Heading 1",
288                    toList $ Pandoc.para $ Pandoc.str "Paragraph above the list",
289                    toList $
290                      Pandoc.bulletList
291                        [ ( (Pandoc.plain $ str "List item 1")
292                              <> ( Pandoc.bulletList
293                                     [ Pandoc.plain $ Pandoc.str "List item 1.1",
294                                       Pandoc.plain $ Pandoc.str "List item 1.2"
295                                     ]
296                                 )
297                          ),
298                          ( (Pandoc.plain $ Pandoc.str "List item 2")
299                              <> ( Pandoc.bulletList
300                                     [Pandoc.plain $ Pandoc.str "List item 2.1"]
301                                 )
302                          )
303                        ],
304                    toList $ Pandoc.para $ Pandoc.str "Paragraph below the list"
305                  ]
306  
307        result <- runIO $ toPandoc input
308        case result of
309          Left err -> expectationFailure ("toPandoc failed: " <> show err)
310          Right actual -> actual `shouldBe` Pandoc.doc expected
311  
312      it "handles nested lists with child blocks and two levels of nesting" $ do
313        let input =
314              [ Automerge.heading1Span [],
315                Automerge.textSpan "A Heading 1",
316                Automerge.paragraphSpan [],
317                Automerge.textSpan "Paragraph above the list",
318                Automerge.orderedListItemSpan [],
319                Automerge.textSpan "List item 1",
320                Automerge.heading4Span [A.OrderedListItemType],
321                Automerge.textSpan "Heading 4 inside a list item",
322                Automerge.orderedListItemSpan [A.OrderedListItemType],
323                Automerge.textSpan "List item 1.1",
324                Automerge.orderedListItemSpan [A.OrderedListItemType, A.OrderedListItemType],
325                Automerge.textSpan "List item 1.1.1",
326                Automerge.paragraphSpan [A.OrderedListItemType, A.OrderedListItemType, A.OrderedListItemType],
327                Automerge.textSpan "Paragraph nested 3 levels deep",
328                Automerge.orderedListItemSpan [A.OrderedListItemType],
329                Automerge.textSpan "List item 1.2",
330                Automerge.orderedListItemSpan [],
331                Automerge.textSpan "List item 2",
332                Automerge.orderedListItemSpan [A.OrderedListItemType],
333                Automerge.textSpan "List item 2.1",
334                Automerge.paragraphSpan [A.OrderedListItemType, A.OrderedListItemType],
335                Automerge.textSpan "Paragraph nested 2 levels deep",
336                Automerge.paragraphSpan [],
337                Automerge.textSpan "Paragraph below the list"
338              ]
339  
340            expected =
341              fromList $
342                concat
343                  [ toList $ Pandoc.header 1 $ Pandoc.str "A Heading 1",
344                    toList $ Pandoc.para $ Pandoc.str "Paragraph above the list",
345                    toList $
346                      Pandoc.orderedList
347                        [ ( (plain $ str "List item 1")
348                              <> (Pandoc.header 4 $ Pandoc.str "Heading 4 inside a list item")
349                              <> ( Pandoc.orderedList
350                                     [ ( (Pandoc.plain $ Pandoc.str "List item 1.1")
351                                           <> Pandoc.orderedList
352                                             [ ( (Pandoc.plain $ Pandoc.str "List item 1.1.1")
353                                                   <> (Pandoc.para $ Pandoc.str "Paragraph nested 3 levels deep")
354                                               )
355                                             ]
356                                       ),
357                                       Pandoc.plain $ Pandoc.str "List item 1.2"
358                                     ]
359                                 )
360                          ),
361                          ( (plain $ str "List item 2")
362                              <> ( Pandoc.orderedList
363                                     [ ( (Pandoc.plain $ Pandoc.str "List item 2.1")
364                                           <> (Pandoc.para $ Pandoc.str "Paragraph nested 2 levels deep")
365                                       )
366                                     ]
367                                 )
368                          )
369                        ],
370                    toList $ Pandoc.para $ Pandoc.str "Paragraph below the list"
371                  ]
372  
373        result <- runIO $ toPandoc input
374        case result of
375          Left err -> expectationFailure ("toPandoc failed: " <> show err)
376          Right actual -> actual `shouldBe` Pandoc.doc expected
377  
378    describe "BlockQuote" $ do
379      it "handles a blockquote with nested paragraphs" $ do
380        let input =
381              [ Automerge.heading1Span [],
382                Automerge.textSpan "A Heading 1",
383                Automerge.paragraphSpan [],
384                Automerge.textSpan "Paragraph above the blockquote",
385                Automerge.blockQuoteSpan [],
386                Automerge.paragraphSpan [A.BlockQuoteType],
387                Automerge.textSpan "Ticking away the moments that make up a dull day",
388                Automerge.paragraphSpan [A.BlockQuoteType],
389                Automerge.textSpan "You fritter and waste the hours in an offhand way",
390                Automerge.paragraphSpan [],
391                Automerge.textSpan "Paragraph below the blockquote"
392              ]
393  
394            expected =
395              fromList $
396                concat
397                  [ toList $ Pandoc.header 1 $ Pandoc.str "A Heading 1",
398                    toList $ Pandoc.para $ Pandoc.str "Paragraph above the blockquote",
399                    toList $
400                      Pandoc.blockQuote $
401                        fromList $
402                          concat $
403                            [ toList $ (Pandoc.para $ str "Ticking away the moments that make up a dull day"),
404                              toList $ (Pandoc.para $ str "You fritter and waste the hours in an offhand way")
405                            ],
406                    toList $ Pandoc.para $ Pandoc.str "Paragraph below the blockquote"
407                  ]
408  
409        result <- runIO $ toPandoc input
410        case result of
411          Left err -> expectationFailure ("toPandoc failed: " <> show err)
412          Right actual -> actual `shouldBe` Pandoc.doc expected
413  
414      it "wraps a text span just after the blockquote in a Plain block" $ do
415        let input =
416              [ Automerge.heading1Span [],
417                Automerge.textSpan "A Heading 1",
418                Automerge.paragraphSpan [],
419                Automerge.textSpan "Paragraph above the blockquote",
420                Automerge.blockQuoteSpan [],
421                Automerge.textSpan "Ticking away the moments that make up a dull day",
422                Automerge.paragraphSpan [A.BlockQuoteType],
423                Automerge.textSpan "You fritter and waste the hours in an offhand way",
424                Automerge.paragraphSpan [],
425                Automerge.textSpan "Paragraph below the blockquote"
426              ]
427  
428            expected =
429              fromList $
430                concat
431                  [ toList $ Pandoc.header 1 $ Pandoc.str "A Heading 1",
432                    toList $ Pandoc.para $ Pandoc.str "Paragraph above the blockquote",
433                    toList $
434                      Pandoc.blockQuote $
435                        fromList $
436                          concat $
437                            [ toList $ (Pandoc.plain $ str "Ticking away the moments that make up a dull day"),
438                              toList $ (Pandoc.para $ str "You fritter and waste the hours in an offhand way")
439                            ],
440                    toList $ Pandoc.para $ Pandoc.str "Paragraph below the blockquote"
441                  ]
442  
443        result <- runIO $ toPandoc input
444        case result of
445          Left err -> expectationFailure ("toPandoc failed: " <> show err)
446          Right actual -> actual `shouldBe` Pandoc.doc expected
447  
448      it "handles a heading and marks inside the blockquote" $ do
449        let input =
450              [ Automerge.heading1Span [],
451                Automerge.textSpan "A Heading 1",
452                Automerge.paragraphSpan [],
453                Automerge.textSpan "Paragraph above the blockquote",
454                Automerge.blockQuoteSpan [],
455                Automerge.heading2Span [A.BlockQuoteType],
456                Automerge.textSpan "Time",
457                Automerge.paragraphSpan [A.BlockQuoteType],
458                Automerge.strongTextSpan "Ticking away",
459                Automerge.textSpan " the moments that make up a dull day",
460                Automerge.paragraphSpan [A.BlockQuoteType],
461                Automerge.textSpan "You fritter and waste the hours in an offhand way",
462                Automerge.paragraphSpan [],
463                Automerge.textSpan "Paragraph below the blockquote"
464              ]
465  
466            expected =
467              fromList $
468                concat
469                  [ toList $ Pandoc.header 1 $ Pandoc.str "A Heading 1",
470                    toList $ Pandoc.para $ Pandoc.str "Paragraph above the blockquote",
471                    toList $
472                      Pandoc.blockQuote $
473                        fromList $
474                          concat $
475                            [ toList $ Pandoc.header 2 $ Pandoc.str "Time",
476                              toList $
477                                ( Pandoc.para $
478                                    fromList $
479                                      concat
480                                        [ toList $ Pandoc.strong $ Pandoc.str "Ticking away",
481                                          toList $ Pandoc.str " the moments that make up a dull day"
482                                        ]
483                                ),
484                              toList $ (Pandoc.para $ str "You fritter and waste the hours in an offhand way")
485                            ],
486                    toList $ Pandoc.para $ Pandoc.str "Paragraph below the blockquote"
487                  ]
488  
489        result <- runIO $ toPandoc input
490        case result of
491          Left err -> expectationFailure ("toPandoc failed: " <> show err)
492          Right actual -> actual `shouldBe` Pandoc.doc expected
493    describe "Notes" $ do
494      it "converts a note reference and its content into a Pandoc note" $ do
495        let noteId = "1"
496            input =
497              [ Automerge.paragraphSpan [],
498                Automerge.textSpan "A paragraph ",
499                Automerge.noteRefSpan [A.ParagraphType] noteId,
500                Automerge.paragraphSpan [],
501                Automerge.textSpan "Another paragraph",
502                Automerge.noteContentSpan [] noteId,
503                Automerge.textSpan "This is a note"
504              ]
505  
506            expected =
507              fromList $
508                concat
509                  [ toList $
510                      Pandoc.para $
511                        fromList $
512                          concat $
513                            [ toList $ Pandoc.str "A paragraph ",
514                              toList $
515                                Pandoc.note $
516                                  fromList $
517                                    concat $
518                                      [ toList $
519                                          (Pandoc.plain $ Pandoc.str "This is a note")
520                                      ]
521                            ],
522                    toList $
523                      Pandoc.para $
524                        Pandoc.str "Another paragraph"
525                  ]
526        result <- runIO $ toPandoc input
527        case result of
528          Left err -> expectationFailure ("toPandoc failed: " <> show err)
529          Right actual -> actual `shouldBe` Pandoc.doc expected
530  
531      it "handles consecutive notes at the end of a paragraph" $ do
532        let input =
533              [ Automerge.paragraphSpan [],
534                Automerge.textSpan "A paragraph ",
535                Automerge.noteRefSpan [A.ParagraphType] "1",
536                Automerge.noteRefSpan [A.ParagraphType] "2",
537                Automerge.paragraphSpan [],
538                Automerge.textSpan "Another paragraph",
539                Automerge.noteContentSpan [] "1",
540                Automerge.textSpan "Note 1 content",
541                Automerge.noteContentSpan [] "2",
542                Automerge.textSpan "Note 2 content"
543              ]
544  
545            expected =
546              fromList $
547                concat
548                  [ toList $
549                      Pandoc.para $
550                        fromList $
551                          concat $
552                            [ toList $ Pandoc.str "A paragraph ",
553                              toList $
554                                Pandoc.note $
555                                  fromList $
556                                    concat $
557                                      [ toList $
558                                          (Pandoc.plain $ Pandoc.str "Note 1 content")
559                                      ],
560                              toList $
561                                Pandoc.note $
562                                  fromList $
563                                    concat $
564                                      [ toList $
565                                          (Pandoc.plain $ Pandoc.str "Note 2 content")
566                                      ]
567                            ],
568                    toList $
569                      Pandoc.para $
570                        Pandoc.str "Another paragraph"
571                  ]
572        result <- runIO $ toPandoc input
573        case result of
574          Left err -> expectationFailure ("toPandoc failed: " <> show err)
575          Right actual -> actual `shouldBe` Pandoc.doc expected
576  
577      it "handles notes between other text" $ do
578        let input =
579              [ Automerge.paragraphSpan [],
580                Automerge.textSpan "A paragraph ",
581                Automerge.noteRefSpan [A.ParagraphType] "1",
582                Automerge.textSpan " ",
583                Automerge.noteRefSpan [A.ParagraphType] "2",
584                Automerge.textSpan " continuing after the note.",
585                Automerge.paragraphSpan [],
586                Automerge.textSpan "Another paragraph",
587                Automerge.noteContentSpan [] "1",
588                Automerge.textSpan "Note 1 content",
589                Automerge.noteContentSpan [] "2",
590                Automerge.textSpan "Note 2 content"
591              ]
592  
593            expected =
594              fromList $
595                concat
596                  [ toList $
597                      Pandoc.para $
598                        fromList $
599                          concat $
600                            [ toList $ Pandoc.str "A paragraph ",
601                              toList $
602                                Pandoc.note $
603                                  fromList $
604                                    concat $
605                                      [ toList $
606                                          (Pandoc.plain $ Pandoc.str "Note 1 content")
607                                      ],
608                              toList $ Pandoc.str " ",
609                              toList $
610                                Pandoc.note $
611                                  fromList $
612                                    concat $
613                                      [ toList $
614                                          (Pandoc.plain $ Pandoc.str "Note 2 content")
615                                      ],
616                              toList $ Pandoc.str " continuing after the note."
617                            ],
618                    toList $
619                      Pandoc.para $
620                        Pandoc.str "Another paragraph"
621                  ]
622        result <- runIO $ toPandoc input
623        case result of
624          Left err -> expectationFailure ("toPandoc failed: " <> show err)
625          Right actual -> actual `shouldBe` Pandoc.doc expected
626  
627      it "handles multi-block note content" $ do
628        let input =
629              [ Automerge.paragraphSpan [],
630                Automerge.textSpan "A paragraph ",
631                Automerge.noteRefSpan [A.ParagraphType] "1",
632                Automerge.paragraphSpan [],
633                Automerge.textSpan "Another paragraph",
634                Automerge.noteContentSpan [] "1",
635                Automerge.paragraphSpan [A.NoteContentType],
636                Automerge.textSpan "Note content paragraph 1",
637                Automerge.paragraphSpan [A.NoteContentType],
638                Automerge.textSpan "Note content paragraph 2"
639              ]
640  
641            expected =
642              fromList $
643                concat
644                  [ toList $
645                      Pandoc.para $
646                        fromList $
647                          concat $
648                            [ toList $ Pandoc.str "A paragraph ",
649                              toList $
650                                Pandoc.note $
651                                  fromList $
652                                    concat $
653                                      [ toList $
654                                          (Pandoc.para $ Pandoc.str "Note content paragraph 1"),
655                                        toList $
656                                          (Pandoc.para $ Pandoc.str "Note content paragraph 2")
657                                      ]
658                            ],
659                    toList $
660                      Pandoc.para $
661                        Pandoc.str "Another paragraph"
662                  ]
663        result <- runIO $ toPandoc input
664        case result of
665          Left err -> expectationFailure ("toPandoc failed: " <> show err)
666          Right actual -> actual `shouldBe` Pandoc.doc expected
667  
668      it "ignores a note reference without content" $ do
669        let input =
670              [ Automerge.paragraphSpan [],
671                Automerge.textSpan "A paragraph ",
672                Automerge.noteRefSpan [A.ParagraphType] "1",
673                Automerge.noteRefSpan [A.ParagraphType] "2",
674                Automerge.paragraphSpan [],
675                Automerge.textSpan "Another paragraph",
676                Automerge.noteContentSpan [] "1",
677                Automerge.textSpan "Note 1 content"
678              ]
679  
680            expected =
681              fromList $
682                concat
683                  [ toList $
684                      Pandoc.para $
685                        fromList $
686                          concat $
687                            [ toList $ Pandoc.str "A paragraph ",
688                              toList $
689                                Pandoc.note $
690                                  fromList $
691                                    concat $
692                                      [ toList $
693                                          (Pandoc.plain $ Pandoc.str "Note 1 content")
694                                      ]
695                            ],
696                    toList $
697                      Pandoc.para $
698                        Pandoc.str "Another paragraph"
699                  ]
700        result <- runIO $ toPandoc input
701        case result of
702          Left err -> expectationFailure ("toPandoc failed: " <> show err)
703          Right actual -> actual `shouldBe` Pandoc.doc expected
704  
705      it "ingores note content without a corresponding reference" $ do
706        let input =
707              [ Automerge.paragraphSpan [],
708                Automerge.textSpan "A paragraph ",
709                Automerge.noteRefSpan [A.ParagraphType] "1",
710                Automerge.paragraphSpan [],
711                Automerge.textSpan "Another paragraph",
712                Automerge.noteContentSpan [] "1",
713                Automerge.textSpan "Note 1 content",
714                Automerge.noteContentSpan [] "2",
715                Automerge.textSpan "Note 2 content"
716              ]
717  
718            expected =
719              fromList $
720                concat
721                  [ toList $
722                      Pandoc.para $
723                        fromList $
724                          concat $
725                            [ toList $ Pandoc.str "A paragraph ",
726                              toList $
727                                Pandoc.note $
728                                  fromList $
729                                    concat $
730                                      [ toList $
731                                          (Pandoc.plain $ Pandoc.str "Note 1 content")
732                                      ]
733                            ],
734                    toList $
735                      Pandoc.para $
736                        Pandoc.str "Another paragraph"
737                  ]
738        result <- runIO $ toPandoc input
739        case result of
740          Left err -> expectationFailure ("toPandoc failed: " <> show err)
741          Right actual -> actual `shouldBe` Pandoc.doc expected