drawio-export/pkg/drawio/export_test.go

411 lines
10 KiB
Go
Raw Normal View History

package drawio_test
import (
"io"
"io/fs"
"os"
"os/exec"
"path"
"strings"
"testing"
"time"
"git.mousesoft.ru/ms/drawio-exporter/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: "/usr/bin/drawio",
args: []string{
"drawio", "--page-index", "0",
"--output", "export/diagrams-1.pdf",
"--export", "source/diagrams.drawio",
},
},
{
cmd: "/usr/bin/drawio",
args: []string{
"drawio", "--page-index", "1",
"--output", "export/diagrams-2.pdf",
"--export", "source/diagrams.drawio",
},
},
{
cmd: "/usr/bin/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: "/usr/bin/drawio",
args: []string{
"drawio", "--page-index", "0",
"--output", "export/diagrams-1.pdf",
"--export", "source/diagrams.drawio",
},
},
{
cmd: "/usr/bin/drawio",
args: []string{
"drawio", "--page-index", "1",
"--output", "export/diagrams-2.pdf",
"--export", "source/diagrams.drawio",
},
},
{
cmd: "/usr/bin/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: "/usr/bin/drawio",
args: []string{
"drawio", "--page-index", "0",
"--output", "export/additional-Один.pdf",
"--export", "source/additional.xml",
},
},
{
cmd: "/usr/bin/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: "/usr/bin/drawio",
args: []string{
"drawio", "--page-index", "0",
"--output", "export/subdir/Вложенные диаграммы-Первая диаграмма.pdf",
"--export", "source/subdir/Вложенные диаграммы.drawio",
},
},
{
cmd: "/usr/bin/drawio",
args: []string{
"drawio", "--page-index", "1",
"--output", "export/subdir/Вложенные диаграммы-Вторая диаграмма.pdf",
"--export", "source/subdir/Вложенные диаграммы.drawio",
},
},
},
},
},
},
}
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.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))
})
}
})
}
})
}
}