2026-08-17 01:14:00 +03:00
|
|
|
// Тест DocumentManager (Фаза 4): открытие вкладок, редактирование,
|
|
|
|
|
// сохранение, автосохранение по таймеру, закрытие, заголовки, dirty-флаги.
|
|
|
|
|
#include <QCoreApplication>
|
|
|
|
|
#include <QTemporaryDir>
|
|
|
|
|
#include <QDir>
|
|
|
|
|
#include <QFile>
|
|
|
|
|
#include <QTimer>
|
|
|
|
|
#include <cstdio>
|
|
|
|
|
|
|
|
|
|
#include "core/DocumentManager.h"
|
|
|
|
|
|
|
|
|
|
static int fail(const char *msg, const QString &detail = QString())
|
|
|
|
|
{
|
|
|
|
|
std::fprintf(stderr, "FAIL: %s %s\n", msg, qPrintable(detail));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
|
{
|
|
|
|
|
QCoreApplication app(argc, argv);
|
|
|
|
|
|
|
|
|
|
QTemporaryDir dir;
|
|
|
|
|
if (!dir.isValid())
|
|
|
|
|
return fail("temp dir");
|
|
|
|
|
|
|
|
|
|
const QString vault = dir.path();
|
|
|
|
|
QDir(vault).mkpath("sub");
|
|
|
|
|
|
|
|
|
|
// --- открытие ---
|
|
|
|
|
{
|
|
|
|
|
QFile f(vault + "/a.md");
|
|
|
|
|
f.open(QIODevice::WriteOnly);
|
|
|
|
|
f.write("# A\n");
|
|
|
|
|
f.close();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DocumentManager dm;
|
|
|
|
|
dm.setAutosaveIntervalMs(300); // быстрый автосейв для теста
|
|
|
|
|
|
|
|
|
|
int idx = dm.openDocument(vault + "/a.md");
|
|
|
|
|
if (idx != 0)
|
|
|
|
|
return fail("openDocument вернул неверный индекс", QString::number(idx));
|
|
|
|
|
if (dm.openTabs().size() != 1)
|
|
|
|
|
return fail("вкладка не создана");
|
|
|
|
|
if (dm.contentAt(0) != "# A\n")
|
|
|
|
|
return fail("содержимое не прочитано");
|
|
|
|
|
if (dm.titleAt(0) != "a.md")
|
|
|
|
|
return fail("заголовок", dm.titleAt(0));
|
|
|
|
|
if (dm.isDirty(0))
|
|
|
|
|
return fail("свежий файл помечен изменённым");
|
|
|
|
|
|
|
|
|
|
// --- повторное открытие той же вкладки ---
|
|
|
|
|
if (dm.openDocument(vault + "/a.md") != 0)
|
|
|
|
|
return fail("повторное открытие создало новую вкладку");
|
|
|
|
|
|
|
|
|
|
// --- редактирование ---
|
|
|
|
|
dm.updateContent(0, "# A edited\n\nНовый текст\n");
|
|
|
|
|
if (!dm.isDirty(0))
|
|
|
|
|
return fail("правка не помечена");
|
|
|
|
|
if (dm.contentAt(0).isEmpty() || !dm.contentAt(0).contains("Новый текст"))
|
|
|
|
|
return fail("контент не обновился");
|
|
|
|
|
|
|
|
|
|
// --- сохранение ---
|
|
|
|
|
dm.saveDocument(0);
|
|
|
|
|
if (dm.isDirty(0))
|
|
|
|
|
return fail("после сохранения dirty остался");
|
|
|
|
|
{
|
|
|
|
|
QFile f(vault + "/a.md");
|
|
|
|
|
f.open(QIODevice::ReadOnly);
|
|
|
|
|
const QString s = QString::fromUtf8(f.readAll());
|
|
|
|
|
if (!s.contains("Новый текст"))
|
|
|
|
|
return fail("файл не записан");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --- автосохранение по таймеру ---
|
|
|
|
|
dm.updateContent(0, "# A edited\n\nАвтосейв\n");
|
|
|
|
|
{
|
2026-09-01 19:25:07 +03:00
|
|
|
// используем отдельный event-loop, чтобы не триггерить aboutToQuit
|
|
|
|
|
QEventLoop loop;
|
2026-08-17 01:14:00 +03:00
|
|
|
QTimer t;
|
2026-09-01 19:25:07 +03:00
|
|
|
QObject::connect(&t, &QTimer::timeout, &loop, &QEventLoop::quit);
|
2026-08-17 01:14:00 +03:00
|
|
|
t.setSingleShot(true);
|
|
|
|
|
t.start(700);
|
2026-09-01 19:25:07 +03:00
|
|
|
loop.exec();
|
2026-08-17 01:14:00 +03:00
|
|
|
}
|
|
|
|
|
if (dm.isDirty(0))
|
|
|
|
|
return fail("автосохранение не сработало");
|
|
|
|
|
{
|
|
|
|
|
QFile f(vault + "/a.md");
|
|
|
|
|
f.open(QIODevice::ReadOnly);
|
|
|
|
|
if (!QString::fromUtf8(f.readAll()).contains("Автосейв"))
|
|
|
|
|
return fail("автосохранение не записало файл");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --- второй документ и закрытие ---
|
|
|
|
|
{
|
|
|
|
|
QFile f(vault + "/sub/b.md");
|
|
|
|
|
f.open(QIODevice::WriteOnly);
|
|
|
|
|
f.write("b\n");
|
|
|
|
|
f.close();
|
|
|
|
|
}
|
|
|
|
|
const int idxB = dm.openDocument(vault + "/sub/b.md");
|
|
|
|
|
if (idxB != 1)
|
|
|
|
|
return fail("второй документ", QString::number(idxB));
|
|
|
|
|
if (dm.openTabs().size() != 2)
|
|
|
|
|
return fail("вкладок должно быть 2");
|
|
|
|
|
|
|
|
|
|
dm.updateContent(idxB, "b изменён");
|
|
|
|
|
if (!dm.closeTab(1))
|
|
|
|
|
return fail("closeTab");
|
|
|
|
|
if (dm.openTabs().size() != 1)
|
|
|
|
|
return fail("вкладка не закрыта");
|
|
|
|
|
if (dm.isDirty(0))
|
|
|
|
|
return fail("активная вкладка испорчена после закрытия");
|
|
|
|
|
{
|
|
|
|
|
QFile f(vault + "/sub/b.md");
|
|
|
|
|
f.open(QIODevice::ReadOnly);
|
|
|
|
|
if (!QString::fromUtf8(f.readAll()).contains("изменён"))
|
|
|
|
|
return fail("закрытие не сохранило изменённый документ");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --- несуществующий файл ---
|
|
|
|
|
if (dm.openDocument(vault + "/нет.md") != -1)
|
|
|
|
|
return fail("открытие несуществующего файла");
|
|
|
|
|
|
|
|
|
|
// --- isTextForEditor ---
|
|
|
|
|
if (!dm.isTextForEditor("/x/a.md") || !dm.isTextForEditor("/x/a.txt")
|
|
|
|
|
|| !dm.isTextForEditor("/x/a.py") || dm.isTextForEditor("/x/a.png")
|
|
|
|
|
|| dm.isTextForEditor("/x/a.pdf"))
|
|
|
|
|
return fail("isTextForEditor");
|
|
|
|
|
|
|
|
|
|
std::printf("DOCUMENT MANAGER TEST OK\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|