package converter import ( "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // === Markdown to Confluence XML tests === func TestMarkdownToConfluence_Heading(t *testing.T) { result, err := MarkdownToConfluence([]byte("# Hello World")) require.NoError(t, err) assert.Contains(t, result, "

Hello World

") } func TestMarkdownToConfluence_AllHeadingLevels(t *testing.T) { for i, tag := range []string{"h1", "h2", "h3", "h4", "h5", "h6"} { prefix := strings.Repeat("#", i+1) result, err := MarkdownToConfluence([]byte(prefix + " Heading")) require.NoError(t, err) assert.Contains(t, result, "<"+tag+">Heading", "level %d", i+1) } } func TestMarkdownToConfluence_Bold(t *testing.T) { result, err := MarkdownToConfluence([]byte("**bold text**")) require.NoError(t, err) assert.Contains(t, result, "bold text") } func TestMarkdownToConfluence_Italic(t *testing.T) { result, err := MarkdownToConfluence([]byte("*italic text*")) require.NoError(t, err) assert.Contains(t, result, "italic text") } func TestMarkdownToConfluence_Strikethrough(t *testing.T) { result, err := MarkdownToConfluence([]byte("~~deleted~~")) require.NoError(t, err) assert.Contains(t, result, "deleted") } func TestMarkdownToConfluence_InlineCode(t *testing.T) { result, err := MarkdownToConfluence([]byte("`code`")) require.NoError(t, err) assert.Contains(t, result, "code") } func TestMarkdownToConfluence_CodeBlock(t *testing.T) { input := "```go\nfmt.Println(\"hello\")\n```" result, err := MarkdownToConfluence([]byte(input)) require.NoError(t, err) assert.Contains(t, result, `ac:name="code"`) assert.Contains(t, result, `ac:name="language">go`) assert.Contains(t, result, ``) } func TestMarkdownToConfluence_CodeBlockNoLanguage(t *testing.T) { input := "```\nsome code\n```" result, err := MarkdownToConfluence([]byte(input)) require.NoError(t, err) assert.Contains(t, result, `ac:name="code"`) assert.NotContains(t, result, `ac:name="language"`) } func TestMarkdownToConfluence_Table(t *testing.T) { input := "| A | B |\n|---|---|\n| 1 | 2 |" result, err := MarkdownToConfluence([]byte(input)) require.NoError(t, err) assert.Contains(t, result, "") assert.Contains(t, result, "") assert.Contains(t, result, "") } func TestMarkdownToConfluence_Blockquote(t *testing.T) { result, err := MarkdownToConfluence([]byte("> Important note")) require.NoError(t, err) assert.Contains(t, result, `ac:name="info"`) assert.Contains(t, result, "Important note") } func TestMarkdownToConfluence_Image(t *testing.T) { result, err := MarkdownToConfluence([]byte("![alt text](https://example.com/img.png)")) require.NoError(t, err) assert.Contains(t, result, "Click here`) } func TestMarkdownToConfluence_UnorderedList(t *testing.T) { input := "- One\n- Two\n- Three" result, err := MarkdownToConfluence([]byte(input)) require.NoError(t, err) assert.Contains(t, result, "

A

1

Name

Age

Alice

30

` result, err := ConfluenceToMarkdown(input) require.NoError(t, err) assert.Contains(t, result, "| Name |") assert.Contains(t, result, "| Alice |") assert.Contains(t, result, "|---|---|") } func TestConfluenceToMarkdown_InfoPanel(t *testing.T) { input := `

Important note

` result, err := ConfluenceToMarkdown(input) require.NoError(t, err) assert.Contains(t, result, "> Important note") } func TestConfluenceToMarkdown_HorizontalRule(t *testing.T) { result, err := ConfluenceToMarkdown("
") require.NoError(t, err) assert.Contains(t, result, "---") } func TestConfluenceToMarkdown_Emoticons(t *testing.T) { tests := []struct { name string input string expected string }{ {"plus", ``, "(+)"}, {"minus", ``, "(-)"}, {"question", ``, "(?)"}, {"tick", ``, "(v)"}, {"cross", ``, "(x)"}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { result, err := ConfluenceToMarkdown(tc.input) require.NoError(t, err) assert.Contains(t, result, tc.expected) }) } } func TestConfluenceToMarkdown_InlineCommentMarker(t *testing.T) { input := `

Before commented text after

` result, err := ConfluenceToMarkdown(input) require.NoError(t, err) assert.Contains(t, result, ``) assert.Contains(t, result, "commented text") assert.Contains(t, result, "") } // === User reference tests === func TestConfluenceToMarkdown_UserReference(t *testing.T) { input := `

Author:

` result, err := ConfluenceToMarkdown(input) require.NoError(t, err) assert.Contains(t, result, ``) } func TestMarkdownToConfluence_UserReference(t *testing.T) { input := `Author: ` result, err := MarkdownToConfluence([]byte(input)) require.NoError(t, err) assert.Contains(t, result, ``) } func TestRoundTrip_UserReference(t *testing.T) { xmlInput := `

Author: wrote this

` md, err := ConfluenceToMarkdown(xmlInput) require.NoError(t, err) require.Contains(t, md, `data-user-key="abc123"`) xmlOutput, err := MarkdownToConfluence([]byte(md)) require.NoError(t, err) assert.Contains(t, xmlOutput, `ri:userkey="abc123"`) } // === Attachment image tests === func TestConfluenceToMarkdown_AttachmentImage(t *testing.T) { input := `

` result, err := ConfluenceToMarkdown(input) require.NoError(t, err) assert.Contains(t, result, ``) } func TestConfluenceToMarkdown_AttachmentImageWithAlt(t *testing.T) { input := `

` result, err := ConfluenceToMarkdown(input) require.NoError(t, err) assert.Contains(t, result, `data-attachment="screenshot.png"`) assert.Contains(t, result, `data-alt="My Screenshot"`) } func TestMarkdownToConfluence_AttachmentImage(t *testing.T) { input := `Image: ` result, err := MarkdownToConfluence([]byte(input)) require.NoError(t, err) assert.Contains(t, result, ``) } func TestMarkdownToConfluence_AttachmentImageWithAlt(t *testing.T) { input := `` result, err := MarkdownToConfluence([]byte(input)) require.NoError(t, err) assert.Contains(t, result, `ac:alt="My Shot"`) assert.Contains(t, result, `ri:filename="screenshot.png"`) } func TestRoundTrip_AttachmentImage(t *testing.T) { xmlInput := `

` md, err := ConfluenceToMarkdown(xmlInput) require.NoError(t, err) require.Contains(t, md, `data-attachment="Pasted image 20260325004147.png"`) xmlOutput, err := MarkdownToConfluence([]byte(md)) require.NoError(t, err) assert.Contains(t, xmlOutput, `ri:filename="Pasted image 20260325004147.png"`) } // === Inline spacing tests === func TestConfluenceToMarkdown_SpaceAfterBold(t *testing.T) { input := `
  • ATE: Запуск плейбуков
` result, err := ConfluenceToMarkdown(input) require.NoError(t, err) assert.Contains(t, result, "**ATE:** Запуск плейбуков") } func TestConfluenceToMarkdown_SpaceBetweenInlineElements(t *testing.T) { input := `
  • Bold then italic text
` result, err := ConfluenceToMarkdown(input) require.NoError(t, err) assert.Contains(t, result, "**Bold** then *italic* text") } // === Round-trip tests === func TestRoundTrip_Basic(t *testing.T) { input := `# Test Some **bold** and *italic* text. ## Code ` + "```go\nfunc main() {}\n```" + ` ## List - One - Two - Three | H1 | H2 | |----|-----| | A | B | ` xml, err := MarkdownToConfluence([]byte(input)) require.NoError(t, err) md, err := ConfluenceToMarkdown(xml) require.NoError(t, err) for _, check := range []string{"# Test", "**bold**", "*italic*", "```go", "func main() {}", "- One", "| H1", "| A"} { assert.Contains(t, md, check, "round-trip should preserve %q", check) } } func TestRoundTrip_Blockquote(t *testing.T) { input := "> This is a blockquote\n" xml, err := MarkdownToConfluence([]byte(input)) require.NoError(t, err) md, err := ConfluenceToMarkdown(xml) require.NoError(t, err) assert.Contains(t, md, "> This is a blockquote") } func TestRoundTrip_Link(t *testing.T) { input := "[Example](https://example.com)\n" xml, err := MarkdownToConfluence([]byte(input)) require.NoError(t, err) md, err := ConfluenceToMarkdown(xml) require.NoError(t, err) assert.Contains(t, md, "[Example](https://example.com)") } func TestRoundTrip_InlineCommentMarker(t *testing.T) { xmlInput := `

Hello important text world

` md, err := ConfluenceToMarkdown(xmlInput) require.NoError(t, err) require.Contains(t, md, `data-inline-comment="b2f6ce98-4dc9-45e0-a9b6-b4a5109657ca"`) xmlOutput, err := MarkdownToConfluence([]byte(md)) require.NoError(t, err) assert.Contains(t, xmlOutput, ``) assert.Contains(t, xmlOutput, "") assert.Contains(t, xmlOutput, "important text") } func TestRoundTrip_InlineCommentFromRealXML(t *testing.T) { xmlInput := `

Товарищ! Не майся дурью, копируй этот шаблон и редактируй его! Ускоришь написание RFC!

` md, err := ConfluenceToMarkdown(xmlInput) require.NoError(t, err) xmlOutput, err := MarkdownToConfluence([]byte(md)) require.NoError(t, err) assert.Contains(t, xmlOutput, `ac:ref="b2f6ce98-4dc9-45e0-a9b6-b4a5109657ca"`) assert.Contains(t, xmlOutput, "Не майся дурью") }