mirror of
https://github.com/hanzoai/forge.git
synced 2026-10-30 15:00:39 +00:00
Source files keep their SPDX-License-Identifier and Hanzo copyright line; the Gitea, Gogs and LFS Test Server copyrights they used to repeat now live once in NOTICE, alongside LICENSE. The header lint accepts any copyright line above the SPDX line, so it no longer demands an upstream one. Co-authored-by: Hanzo Dev <[email protected]>
965 lines
20 KiB
Go
965 lines
20 KiB
Go
// Copyright 2026 Hanzo AI, Inc. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package template
|
|
|
|
import (
|
|
"net/url"
|
|
"testing"
|
|
|
|
"github.com/hanzoai/git/modules/json"
|
|
api "github.com/hanzoai/git/modules/structs"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestValidate(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
filename string
|
|
content string
|
|
want *api.IssueTemplate
|
|
wantErr string
|
|
}{
|
|
{
|
|
name: "miss name",
|
|
content: ``,
|
|
wantErr: "'name' is required",
|
|
},
|
|
{
|
|
name: "miss about",
|
|
content: `
|
|
name: "test"
|
|
`,
|
|
wantErr: "'about' is required",
|
|
},
|
|
{
|
|
name: "miss body",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
`,
|
|
wantErr: "'body' is required",
|
|
},
|
|
{
|
|
name: "markdown miss value",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "markdown"
|
|
`,
|
|
wantErr: "body[0](markdown): 'value' is required",
|
|
},
|
|
{
|
|
name: "markdown invalid value",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "markdown"
|
|
attributes:
|
|
value: true
|
|
`,
|
|
wantErr: "body[0](markdown): 'value' should be a string",
|
|
},
|
|
{
|
|
name: "markdown empty value",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "markdown"
|
|
attributes:
|
|
value: ""
|
|
`,
|
|
wantErr: "body[0](markdown): 'value' is required",
|
|
},
|
|
{
|
|
name: "textarea invalid id",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "textarea"
|
|
id: "?"
|
|
`,
|
|
wantErr: "body[0](textarea): 'id' should contain only alphanumeric, '-' and '_'",
|
|
},
|
|
{
|
|
name: "textarea miss label",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "textarea"
|
|
id: "1"
|
|
`,
|
|
wantErr: "body[0](textarea): 'label' is required",
|
|
},
|
|
{
|
|
name: "textarea conflict id",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "textarea"
|
|
id: "1"
|
|
attributes:
|
|
label: "a"
|
|
- type: "textarea"
|
|
id: "1"
|
|
attributes:
|
|
label: "b"
|
|
`,
|
|
wantErr: "body[1](textarea): 'id' should be unique",
|
|
},
|
|
{
|
|
name: "textarea invalid description",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "textarea"
|
|
id: "1"
|
|
attributes:
|
|
label: "a"
|
|
description: true
|
|
`,
|
|
wantErr: "body[0](textarea): 'description' should be a string",
|
|
},
|
|
{
|
|
name: "textarea invalid required",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "textarea"
|
|
id: "1"
|
|
attributes:
|
|
label: "a"
|
|
validations:
|
|
required: "on"
|
|
`,
|
|
wantErr: "body[0](textarea): 'required' should be a bool",
|
|
},
|
|
{
|
|
name: "input invalid description",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "input"
|
|
id: "1"
|
|
attributes:
|
|
label: "a"
|
|
description: true
|
|
`,
|
|
wantErr: "body[0](input): 'description' should be a string",
|
|
},
|
|
{
|
|
name: "input invalid is_number",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "input"
|
|
id: "1"
|
|
attributes:
|
|
label: "a"
|
|
validations:
|
|
is_number: "yes"
|
|
`,
|
|
wantErr: "body[0](input): 'is_number' should be a bool",
|
|
},
|
|
{
|
|
name: "input invalid regex",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "input"
|
|
id: "1"
|
|
attributes:
|
|
label: "a"
|
|
validations:
|
|
regex: true
|
|
`,
|
|
wantErr: "body[0](input): 'regex' should be a string",
|
|
},
|
|
{
|
|
name: "dropdown invalid description",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "dropdown"
|
|
id: "1"
|
|
attributes:
|
|
label: "a"
|
|
description: true
|
|
`,
|
|
wantErr: "body[0](dropdown): 'description' should be a string",
|
|
},
|
|
{
|
|
name: "dropdown invalid multiple",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "dropdown"
|
|
id: "1"
|
|
attributes:
|
|
label: "a"
|
|
multiple: "on"
|
|
`,
|
|
wantErr: "body[0](dropdown): 'multiple' should be a bool",
|
|
},
|
|
{
|
|
name: "dropdown invalid list",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "dropdown"
|
|
id: "1"
|
|
attributes:
|
|
label: "a"
|
|
list: "on"
|
|
`,
|
|
wantErr: "body[0](dropdown): 'list' should be a bool",
|
|
},
|
|
{
|
|
name: "checkboxes invalid description",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "checkboxes"
|
|
id: "1"
|
|
attributes:
|
|
label: "a"
|
|
description: true
|
|
`,
|
|
wantErr: "body[0](checkboxes): 'description' should be a string",
|
|
},
|
|
{
|
|
name: "invalid type",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "video"
|
|
id: "1"
|
|
attributes:
|
|
label: "a"
|
|
`,
|
|
wantErr: "body[0](video): unknown type",
|
|
},
|
|
{
|
|
name: "dropdown miss options",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "dropdown"
|
|
id: "1"
|
|
attributes:
|
|
label: "a"
|
|
`,
|
|
wantErr: "body[0](dropdown): 'options' is required and should be an array",
|
|
},
|
|
{
|
|
name: "dropdown invalid options",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "dropdown"
|
|
id: "1"
|
|
attributes:
|
|
label: "a"
|
|
options:
|
|
- "a"
|
|
- true
|
|
`,
|
|
wantErr: "body[0](dropdown), option[1]: should be a string",
|
|
},
|
|
{
|
|
name: "checkboxes invalid options",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "checkboxes"
|
|
id: "1"
|
|
attributes:
|
|
label: "a"
|
|
options:
|
|
- "a"
|
|
- true
|
|
`,
|
|
wantErr: "body[0](checkboxes), option[0]: should be a dictionary",
|
|
},
|
|
{
|
|
name: "checkboxes option miss label",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "checkboxes"
|
|
id: "1"
|
|
attributes:
|
|
label: "a"
|
|
options:
|
|
- required: true
|
|
`,
|
|
wantErr: "body[0](checkboxes), option[0]: 'label' is required and should be a string",
|
|
},
|
|
{
|
|
name: "checkboxes option invalid required",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "checkboxes"
|
|
id: "1"
|
|
attributes:
|
|
label: "a"
|
|
options:
|
|
- label: "a"
|
|
required: "on"
|
|
`,
|
|
wantErr: "body[0](checkboxes), option[0]: 'required' should be a bool",
|
|
},
|
|
{
|
|
name: "field is required but hidden",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: "input"
|
|
id: "1"
|
|
attributes:
|
|
label: "a"
|
|
validations:
|
|
required: true
|
|
visible: [content]
|
|
`,
|
|
wantErr: "body[0](input): can not require a hidden field",
|
|
},
|
|
{
|
|
name: "checkboxes is required but hidden",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: checkboxes
|
|
id: "1"
|
|
attributes:
|
|
label: Label of checkboxes
|
|
description: Description of checkboxes
|
|
options:
|
|
- label: Option 1
|
|
required: false
|
|
- label: Required and hidden
|
|
required: true
|
|
visible: [content]
|
|
`,
|
|
wantErr: "body[0](checkboxes), option[1]: can not require a hidden checkbox",
|
|
},
|
|
{
|
|
name: "dropdown default is not an integer",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: dropdown
|
|
id: "1"
|
|
attributes:
|
|
label: Label of dropdown
|
|
description: Description of dropdown
|
|
multiple: true
|
|
options:
|
|
- Option 1 of dropdown
|
|
- Option 2 of dropdown
|
|
- Option 3 of dropdown
|
|
default: "def"
|
|
validations:
|
|
required: true
|
|
`,
|
|
wantErr: "body[0](dropdown): 'default' should be an int",
|
|
},
|
|
{
|
|
name: "dropdown default is out of range",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: dropdown
|
|
id: "1"
|
|
attributes:
|
|
label: Label of dropdown
|
|
description: Description of dropdown
|
|
multiple: true
|
|
options:
|
|
- Option 1 of dropdown
|
|
- Option 2 of dropdown
|
|
- Option 3 of dropdown
|
|
default: 3
|
|
validations:
|
|
required: true
|
|
`,
|
|
wantErr: "body[0](dropdown): the value of 'default' is out of range",
|
|
},
|
|
{
|
|
name: "dropdown without default is valid",
|
|
content: `
|
|
name: "test"
|
|
about: "this is about"
|
|
body:
|
|
- type: dropdown
|
|
id: "1"
|
|
attributes:
|
|
label: Label of dropdown
|
|
description: Description of dropdown
|
|
multiple: true
|
|
options:
|
|
- Option 1 of dropdown
|
|
- Option 2 of dropdown
|
|
- Option 3 of dropdown
|
|
validations:
|
|
required: true
|
|
`,
|
|
want: &api.IssueTemplate{
|
|
Name: "test",
|
|
About: "this is about",
|
|
Fields: []*api.IssueFormField{
|
|
{
|
|
Type: "dropdown",
|
|
ID: "1",
|
|
Attributes: map[string]any{
|
|
"label": "Label of dropdown",
|
|
"description": "Description of dropdown",
|
|
"multiple": true,
|
|
"options": []any{
|
|
"Option 1 of dropdown",
|
|
"Option 2 of dropdown",
|
|
"Option 3 of dropdown",
|
|
},
|
|
},
|
|
Validations: map[string]any{
|
|
"required": true,
|
|
},
|
|
Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleForm, api.IssueFormFieldVisibleContent},
|
|
},
|
|
},
|
|
FileName: "test.yaml",
|
|
},
|
|
wantErr: "",
|
|
},
|
|
{
|
|
name: "valid",
|
|
content: `
|
|
name: Name
|
|
title: Title
|
|
about: About
|
|
labels: ["label1", "label2"]
|
|
assignees: ["user1", "user2"]
|
|
ref: Ref
|
|
body:
|
|
- type: markdown
|
|
id: id1
|
|
attributes:
|
|
value: Value of the markdown
|
|
- type: textarea
|
|
id: id2
|
|
attributes:
|
|
label: Label of textarea
|
|
description: Description of textarea
|
|
placeholder: Placeholder of textarea
|
|
value: Value of textarea
|
|
render: bash
|
|
validations:
|
|
required: true
|
|
- type: input
|
|
id: id3
|
|
attributes:
|
|
label: Label of input
|
|
description: Description of input
|
|
placeholder: Placeholder of input
|
|
value: Value of input
|
|
validations:
|
|
required: true
|
|
is_number: true
|
|
regex: "[a-zA-Z0-9]+"
|
|
- type: dropdown
|
|
id: id4
|
|
attributes:
|
|
label: Label of dropdown
|
|
description: Description of dropdown
|
|
multiple: true
|
|
options:
|
|
- Option 1 of dropdown
|
|
- Option 2 of dropdown
|
|
- Option 3 of dropdown
|
|
default: 1
|
|
validations:
|
|
required: true
|
|
- type: checkboxes
|
|
id: id5
|
|
attributes:
|
|
label: Label of checkboxes
|
|
description: Description of checkboxes
|
|
options:
|
|
- label: Option 1 of checkboxes
|
|
required: true
|
|
- label: Option 2 of checkboxes
|
|
required: false
|
|
- label: Hidden Option 3 of checkboxes
|
|
visible: [content]
|
|
- label: Required but not submitted
|
|
required: true
|
|
visible: [form]
|
|
`,
|
|
want: &api.IssueTemplate{
|
|
Name: "Name",
|
|
Title: "Title",
|
|
About: "About",
|
|
Labels: []string{"label1", "label2"},
|
|
Assignees: []string{"user1", "user2"},
|
|
Ref: "Ref",
|
|
Fields: []*api.IssueFormField{
|
|
{
|
|
Type: "markdown",
|
|
ID: "id1",
|
|
Attributes: map[string]any{
|
|
"value": "Value of the markdown",
|
|
},
|
|
Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleForm},
|
|
},
|
|
{
|
|
Type: "textarea",
|
|
ID: "id2",
|
|
Attributes: map[string]any{
|
|
"label": "Label of textarea",
|
|
"description": "Description of textarea",
|
|
"placeholder": "Placeholder of textarea",
|
|
"value": "Value of textarea",
|
|
"render": "bash",
|
|
},
|
|
Validations: map[string]any{
|
|
"required": true,
|
|
},
|
|
Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleForm, api.IssueFormFieldVisibleContent},
|
|
},
|
|
{
|
|
Type: "input",
|
|
ID: "id3",
|
|
Attributes: map[string]any{
|
|
"label": "Label of input",
|
|
"description": "Description of input",
|
|
"placeholder": "Placeholder of input",
|
|
"value": "Value of input",
|
|
},
|
|
Validations: map[string]any{
|
|
"required": true,
|
|
"is_number": true,
|
|
"regex": "[a-zA-Z0-9]+",
|
|
},
|
|
Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleForm, api.IssueFormFieldVisibleContent},
|
|
},
|
|
{
|
|
Type: "dropdown",
|
|
ID: "id4",
|
|
Attributes: map[string]any{
|
|
"label": "Label of dropdown",
|
|
"description": "Description of dropdown",
|
|
"multiple": true,
|
|
"options": []any{
|
|
"Option 1 of dropdown",
|
|
"Option 2 of dropdown",
|
|
"Option 3 of dropdown",
|
|
},
|
|
"default": 1,
|
|
},
|
|
Validations: map[string]any{
|
|
"required": true,
|
|
},
|
|
Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleForm, api.IssueFormFieldVisibleContent},
|
|
},
|
|
{
|
|
Type: "checkboxes",
|
|
ID: "id5",
|
|
Attributes: map[string]any{
|
|
"label": "Label of checkboxes",
|
|
"description": "Description of checkboxes",
|
|
"options": []any{
|
|
map[string]any{"label": "Option 1 of checkboxes", "required": true},
|
|
map[string]any{"label": "Option 2 of checkboxes", "required": false},
|
|
map[string]any{"label": "Hidden Option 3 of checkboxes", "visible": []string{"content"}},
|
|
map[string]any{"label": "Required but not submitted", "required": true, "visible": []string{"form"}},
|
|
},
|
|
},
|
|
Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleForm, api.IssueFormFieldVisibleContent},
|
|
},
|
|
},
|
|
FileName: "test.yaml",
|
|
},
|
|
wantErr: "",
|
|
},
|
|
{
|
|
name: "single label",
|
|
content: `
|
|
name: Name
|
|
title: Title
|
|
about: About
|
|
labels: label1
|
|
ref: Ref
|
|
body:
|
|
- type: markdown
|
|
id: id1
|
|
attributes:
|
|
value: Value of the markdown shown in form
|
|
- type: markdown
|
|
id: id2
|
|
attributes:
|
|
value: Value of the markdown shown in created issue
|
|
visible: [content]
|
|
`,
|
|
want: &api.IssueTemplate{
|
|
Name: "Name",
|
|
Title: "Title",
|
|
About: "About",
|
|
Labels: []string{"label1"},
|
|
Ref: "Ref",
|
|
Fields: []*api.IssueFormField{
|
|
{
|
|
Type: "markdown",
|
|
ID: "id1",
|
|
Attributes: map[string]any{
|
|
"value": "Value of the markdown shown in form",
|
|
},
|
|
Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleForm},
|
|
},
|
|
{
|
|
Type: "markdown",
|
|
ID: "id2",
|
|
Attributes: map[string]any{
|
|
"value": "Value of the markdown shown in created issue",
|
|
},
|
|
Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleContent},
|
|
},
|
|
},
|
|
FileName: "test.yaml",
|
|
},
|
|
wantErr: "",
|
|
},
|
|
{
|
|
name: "comma-delimited labels",
|
|
content: `
|
|
name: Name
|
|
title: Title
|
|
about: About
|
|
labels: label1,label2,,label3 ,,
|
|
ref: Ref
|
|
body:
|
|
- type: markdown
|
|
id: id1
|
|
attributes:
|
|
value: Value of the markdown
|
|
`,
|
|
want: &api.IssueTemplate{
|
|
Name: "Name",
|
|
Title: "Title",
|
|
About: "About",
|
|
Labels: []string{"label1", "label2", "label3"},
|
|
Ref: "Ref",
|
|
Fields: []*api.IssueFormField{
|
|
{
|
|
Type: "markdown",
|
|
ID: "id1",
|
|
Attributes: map[string]any{
|
|
"value": "Value of the markdown",
|
|
},
|
|
Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleForm},
|
|
},
|
|
},
|
|
FileName: "test.yaml",
|
|
},
|
|
wantErr: "",
|
|
},
|
|
{
|
|
name: "empty string as labels",
|
|
content: `
|
|
name: Name
|
|
title: Title
|
|
about: About
|
|
labels: ''
|
|
ref: Ref
|
|
body:
|
|
- type: markdown
|
|
id: id1
|
|
attributes:
|
|
value: Value of the markdown
|
|
`,
|
|
want: &api.IssueTemplate{
|
|
Name: "Name",
|
|
Title: "Title",
|
|
About: "About",
|
|
Labels: nil,
|
|
Ref: "Ref",
|
|
Fields: []*api.IssueFormField{
|
|
{
|
|
Type: "markdown",
|
|
ID: "id1",
|
|
Attributes: map[string]any{
|
|
"value": "Value of the markdown",
|
|
},
|
|
Visible: []api.IssueFormFieldVisible{api.IssueFormFieldVisibleForm},
|
|
},
|
|
},
|
|
FileName: "test.yaml",
|
|
},
|
|
wantErr: "",
|
|
},
|
|
{
|
|
name: "comma delimited labels in markdown",
|
|
filename: "test.md",
|
|
content: `---
|
|
name: Name
|
|
title: Title
|
|
about: About
|
|
labels: label1,label2,,label3 ,,
|
|
ref: Ref
|
|
---
|
|
Content
|
|
`,
|
|
want: &api.IssueTemplate{
|
|
Name: "Name",
|
|
Title: "Title",
|
|
About: "About",
|
|
Labels: []string{"label1", "label2", "label3"},
|
|
Ref: "Ref",
|
|
Fields: nil,
|
|
Content: "Content\n",
|
|
FileName: "test.md",
|
|
},
|
|
wantErr: "",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
filename := "test.yaml"
|
|
if tt.filename != "" {
|
|
filename = tt.filename
|
|
}
|
|
tmpl, err := unmarshal(filename, []byte(tt.content))
|
|
require.NoError(t, err)
|
|
if tt.wantErr != "" {
|
|
require.EqualError(t, Validate(tmpl), tt.wantErr)
|
|
} else {
|
|
require.NoError(t, Validate(tmpl))
|
|
want, _ := json.Marshal(tt.want)
|
|
got, _ := json.Marshal(tmpl)
|
|
require.JSONEq(t, string(want), string(got))
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRenderToMarkdown(t *testing.T) {
|
|
type args struct {
|
|
template string
|
|
values url.Values
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want string
|
|
}{
|
|
{
|
|
name: "normal",
|
|
args: args{
|
|
template: `
|
|
name: Name
|
|
title: Title
|
|
about: About
|
|
labels: ["label1", "label2"]
|
|
ref: Ref
|
|
body:
|
|
- type: markdown
|
|
id: id1
|
|
attributes:
|
|
value: Value of the markdown shown in form
|
|
- type: markdown
|
|
id: id2
|
|
attributes:
|
|
value: Value of the markdown shown in created issue
|
|
visible: [content]
|
|
- type: textarea
|
|
id: id3
|
|
attributes:
|
|
label: Label of textarea
|
|
description: Description of textarea
|
|
placeholder: Placeholder of textarea
|
|
value: Value of textarea
|
|
render: bash
|
|
validations:
|
|
required: true
|
|
- type: input
|
|
id: id4
|
|
attributes:
|
|
label: Label of input
|
|
description: Description of input
|
|
placeholder: Placeholder of input
|
|
value: Value of input
|
|
hide_label: true
|
|
validations:
|
|
required: true
|
|
is_number: true
|
|
regex: "[a-zA-Z0-9]+"
|
|
- type: dropdown
|
|
id: id5
|
|
attributes:
|
|
label: Label of dropdown (one line)
|
|
description: Description of dropdown
|
|
multiple: true
|
|
options:
|
|
- Option 1 of dropdown
|
|
- Option 2 of dropdown
|
|
- Option 3 of dropdown
|
|
validations:
|
|
required: true
|
|
- type: dropdown
|
|
id: id6
|
|
attributes:
|
|
label: Label of dropdown (list)
|
|
description: Description of dropdown
|
|
multiple: true
|
|
list: true
|
|
options:
|
|
- Option 1 of dropdown
|
|
- Option 2 of dropdown
|
|
- Option 3 of dropdown
|
|
validations:
|
|
required: true
|
|
- type: checkboxes
|
|
id: id7
|
|
attributes:
|
|
label: Label of checkboxes
|
|
description: Description of checkboxes
|
|
options:
|
|
- label: Option 1 of checkboxes
|
|
required: true
|
|
- label: Option 2 of checkboxes
|
|
required: false
|
|
- label: Option 3 of checkboxes
|
|
required: true
|
|
visible: [form]
|
|
- label: Hidden Option of checkboxes
|
|
visible: [content]
|
|
`,
|
|
values: map[string][]string{
|
|
"form-field-id3": {"Value of id3"},
|
|
"form-field-id4": {"Value of id4"},
|
|
"form-field-id5": {"0,1"},
|
|
"form-field-id6": {"1,2"},
|
|
"form-field-id7-0": {"on"},
|
|
"form-field-id7-2": {"on"},
|
|
},
|
|
},
|
|
|
|
want: `Value of the markdown shown in created issue
|
|
|
|
### Label of textarea
|
|
|
|
` + "```bash\nValue of id3\n```" + `
|
|
|
|
Value of id4
|
|
|
|
### Label of dropdown (one line)
|
|
|
|
Option 1 of dropdown, Option 2 of dropdown
|
|
|
|
### Label of dropdown (list)
|
|
|
|
- Option 2 of dropdown
|
|
- Option 3 of dropdown
|
|
|
|
### Label of checkboxes
|
|
|
|
- [x] Option 1 of checkboxes
|
|
- [ ] Option 2 of checkboxes
|
|
- [ ] Hidden Option of checkboxes
|
|
|
|
`,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
template, err := Unmarshal("test.yaml", []byte(tt.args.template))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got := RenderToMarkdown(template, tt.args.values); got != tt.want {
|
|
assert.Equal(t, tt.want, got)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func Test_minQuotes(t *testing.T) {
|
|
type args struct {
|
|
value string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want string
|
|
}{
|
|
{
|
|
name: "without quote",
|
|
args: args{
|
|
value: "Hello\nWorld",
|
|
},
|
|
want: "```",
|
|
},
|
|
{
|
|
name: "with 1 quote",
|
|
args: args{
|
|
value: "Hello\nWorld\n`text`\n",
|
|
},
|
|
want: "```",
|
|
},
|
|
{
|
|
name: "with 3 quotes",
|
|
args: args{
|
|
value: "Hello\nWorld\n`text`\n```go\ntext\n```\n",
|
|
},
|
|
want: "````",
|
|
},
|
|
{
|
|
name: "with more quotes",
|
|
args: args{
|
|
value: "Hello\nWorld\n`text`\n```go\ntext\n```\n``````````bash\ntext\n``````````\n",
|
|
},
|
|
want: "```````````",
|
|
},
|
|
{
|
|
name: "not leading quotes",
|
|
args: args{
|
|
value: "Hello\nWorld`text````go\ntext`````````````bash\ntext``````````\n",
|
|
},
|
|
want: "```",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := minQuotes(tt.args.value)
|
|
assert.Equal(t, tt.want, got)
|
|
})
|
|
}
|
|
}
|