mirror of
https://github.com/go-gitea/gitea.git
synced 2024-12-23 17:13:46 +08:00
77e29e0c39
Add new option: `visible`: witch can hide a specific field of the form or the created content afterwards It is a string array witch can contain `form` and `content`. If only `form` is present, it wont show up in the created issue afterwards and the other way around. By default it sets both except for markdown As they are optional and github don't have any similar thing, it is non breaking and also do not conflict with it. With this you can: - define "post issue creation" elements like a TODO list to track an issue state - make sure to have a checkbox that reminds the user to check for a thing but dont have it in the created issue afterwards - define markdown for the created issue (was the downside of using yaml instead of md in the past) - ... ## Demo ```yaml name: New Contribution description: External Contributor creating a pull body: - type: checkboxes id: extern-todo visible: [form] attributes: label: Contribution Guidelines options: - label: I checked there exist no similar feature to be extended required: true - label: I did read the CONTRIBUTION.MD required: true - type: checkboxes id: intern-todo visible: [content] attributes: label: Maintainer Check-List options: - label: Does this pull follow the KISS principe - label: Checked if internal bord was notifyed # .... ``` [Demo Video](https://cloud.obermui.de/s/tm34fSAbJp9qw9z/download/vid-20240220-152751.mkv) --- *Sponsored by Kithara Software GmbH* --------- Co-authored-by: John Olheiser <john.olheiser@gmail.com> Co-authored-by: delvh <dev.lh@web.de>
839 lines
17 KiB
Go
839 lines
17 KiB
Go
// Copyright 2022 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package template
|
|
|
|
import (
|
|
"net/url"
|
|
"testing"
|
|
|
|
"code.gitea.io/gitea/modules/json"
|
|
api "code.gitea.io/gitea/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: "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 a 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: "valid",
|
|
content: `
|
|
name: Name
|
|
title: Title
|
|
about: About
|
|
labels: ["label1", "label2"]
|
|
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
|
|
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"},
|
|
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",
|
|
},
|
|
},
|
|
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
|
|
description: Description of dropdown
|
|
multiple: true
|
|
options:
|
|
- Option 1 of dropdown
|
|
- Option 2 of dropdown
|
|
- Option 3 of dropdown
|
|
validations:
|
|
required: true
|
|
- type: checkboxes
|
|
id: id6
|
|
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-0": {"on"},
|
|
"form-field-id6-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
|
|
|
|
Option 1 of dropdown, Option 2 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.EqualValues(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) {
|
|
if got := minQuotes(tt.args.value); got != tt.want {
|
|
t.Errorf("minQuotes() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|