Фазы 2-3: мульти-окна (WindowController, per-window FileStore), файловое дерево (FileStore+FileTreePanel, иконки/раскрытие/ПКМ/+drag&drop/подтверждения), NameDialog/ConfirmDialog; тест filestore (13/13)
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
// Тест FileStore (Фаза 3): дерево хранилища, создание/переименование/
|
||||
// удаление/перемещение, раскрытие папок, иконки, валидация имён.
|
||||
#include <QCoreApplication>
|
||||
#include <QTemporaryDir>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <cstdio>
|
||||
|
||||
#include "core/FileStore.h"
|
||||
|
||||
static int fail(const char *msg, const QString &detail = QString())
|
||||
{
|
||||
std::fprintf(stderr, "FAIL: %s %s\n", msg, qPrintable(detail));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rowOf(FileStore &fs, const QString &path)
|
||||
{
|
||||
const int n = fs.rowCount();
|
||||
for (int i = 0; i < n; ++i)
|
||||
if (fs.itemPath(i) == path)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
QTemporaryDir dir;
|
||||
if (!dir.isValid())
|
||||
return fail("temp dir");
|
||||
|
||||
FileStore fs;
|
||||
const QString vault = dir.path();
|
||||
QString err = fs.openVault(vault);
|
||||
if (!err.isEmpty())
|
||||
return fail("openVault", err);
|
||||
|
||||
// --- создание ---
|
||||
err = fs.createFile(vault, "note.md");
|
||||
if (!err.isEmpty())
|
||||
return fail("createFile", err);
|
||||
err = fs.createFolder(vault, "sub");
|
||||
if (!err.isEmpty())
|
||||
return fail("createFolder", err);
|
||||
err = fs.createFolder(dir.path() + "/sub", "deep");
|
||||
if (!err.isEmpty())
|
||||
return fail("createFolder deep", err);
|
||||
err = fs.createFile(dir.path() + "/sub", "inner.txt");
|
||||
if (!err.isEmpty())
|
||||
return fail("createFile inner", err);
|
||||
|
||||
const QString note = dir.path() + "/note.md";
|
||||
const QString sub = dir.path() + "/sub";
|
||||
const QString deep = dir.path() + "/sub/deep";
|
||||
const QString inner = dir.path() + "/sub/inner.txt";
|
||||
|
||||
// Папка sub содержит children; deep пустая
|
||||
if (rowOf(fs, sub) < 0)
|
||||
return fail("sub не в дереве");
|
||||
|
||||
// --- иконки (sub автоматически раскрыта после создания) ---
|
||||
{
|
||||
const QString subIcon = fs.data(fs.index(rowOf(fs, sub)), FileStore::IconRole).toString();
|
||||
if (subIcon != "folder")
|
||||
return fail("иконка sub", subIcon);
|
||||
const int ri = rowOf(fs, deep);
|
||||
if (ri < 0)
|
||||
return fail("deep не видна (авто-раскрытие)", QString());
|
||||
const QString deepIcon = fs.data(fs.index(ri), FileStore::IconRole).toString();
|
||||
if (deepIcon != "folder-empty")
|
||||
return fail("иконка deep", deepIcon);
|
||||
}
|
||||
|
||||
// --- раскрытие/сворачивание ---
|
||||
{
|
||||
const int subRow = rowOf(fs, sub);
|
||||
if (subRow < 0)
|
||||
return fail("sub отсутствует");
|
||||
if (rowOf(fs, inner) < 0 || rowOf(fs, deep) < 0)
|
||||
return fail("вложенное не видно при раскрытой sub");
|
||||
|
||||
fs.toggleExpand(subRow); // сворачиваем
|
||||
if (rowOf(fs, inner) >= 0 || rowOf(fs, deep) >= 0)
|
||||
return fail("свёрнутая sub показывает вложенное");
|
||||
|
||||
fs.toggleExpand(rowOf(fs, sub)); // раскрываем снова
|
||||
if (rowOf(fs, inner) < 0 || rowOf(fs, deep) < 0)
|
||||
return fail("повторное раскрытие не работает");
|
||||
}
|
||||
|
||||
// --- переименование ---
|
||||
err = fs.renameItem(deep, "deep2");
|
||||
if (!err.isEmpty())
|
||||
return fail("renameItem", err);
|
||||
if (!QDir(dir.path() + "/sub/deep2").exists())
|
||||
return fail("rename: папка не переименована");
|
||||
|
||||
// --- перемещение ---
|
||||
err = fs.moveItem(note, sub);
|
||||
if (!err.isEmpty())
|
||||
return fail("moveItem", err);
|
||||
if (!QFile::exists(dir.path() + "/sub/note.md"))
|
||||
return fail("move: файл не перемещён");
|
||||
|
||||
// --- удаление ---
|
||||
err = fs.removeItem(dir.path() + "/sub/inner.txt");
|
||||
if (!err.isEmpty())
|
||||
return fail("removeItem file", err);
|
||||
err = fs.removeItem(dir.path() + "/sub/deep2");
|
||||
if (!err.isEmpty())
|
||||
return fail("removeItem dir", err);
|
||||
err = fs.removeItem(sub);
|
||||
if (!err.isEmpty())
|
||||
return fail("removeItem sub", err);
|
||||
if (QDir(sub).exists())
|
||||
return fail("папка осталась после удаления");
|
||||
|
||||
// --- валидация ---
|
||||
if (fs.createFile(vault, "bad/name").isEmpty())
|
||||
return fail("имя с '/' принято");
|
||||
if (fs.createFile(vault, "").isEmpty())
|
||||
return fail("пустое имя принято");
|
||||
if (fs.renameItem(dir.path() + "/note.md", "../escape").isEmpty())
|
||||
return fail("переименование с '..' принято");
|
||||
|
||||
// --- невалидное хранилище ---
|
||||
if (fs.openVault("/нет/такого/пути_xyz").isEmpty())
|
||||
return fail("openVault неверный путь");
|
||||
|
||||
std::printf("FILESTORE TEST OK\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user