2023-04-08 22:04:55 +07:00
|
|
|
|
package drawio_test
|
|
|
|
|
|
|
|
|
|
import (
|
2023-04-12 22:37:54 +07:00
|
|
|
|
"io"
|
|
|
|
|
"io/fs"
|
|
|
|
|
"os"
|
|
|
|
|
"os/exec"
|
|
|
|
|
"path"
|
2023-04-08 22:04:55 +07:00
|
|
|
|
"strings"
|
|
|
|
|
"testing"
|
2023-04-12 22:37:54 +07:00
|
|
|
|
"time"
|
2023-04-08 22:04:55 +07:00
|
|
|
|
|
|
|
|
|
"git.mousesoft.ru/ms/drawio-exporter/pkg/drawio"
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
|
)
|
|
|
|
|
|
2023-04-12 22:37:54 +07:00
|
|
|
|
// Команда оболочки ОС
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-08 22:04:55 +07:00
|
|
|
|
// Тестовые данные
|
2023-04-12 22:37:54 +07:00
|
|
|
|
var testData = []exportTest{
|
2023-04-08 22:04:55 +07:00
|
|
|
|
{
|
|
|
|
|
name: "positive case",
|
2023-04-12 22:37:54 +07:00
|
|
|
|
dirs: map[string][]os.DirEntry{
|
|
|
|
|
"source": {
|
|
|
|
|
dirEntry{name: "diagrams.drawio", isDir: false},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
files: map[string]source{
|
|
|
|
|
"source/diagrams.drawio": {
|
|
|
|
|
data: `<mxfile host="test">
|
2023-04-08 22:04:55 +07:00
|
|
|
|
<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>`,
|
2023-04-12 22:37:54 +07:00
|
|
|
|
diagrams: []string{"1", "2", "3"},
|
|
|
|
|
commands: []command{
|
|
|
|
|
{
|
2023-07-02 13:02:04 +07:00
|
|
|
|
cmd: "drawio",
|
2023-04-12 22:37:54 +07:00
|
|
|
|
args: []string{
|
|
|
|
|
"drawio", "--page-index", "0",
|
|
|
|
|
"--output", "export/diagrams-1.pdf",
|
|
|
|
|
"--export", "source/diagrams.drawio",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
2023-07-02 13:02:04 +07:00
|
|
|
|
cmd: "drawio",
|
2023-04-12 22:37:54 +07:00
|
|
|
|
args: []string{
|
|
|
|
|
"drawio", "--page-index", "1",
|
|
|
|
|
"--output", "export/diagrams-2.pdf",
|
|
|
|
|
"--export", "source/diagrams.drawio",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
2023-07-02 13:02:04 +07:00
|
|
|
|
cmd: "drawio",
|
2023-04-12 22:37:54 +07:00
|
|
|
|
args: []string{
|
|
|
|
|
"drawio", "--page-index", "2",
|
|
|
|
|
"--output", "export/diagrams-3.pdf",
|
|
|
|
|
"--export", "source/diagrams.drawio",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
2023-04-08 22:04:55 +07:00
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "invalid source",
|
2023-04-12 22:37:54 +07:00
|
|
|
|
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">
|
2023-04-08 22:04:55 +07:00
|
|
|
|
<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>
|
2023-04-12 22:37:54 +07:00
|
|
|
|
</mxfile>`,
|
|
|
|
|
diagrams: []string{"1", "2", "3"},
|
|
|
|
|
commands: []command{
|
|
|
|
|
{
|
2023-07-02 13:02:04 +07:00
|
|
|
|
cmd: "drawio",
|
2023-04-12 22:37:54 +07:00
|
|
|
|
args: []string{
|
|
|
|
|
"drawio", "--page-index", "0",
|
|
|
|
|
"--output", "export/diagrams-1.pdf",
|
|
|
|
|
"--export", "source/diagrams.drawio",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
2023-07-02 13:02:04 +07:00
|
|
|
|
cmd: "drawio",
|
2023-04-12 22:37:54 +07:00
|
|
|
|
args: []string{
|
|
|
|
|
"drawio", "--page-index", "1",
|
|
|
|
|
"--output", "export/diagrams-2.pdf",
|
|
|
|
|
"--export", "source/diagrams.drawio",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
2023-07-02 13:02:04 +07:00
|
|
|
|
cmd: "drawio",
|
2023-04-12 22:37:54 +07:00
|
|
|
|
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{
|
|
|
|
|
{
|
2023-07-02 13:02:04 +07:00
|
|
|
|
cmd: "drawio",
|
2023-04-12 22:37:54 +07:00
|
|
|
|
args: []string{
|
|
|
|
|
"drawio", "--page-index", "0",
|
|
|
|
|
"--output", "export/additional-Один.pdf",
|
|
|
|
|
"--export", "source/additional.xml",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
2023-07-02 13:02:04 +07:00
|
|
|
|
cmd: "drawio",
|
2023-04-12 22:37:54 +07:00
|
|
|
|
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{
|
|
|
|
|
{
|
2023-07-02 13:02:04 +07:00
|
|
|
|
cmd: "drawio",
|
2023-04-12 22:37:54 +07:00
|
|
|
|
args: []string{
|
|
|
|
|
"drawio", "--page-index", "0",
|
|
|
|
|
"--output", "export/subdir/Вложенные диаграммы-Первая диаграмма.pdf",
|
|
|
|
|
"--export", "source/subdir/Вложенные диаграммы.drawio",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
2023-07-02 13:02:04 +07:00
|
|
|
|
cmd: "drawio",
|
2023-04-12 22:37:54 +07:00
|
|
|
|
args: []string{
|
|
|
|
|
"drawio", "--page-index", "1",
|
|
|
|
|
"--output", "export/subdir/Вложенные диаграммы-Вторая диаграмма.pdf",
|
|
|
|
|
"--export", "source/subdir/Вложенные диаграммы.drawio",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
2023-04-08 22:04:55 +07:00
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
2023-07-02 13:02:04 +07:00
|
|
|
|
// Инициализация тестовых данных
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-08 22:04:55 +07:00
|
|
|
|
func TestDiagrams(t *testing.T) {
|
|
|
|
|
for _, test := range testData {
|
|
|
|
|
t.Run(test.name, func(t *testing.T) {
|
2023-04-12 22:37:54 +07:00
|
|
|
|
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))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
2023-04-08 22:04:55 +07:00
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|