drawio-export/pkg/drawio/export_test.go
Алексей Бадяев b32f3ab88a
Some checks failed
golangci-lint / lint (stable, ubuntu-latest) (push) Failing after 4s
golangci-lint / lint (stable, windows-latest) (push) Failing after 12s
build / build (push) Failing after 27s
build / build_windows (push) Successful in 52s
Добавлен линтер golangci-lint
2024-10-17 23:29:54 +07:00

423 lines
10 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package drawio_test
import (
"io"
"io/fs"
"os"
"os/exec"
"path"
"strings"
"testing"
"time"
"git.mousesoft.ru/ms/drawio-export/pkg/drawio"
"github.com/stretchr/testify/assert"
)
// Команда оболочки ОС
type command struct {
cmd string // Команда
args []string // Аргументы команды
}
// Файл с диаграммами
type source struct {
output string // Папка вывода для ExportFile
data string // Данные файла с диаграммами
diagrams []string // Срез имён диаграмм
commands []command // Ожидаемые команды экспорта диаграмм
}
// Элемент папки с файлами
type dirEntry struct {
name string // Имя элемента
isDir bool // Истина, если элемент является папкой
}
var (
_ os.DirEntry = (*dirEntry)(nil)
_ os.FileInfo = (*dirEntry)(nil)
)
func (entry dirEntry) Name() string {
return entry.name
}
func (entry dirEntry) IsDir() bool {
return entry.isDir
}
func (entry dirEntry) Type() fs.FileMode {
if entry.isDir {
return fs.ModeDir
}
return 0
}
func (entry dirEntry) Info() (fs.FileInfo, error) {
return nil, nil
}
func (entry dirEntry) Size() int64 {
return 100
}
func (entry dirEntry) Mode() fs.FileMode {
return entry.Type()
}
func (entry dirEntry) ModTime() time.Time {
return time.Now()
}
func (entry dirEntry) Sys() any {
return nil
}
// Конвертация команд в информацию о командах
func cmd2info(commands []*exec.Cmd) []command {
cmdInfo := make([]command, len(commands))
for i, cmd := range commands {
cmdInfo[i] = command{
cmd: cmd.Path,
args: make([]string, len(cmd.Args)),
}
copy(cmdInfo[i].args, cmd.Args)
}
return cmdInfo
}
type exportTest struct {
name string // Наименование теста
dirs map[string][]os.DirEntry // Папки файлов с диаграммами
files map[string]source // Файлы с диаграммами
}
// Информация об ожидаемых командах при экспорте папки
func (test exportTest) dirCommands(dir string, recursive bool) []command {
commands := make([]command, 0, 4)
if tc, ok := test.dirs[dir]; ok {
for _, entry := range tc {
path := path.Join(dir, entry.Name())
if entry.IsDir() && recursive {
commands = append(commands, test.dirCommands(path, true)...)
} else {
commands = append(commands, test.files[path].commands...)
}
}
}
return commands
}
// Тестовые данные
var testData = []exportTest{
{
name: "positive case",
dirs: map[string][]os.DirEntry{
"source": {
dirEntry{name: "diagrams.drawio", isDir: false},
},
},
files: map[string]source{
"source/diagrams.drawio": {
data: `<mxfile host="test">
<diagram name="1" id="01">
<mxGraphModel page="1">
</mxGraphModel>
</diagram>
<diagram name="2" id="02">
<mxGraphModel page="1">
</mxGraphModel>
</diagram>
<diagram name="3" id="03">
<mxGraphModel page="1">
</mxGraphModel>
</diagram>
</mxfile>`,
diagrams: []string{"1", "2", "3"},
commands: []command{
{
cmd: "drawio",
args: []string{
"drawio", "--page-index", "0",
"--output", "export/diagrams-1.pdf",
"--export", "source/diagrams.drawio",
},
},
{
cmd: "drawio",
args: []string{
"drawio", "--page-index", "1",
"--output", "export/diagrams-2.pdf",
"--export", "source/diagrams.drawio",
},
},
{
cmd: "drawio",
args: []string{
"drawio", "--page-index", "2",
"--output", "export/diagrams-3.pdf",
"--export", "source/diagrams.drawio",
},
},
},
},
},
},
{
name: "invalid source",
dirs: map[string][]os.DirEntry{
"source": {
dirEntry{name: "diagrams.drawio", isDir: false},
},
},
files: map[string]source{
"source/diagrams.drawio": {
data: `<nxfile host="test">
<diagram name="1" id="01">
<mxGraphModel page="1">
</mxGraphModel>
</diagram>
<diagram name="2" id="02">
<mxGraphModel page="1">
</mxGraphModel>
</diagram>
<diagram name="3" id="03">
<mxGraphModel page="1">
</mxGraphModel>
</diagram>
</nxfile>`,
diagrams: []string{},
},
},
},
{
name: "nested dirs",
dirs: map[string][]os.DirEntry{
"source": {
dirEntry{name: "diagrams.drawio", isDir: false},
dirEntry{name: "subdir", isDir: true},
dirEntry{name: "additional.xml", isDir: false},
},
"source/subdir": {
dirEntry{name: "Вложенные диаграммы.drawio", isDir: false},
},
},
files: map[string]source{
"source/diagrams.drawio": {
data: `<mxfile host="test">
<diagram name="1" id="01">
<mxGraphModel page="1">
</mxGraphModel>
</diagram>
<diagram name="2" id="02">
<mxGraphModel page="1">
</mxGraphModel>
</diagram>
<diagram name="3" id="03">
<mxGraphModel page="1">
</mxGraphModel>
</diagram>
</mxfile>`,
diagrams: []string{"1", "2", "3"},
commands: []command{
{
cmd: "drawio",
args: []string{
"drawio", "--page-index", "0",
"--output", "export/diagrams-1.pdf",
"--export", "source/diagrams.drawio",
},
},
{
cmd: "drawio",
args: []string{
"drawio", "--page-index", "1",
"--output", "export/diagrams-2.pdf",
"--export", "source/diagrams.drawio",
},
},
{
cmd: "drawio",
args: []string{
"drawio", "--page-index", "2",
"--output", "export/diagrams-3.pdf",
"--export", "source/diagrams.drawio",
},
},
},
},
"source/additional.xml": {
data: `<mxfile host="test">
<diagram name="Один" id="01">
<mxGraphModel page="1">
</mxGraphModel>
</diagram>
<diagram name="Два" id="02">
<mxGraphModel page="1">
</mxGraphModel>
</diagram>
</mxfile>`,
diagrams: []string{"Один", "Два"},
commands: []command{
{
cmd: "drawio",
args: []string{
"drawio", "--page-index", "0",
"--output", "export/additional-Один.pdf",
"--export", "source/additional.xml",
},
},
{
cmd: "drawio",
args: []string{
"drawio", "--page-index", "1",
"--output", "export/additional-Два.pdf",
"--export", "source/additional.xml",
},
},
},
},
"source/subdir/Вложенные диаграммы.drawio": {
output: "export/subdir",
data: `<mxfile host="test">
<diagram name="Первая диаграмма" id="01">
<mxGraphModel page="1">
</mxGraphModel>
</diagram>
<diagram name="Вторая диаграмма" id="02">
<mxGraphModel page="1">
</mxGraphModel>
</diagram>
</mxfile>`,
diagrams: []string{"Первая диаграмма", "Вторая диаграмма"},
commands: []command{
{
cmd: "drawio",
args: []string{
"drawio", "--page-index", "0",
"--output", "export/subdir/Вложенные диаграммы-Первая диаграмма.pdf",
"--export", "source/subdir/Вложенные диаграммы.drawio",
},
},
{
cmd: "drawio",
args: []string{
"drawio", "--page-index", "1",
"--output", "export/subdir/Вложенные диаграммы-Вторая диаграмма.pdf",
"--export", "source/subdir/Вложенные диаграммы.drawio",
},
},
},
},
},
},
}
// Инициализация тестовых данных
func init() {
for _, test := range testData {
for _, src := range test.files {
for i := range src.commands {
cmd := exec.Command("drawio")
src.commands[i].cmd = cmd.Path
}
}
}
}
func TestDiagrams(t *testing.T) {
for _, test := range testData {
t.Run(test.name, func(t *testing.T) {
for filePath, source := range test.files {
t.Run(filePath, func(t *testing.T) {
diagrams, err := drawio.Diagrams(strings.NewReader(source.data))
assert.NoError(t, err)
assert.ElementsMatch(t, source.diagrams, diagrams)
})
}
})
}
}
func TestExportFile(t *testing.T) {
for _, test := range testData {
t.Run(test.name, func(t *testing.T) {
for filePath, source := range test.files {
var openOpt drawio.Option = drawio.WithNop()
if len(source.output) > 0 {
openOpt = drawio.WithOutput(source.output)
}
t.Run(filePath, func(t *testing.T) {
var (
openFileCalls = []string{}
exp = drawio.New(
drawio.WithOpenFile(func(s string) (io.ReadCloser, error) {
openFileCalls = append(openFileCalls, s)
return io.NopCloser(strings.NewReader(source.data)), nil
}),
openOpt,
)
)
commands, err := exp.ExportFile(filePath, []string{})
assert.NoError(t, err)
if assert.Equal(t, 1, len(openFileCalls)) {
assert.Equal(t, filePath, openFileCalls[0])
}
assert.ElementsMatch(t, source.commands, cmd2info(commands))
})
}
})
}
}
func TestExportDir(t *testing.T) {
for _, recursive := range []bool{false, true} {
var (
name string
recursiveOption drawio.Option
)
if recursive {
name = "recursive"
recursiveOption = drawio.WithRecursive()
} else {
name = "non-recursive"
recursiveOption = drawio.WithNop()
}
t.Run(name, func(t *testing.T) {
for _, test := range testData {
t.Run(test.name, func(t *testing.T) {
var (
openFileCalls = []string{}
exp = drawio.New(
drawio.WithOpenFile(func(s string) (io.ReadCloser, error) {
openFileCalls = append(openFileCalls, s)
return io.NopCloser(
strings.NewReader(test.files[s].data),
), nil
}),
drawio.WithReadDir(func(s string) ([]os.DirEntry, error) {
return test.dirs[s], nil
}),
recursiveOption,
)
)
for dir := range test.dirs {
pathDir, _ := path.Split(dir)
if len(pathDir) > 0 {
continue
}
t.Run(dir, func(t *testing.T) {
openFileCalls = openFileCalls[:0]
commands, err := exp.ExportDir(dir, []string{})
assert.NoError(t, err)
assert.ElementsMatch(t,
test.dirCommands(dir, recursive), cmd2info(commands))
})
}
})
}
})
}
}