423 lines
10 KiB
Go
423 lines
10 KiB
Go
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))
|
||
})
|
||
}
|
||
})
|
||
}
|
||
})
|
||
}
|
||
}
|