清理废弃模块并完善测试基础设施
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
#include "TestHarness.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QStandardPaths>
|
||||
#include <QTextStream>
|
||||
|
||||
#include <exception>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QStandardPaths::setTestModeEnabled(true);
|
||||
QCoreApplication application(argc, argv);
|
||||
QCoreApplication::setOrganizationName(QStringLiteral("QtDesktopPetInternalQA"));
|
||||
QCoreApplication::setApplicationName(QStringLiteral("CoreLogicTests"));
|
||||
|
||||
QTextStream output(stdout);
|
||||
QTextStream errors(stderr);
|
||||
int failedCount = 0;
|
||||
|
||||
for (const Qa::TestCase &test : Qa::registry())
|
||||
{
|
||||
try
|
||||
{
|
||||
test.function();
|
||||
output << "[PASS] " << QString::fromStdString(test.name) << Qt::endl;
|
||||
}
|
||||
catch (const std::exception &exception)
|
||||
{
|
||||
++failedCount;
|
||||
errors << "[FAIL] " << QString::fromStdString(test.name)
|
||||
<< ": " << exception.what() << Qt::endl;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
++failedCount;
|
||||
errors << "[FAIL] " << QString::fromStdString(test.name)
|
||||
<< ": unknown exception" << Qt::endl;
|
||||
}
|
||||
}
|
||||
|
||||
output << "Executed " << Qa::registry().size() << " tests; "
|
||||
<< failedCount << " failed." << Qt::endl;
|
||||
return failedCount == 0 ? 0 : 1;
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
#include "TestHarness.h"
|
||||
|
||||
#include "src/ai/ConversationStore.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QDate>
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QTemporaryDir>
|
||||
#include <QTime>
|
||||
|
||||
namespace
|
||||
{
|
||||
ChatMessage message(const QString &role, const QString &content, int minute)
|
||||
{
|
||||
return {
|
||||
role,
|
||||
content,
|
||||
QDateTime(QDate(2026, 7, 17), QTime(10, minute)),
|
||||
QStringLiteral("openai"),
|
||||
QStringLiteral("test-model"),
|
||||
};
|
||||
}
|
||||
|
||||
bool writeBytes(const QString &filePath, const QByteArray &bytes)
|
||||
{
|
||||
QFile file(filePath);
|
||||
return file.open(QIODevice::WriteOnly | QIODevice::Truncate)
|
||||
&& file.write(bytes) == bytes.size();
|
||||
}
|
||||
}
|
||||
|
||||
QA_TEST(ConversationStore, SavesLoadsAndLimitsEvenHistory)
|
||||
{
|
||||
QTemporaryDir directory;
|
||||
QA_EXPECT(directory.isValid());
|
||||
const QString filePath = directory.filePath(QStringLiteral("conversation_history.json"));
|
||||
const ConversationStore store(filePath);
|
||||
const QVector<ChatMessage> messages = {
|
||||
message(QStringLiteral("user"), QStringLiteral("one"), 0),
|
||||
message(QStringLiteral("assistant"), QStringLiteral("two"), 1),
|
||||
message(QStringLiteral("user"), QStringLiteral("three"), 2),
|
||||
message(QStringLiteral("assistant"), QStringLiteral("four"), 3),
|
||||
};
|
||||
|
||||
QA_EXPECT(store.save(messages, 4));
|
||||
const QVector<ChatMessage> loaded = store.load(3);
|
||||
QA_EXPECT_EQ(loaded.size(), 2);
|
||||
QA_EXPECT_EQ(loaded.first().content, QStringLiteral("three"));
|
||||
QA_EXPECT_EQ(loaded.last().model, QStringLiteral("test-model"));
|
||||
}
|
||||
|
||||
QA_TEST(ConversationStore, AvoidsDuplicatingOverlappingMessages)
|
||||
{
|
||||
QTemporaryDir directory;
|
||||
QA_EXPECT(directory.isValid());
|
||||
const ConversationStore store(directory.filePath(QStringLiteral("history.json")));
|
||||
const QVector<ChatMessage> firstPair = {
|
||||
message(QStringLiteral("user"), QStringLiteral("hello"), 0),
|
||||
message(QStringLiteral("assistant"), QStringLiteral("world"), 1),
|
||||
};
|
||||
|
||||
QA_EXPECT(store.save(firstPair, 10));
|
||||
QA_EXPECT(store.save(firstPair, 10));
|
||||
QA_EXPECT_EQ(store.load(10).size(), 2);
|
||||
}
|
||||
|
||||
QA_TEST(ConversationStore, LoadsLegacyCreatedAtField)
|
||||
{
|
||||
QTemporaryDir directory;
|
||||
QA_EXPECT(directory.isValid());
|
||||
const QString filePath = directory.filePath(QStringLiteral("legacy.json"));
|
||||
QJsonArray messages;
|
||||
messages.append(QJsonObject{
|
||||
{QStringLiteral("role"), QStringLiteral("user")},
|
||||
{QStringLiteral("content"), QStringLiteral("legacy-user")},
|
||||
{QStringLiteral("createdAt"), QStringLiteral("2026-07-17T10:00:00")},
|
||||
});
|
||||
messages.append(QJsonObject{
|
||||
{QStringLiteral("role"), QStringLiteral("assistant")},
|
||||
{QStringLiteral("content"), QStringLiteral("legacy-assistant")},
|
||||
{QStringLiteral("createdAt"), QStringLiteral("2026-07-17T10:00:01")},
|
||||
});
|
||||
QA_EXPECT(writeBytes(filePath, QJsonDocument(QJsonObject{{QStringLiteral("messages"), messages}}).toJson()));
|
||||
|
||||
const QVector<ChatMessage> loaded = ConversationStore(filePath).load(10);
|
||||
QA_EXPECT_EQ(loaded.size(), 2);
|
||||
QA_EXPECT(loaded.first().timestamp.isValid());
|
||||
QA_EXPECT(loaded.first().provider.isEmpty());
|
||||
}
|
||||
|
||||
QA_TEST(ConversationStore, BacksUpBrokenJsonAndClearsHistory)
|
||||
{
|
||||
QTemporaryDir directory;
|
||||
QA_EXPECT(directory.isValid());
|
||||
const QString filePath = directory.filePath(QStringLiteral("conversation_history.json"));
|
||||
QA_EXPECT(writeBytes(filePath, QByteArrayLiteral("{broken")));
|
||||
|
||||
QString errorMessage;
|
||||
const ConversationStore store(filePath);
|
||||
QA_EXPECT(store.load(10, &errorMessage).isEmpty());
|
||||
QA_EXPECT(!errorMessage.isEmpty());
|
||||
QA_EXPECT(!QFile::exists(filePath));
|
||||
QA_EXPECT_EQ(
|
||||
QDir(directory.path()).entryList({QStringLiteral("conversation_history.broken.*.json")}, QDir::Files).size(),
|
||||
1);
|
||||
|
||||
QA_EXPECT(store.save({
|
||||
message(QStringLiteral("user"), QStringLiteral("hello"), 0),
|
||||
message(QStringLiteral("assistant"), QStringLiteral("world"), 1),
|
||||
}, 10));
|
||||
QA_EXPECT(store.clear());
|
||||
QA_EXPECT(!QFile::exists(filePath));
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "TestHarness.h"
|
||||
|
||||
#include "src/assistant/CommandDispatcher.h"
|
||||
#include "src/assistant/IntentRouter.h"
|
||||
|
||||
QA_TEST(IntentRouting, TrimsChatText)
|
||||
{
|
||||
const UserIntent intent = IntentRouter().route(QStringLiteral(" 你好 "));
|
||||
QA_EXPECT_EQ(intent.type, UserIntentType::Chat);
|
||||
QA_EXPECT_EQ(intent.text, QStringLiteral("你好"));
|
||||
}
|
||||
|
||||
QA_TEST(IntentRouting, ReminderHasPriorityOverWeather)
|
||||
{
|
||||
const UserIntent intent = IntentRouter().route(QStringLiteral("明天提醒我看天气"));
|
||||
QA_EXPECT_EQ(intent.type, UserIntentType::Reminder);
|
||||
}
|
||||
|
||||
QA_TEST(IntentRouting, RecognizesWeatherExpressions)
|
||||
{
|
||||
const IntentRouter router;
|
||||
QA_EXPECT_EQ(router.route(QStringLiteral("西安天气怎么样")).type, UserIntentType::Weather);
|
||||
QA_EXPECT_EQ(router.route(QStringLiteral("明天会不会下雨")).type, UserIntentType::Weather);
|
||||
QA_EXPECT_EQ(router.route(QStringLiteral("外面冷不冷")).type, UserIntentType::Weather);
|
||||
}
|
||||
|
||||
QA_TEST(IntentRouting, RemovedLocalCapabilitiesRemainChat)
|
||||
{
|
||||
const IntentRouter router;
|
||||
QA_EXPECT_EQ(router.route(QStringLiteral("读取文件")).type, UserIntentType::Chat);
|
||||
QA_EXPECT_EQ(router.route(QStringLiteral("打开 Codex")).type, UserIntentType::Chat);
|
||||
QA_EXPECT_EQ(router.route(QStringLiteral("分析这个项目")).type, UserIntentType::Chat);
|
||||
QA_EXPECT_EQ(router.route(QStringLiteral("创建 test.txt")).type, UserIntentType::Chat);
|
||||
}
|
||||
|
||||
QA_TEST(IntentRouting, DispatcherMapsSupportedActions)
|
||||
{
|
||||
const CommandDispatcher dispatcher;
|
||||
QA_EXPECT_EQ(dispatcher.dispatch(QStringLiteral("提醒我休息")).action, CommandDispatchAction::Reminder);
|
||||
QA_EXPECT_EQ(dispatcher.dispatch(QStringLiteral("北京天气")).action, CommandDispatchAction::Weather);
|
||||
QA_EXPECT_EQ(dispatcher.dispatch(QStringLiteral("讲个笑话")).action, CommandDispatchAction::Chat);
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
#include "TestHarness.h"
|
||||
|
||||
#include "src/reminder/ReminderParser.h"
|
||||
#include "src/reminder/ReminderTypes.h"
|
||||
|
||||
#include <QDate>
|
||||
#include <QDateTime>
|
||||
#include <QStringList>
|
||||
#include <QTime>
|
||||
|
||||
namespace
|
||||
{
|
||||
QDateTime fixedNow()
|
||||
{
|
||||
return QDateTime(QDate(2026, 7, 17), QTime(14, 0));
|
||||
}
|
||||
}
|
||||
|
||||
QA_TEST(ReminderParser, ParsesRelativeMinutes)
|
||||
{
|
||||
const ReminderCommand command = ReminderParser().parse(QStringLiteral("10分钟后提醒我喝水"), fixedNow());
|
||||
QA_EXPECT_EQ(command.type, ReminderCommandType::Create);
|
||||
QA_EXPECT_EQ(command.remindAt, fixedNow().addSecs(10 * 60));
|
||||
QA_EXPECT_EQ(command.title, QStringLiteral("喝水"));
|
||||
}
|
||||
|
||||
QA_TEST(ReminderParser, ParsesHalfHours)
|
||||
{
|
||||
const ReminderParser parser;
|
||||
QA_EXPECT_EQ(
|
||||
parser.parse(QStringLiteral("半小时后提醒我休息"), fixedNow()).remindAt,
|
||||
fixedNow().addSecs(30 * 60));
|
||||
QA_EXPECT_EQ(
|
||||
parser.parse(QStringLiteral("一个半小时后提醒我喝水"), fixedNow()).remindAt,
|
||||
fixedNow().addSecs(90 * 60));
|
||||
}
|
||||
|
||||
QA_TEST(ReminderParser, ParsesTomorrowClockTime)
|
||||
{
|
||||
const ReminderCommand command = ReminderParser().parse(QStringLiteral("明天9点提醒我开会"), fixedNow());
|
||||
QA_EXPECT_EQ(command.type, ReminderCommandType::Create);
|
||||
QA_EXPECT_EQ(command.remindAt, QDateTime(QDate(2026, 7, 18), QTime(9, 0)));
|
||||
}
|
||||
|
||||
QA_TEST(ReminderParser, ParsesSupportedRecurrence)
|
||||
{
|
||||
const ReminderParser parser;
|
||||
const ReminderCommand daily = parser.parse(QStringLiteral("每天9点提醒我打卡"), fixedNow());
|
||||
const ReminderCommand weekly = parser.parse(QStringLiteral("每周一上午10点提醒我周会"), fixedNow());
|
||||
const ReminderCommand monthly = parser.parse(QStringLiteral("每月31号9点提醒我交报告"), fixedNow());
|
||||
|
||||
QA_EXPECT_EQ(daily.recurrence.type, ReminderRecurrenceType::Daily);
|
||||
QA_EXPECT_EQ(daily.remindAt, QDateTime(QDate(2026, 7, 18), QTime(9, 0)));
|
||||
QA_EXPECT_EQ(weekly.recurrence.type, ReminderRecurrenceType::Weekly);
|
||||
QA_EXPECT_EQ(weekly.recurrence.weekday, 1);
|
||||
QA_EXPECT_EQ(monthly.recurrence.type, ReminderRecurrenceType::Monthly);
|
||||
QA_EXPECT_EQ(monthly.recurrence.monthDay, 31);
|
||||
QA_EXPECT_EQ(monthly.remindAt, QDateTime(QDate(2026, 7, 31), QTime(9, 0)));
|
||||
}
|
||||
|
||||
QA_TEST(ReminderParser, RejectsUnsupportedRecurrence)
|
||||
{
|
||||
const ReminderParser parser;
|
||||
const QStringList requests = {
|
||||
QStringLiteral("工作日9点提醒我打卡"),
|
||||
QStringLiteral("每两天提醒我喝水"),
|
||||
QStringLiteral("农历初一提醒我"),
|
||||
QStringLiteral("每月最后一天9点提醒我结算"),
|
||||
};
|
||||
|
||||
for (const QString &request : requests)
|
||||
{
|
||||
const ReminderCommand command = parser.parse(request, fixedNow());
|
||||
QA_EXPECT_EQ(command.type, ReminderCommandType::Invalid);
|
||||
QA_EXPECT(!command.errorMessage.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
QA_TEST(ReminderParser, ParsesListAndCancelCommands)
|
||||
{
|
||||
const ReminderParser parser;
|
||||
QA_EXPECT_EQ(parser.parse(QStringLiteral("提醒列表"), fixedNow()).type, ReminderCommandType::List);
|
||||
|
||||
const ReminderCommand cancel = parser.parse(QStringLiteral("取消喝水提醒"), fixedNow());
|
||||
QA_EXPECT_EQ(cancel.type, ReminderCommandType::Cancel);
|
||||
QA_EXPECT_EQ(cancel.cancelQuery, QStringLiteral("喝水"));
|
||||
}
|
||||
|
||||
QA_TEST(ReminderTypes, ConvertsAndSortsValues)
|
||||
{
|
||||
QA_EXPECT_EQ(reminderStatusFromString(QStringLiteral("TRIGGERED")), ReminderStatus::Triggered);
|
||||
QA_EXPECT_EQ(reminderRecurrenceTypeFromString(QStringLiteral("weekly")), ReminderRecurrenceType::Weekly);
|
||||
QA_EXPECT_EQ(reminderRecurrenceTypeToString(ReminderRecurrenceType::Monthly), QStringLiteral("monthly"));
|
||||
|
||||
ReminderItem later;
|
||||
later.id = QStringLiteral("later");
|
||||
later.remindAt = fixedNow().addSecs(60);
|
||||
ReminderItem earlier;
|
||||
earlier.id = QStringLiteral("earlier");
|
||||
earlier.remindAt = fixedNow();
|
||||
|
||||
const QVector<ReminderItem> sorted = sortedReminders({later, earlier});
|
||||
QA_EXPECT_EQ(sorted.first().id, QStringLiteral("earlier"));
|
||||
QA_EXPECT_EQ(sorted.last().id, QStringLiteral("later"));
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
#include "TestHarness.h"
|
||||
|
||||
#include "src/weather/WeatherParser.h"
|
||||
#include "src/weather/WeatherSummaryFormatter.h"
|
||||
|
||||
QA_TEST(WeatherParser, ExtractsExplicitCitiesAndDates)
|
||||
{
|
||||
const WeatherParser parser;
|
||||
const WeatherQuery current = parser.parse(QStringLiteral("西安天气怎么样"));
|
||||
const WeatherQuery tomorrow = parser.parse(QStringLiteral("明天西安天气怎么样"));
|
||||
const WeatherQuery afterTomorrow = parser.parse(QStringLiteral("后天纽约天气"));
|
||||
|
||||
QA_EXPECT_EQ(current.cityName, QStringLiteral("西安"));
|
||||
QA_EXPECT_EQ(current.kind, WeatherQueryKind::Current);
|
||||
QA_EXPECT_EQ(tomorrow.cityName, QStringLiteral("西安"));
|
||||
QA_EXPECT_EQ(tomorrow.dateOffset, 1);
|
||||
QA_EXPECT_EQ(afterTomorrow.cityName, QStringLiteral("纽约"));
|
||||
QA_EXPECT_EQ(afterTomorrow.dateOffset, 2);
|
||||
}
|
||||
|
||||
QA_TEST(WeatherParser, ParsesRangeAndDefaultCityRequest)
|
||||
{
|
||||
const WeatherParser parser;
|
||||
const WeatherQuery range = parser.parse(QStringLiteral("未来三天北京天气"));
|
||||
const WeatherQuery defaultCity = parser.parse(QStringLiteral("今天天气怎么样"));
|
||||
|
||||
QA_EXPECT_EQ(range.kind, WeatherQueryKind::Range);
|
||||
QA_EXPECT_EQ(range.forecastDays, 3);
|
||||
QA_EXPECT_EQ(range.cityName, QStringLiteral("北京"));
|
||||
QA_EXPECT(defaultCity.cityName.isEmpty());
|
||||
}
|
||||
|
||||
QA_TEST(WeatherParser, RejectsUnsupportedQueries)
|
||||
{
|
||||
const WeatherParser parser;
|
||||
QA_EXPECT(!parser.parse(QStringLiteral("西安空气质量")).unsupportedReason.isEmpty());
|
||||
QA_EXPECT(!parser.parse(QStringLiteral("北京天气预警")).unsupportedReason.isEmpty());
|
||||
QA_EXPECT(!parser.parse(QStringLiteral("明天穿什么")).unsupportedReason.isEmpty());
|
||||
}
|
||||
|
||||
QA_TEST(WeatherFormatter, MapsWeatherCodesAndWindDirections)
|
||||
{
|
||||
QA_EXPECT_EQ(WeatherSummaryFormatter::weatherCodeText(0), QStringLiteral("晴"));
|
||||
QA_EXPECT_EQ(WeatherSummaryFormatter::weatherCodeText(95), QStringLiteral("雷暴"));
|
||||
QA_EXPECT_EQ(WeatherSummaryFormatter::weatherCodeText(-1), QStringLiteral("未知天气"));
|
||||
QA_EXPECT_EQ(WeatherSummaryFormatter::windDirectionText(0), QStringLiteral("北风"));
|
||||
QA_EXPECT_EQ(WeatherSummaryFormatter::windDirectionText(90), QStringLiteral("东风"));
|
||||
QA_EXPECT_EQ(WeatherSummaryFormatter::windDirectionText(225), QStringLiteral("西南风"));
|
||||
}
|
||||
|
||||
QA_TEST(WeatherFormatter, FormatsCurrentWeatherWithSource)
|
||||
{
|
||||
WeatherReport report;
|
||||
report.query.kind = WeatherQueryKind::Current;
|
||||
report.location.cityName = QStringLiteral("西安");
|
||||
report.location.countryName = QStringLiteral("中国");
|
||||
report.location.source = WeatherLocationSource::SettingsDefault;
|
||||
report.current.valid = true;
|
||||
report.current.weatherCode = 0;
|
||||
report.current.hasTemperature = true;
|
||||
report.current.temperatureC = 28.5;
|
||||
|
||||
const QString message = WeatherSummaryFormatter().format(report);
|
||||
QA_EXPECT(message.contains(QStringLiteral("使用设置页默认城市")));
|
||||
QA_EXPECT(message.contains(QStringLiteral("西安,中国当前天气:晴")));
|
||||
QA_EXPECT(message.contains(QStringLiteral("28.5℃")));
|
||||
}
|
||||
|
||||
QA_TEST(WeatherFormatter, FormatsAmbiguousLocationAndMissingData)
|
||||
{
|
||||
WeatherReport report;
|
||||
report.query.kind = WeatherQueryKind::Current;
|
||||
report.location.cityName = QStringLiteral("Springfield");
|
||||
report.location.countryName = QStringLiteral("United States");
|
||||
report.hasLocationAmbiguity = true;
|
||||
report.locationCandidates = {
|
||||
{QStringLiteral("Springfield"), QStringLiteral("Illinois"), QStringLiteral("United States"), {}, 0.0, 0.0},
|
||||
{QStringLiteral("Springfield"), QStringLiteral("Missouri"), QStringLiteral("United States"), {}, 0.0, 0.0},
|
||||
};
|
||||
|
||||
const QString message = WeatherSummaryFormatter().format(report);
|
||||
QA_EXPECT(message.contains(QStringLiteral("可能存在同名城市")));
|
||||
QA_EXPECT(message.contains(QStringLiteral("Missouri")));
|
||||
QA_EXPECT(message.contains(QStringLiteral("缺少当前天气")));
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#include "TestHarness.h"
|
||||
|
||||
#include "src/config/AIConfig.h"
|
||||
#include "src/web/WebCapabilityDetector.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
AIConfig completeConfig(const QString &provider)
|
||||
{
|
||||
AIConfig config = defaultAIConfigForProvider(provider);
|
||||
config.model = QStringLiteral("test-model");
|
||||
config.apiKey = QStringLiteral("test-key-not-a-real-secret");
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
QA_TEST(WebCapability, RespectsGlobalDisable)
|
||||
{
|
||||
WebConfig webConfig;
|
||||
webConfig.enabled = false;
|
||||
const WebCapability capability = WebCapabilityDetector::detect(completeConfig(QStringLiteral("openai")), webConfig);
|
||||
QA_EXPECT(!capability.supported);
|
||||
QA_EXPECT(capability.statusText.contains(QStringLiteral("已关闭")));
|
||||
}
|
||||
|
||||
QA_TEST(WebCapability, AcceptsOfficialOpenAI)
|
||||
{
|
||||
const WebCapability capability = WebCapabilityDetector::detect(completeConfig(QStringLiteral("openai")));
|
||||
QA_EXPECT(capability.supported);
|
||||
QA_EXPECT_EQ(capability.kind, WebProviderKind::OpenAIResponses);
|
||||
}
|
||||
|
||||
QA_TEST(WebCapability, RejectsThirdPartyOpenAIBaseUrl)
|
||||
{
|
||||
AIConfig config = completeConfig(QStringLiteral("openai"));
|
||||
config.baseUrl = QStringLiteral("https://relay.example.com/v1");
|
||||
const WebCapability capability = WebCapabilityDetector::detect(config);
|
||||
QA_EXPECT(!capability.supported);
|
||||
QA_EXPECT(capability.userMessage.contains(QStringLiteral("api.openai.com")));
|
||||
}
|
||||
|
||||
QA_TEST(WebCapability, AcceptsGeminiProtocol)
|
||||
{
|
||||
const WebCapability capability = WebCapabilityDetector::detect(completeConfig(QStringLiteral("google")));
|
||||
QA_EXPECT(capability.supported);
|
||||
QA_EXPECT_EQ(capability.kind, WebProviderKind::GeminiGrounding);
|
||||
}
|
||||
|
||||
QA_TEST(WebCapability, RejectsDeepSeekAndCustomProviders)
|
||||
{
|
||||
const WebCapability deepSeek = WebCapabilityDetector::detect(completeConfig(QStringLiteral("deepseek")));
|
||||
const WebCapability custom = WebCapabilityDetector::detect(completeConfig(QStringLiteral("custom")));
|
||||
QA_EXPECT(!deepSeek.supported);
|
||||
QA_EXPECT(deepSeek.statusText.contains(QStringLiteral("DeepSeek")));
|
||||
QA_EXPECT(!custom.supported);
|
||||
QA_EXPECT(custom.statusText.contains(QStringLiteral("无法确认")));
|
||||
}
|
||||
|
||||
QA_TEST(WebCapability, RequiresCompleteConfiguration)
|
||||
{
|
||||
AIConfig config = defaultAIConfigForProvider(QStringLiteral("openai"));
|
||||
const WebCapability capability = WebCapabilityDetector::detect(config);
|
||||
QA_EXPECT(!capability.supported);
|
||||
QA_EXPECT(capability.statusText.contains(QStringLiteral("未配置完整")));
|
||||
}
|
||||
Reference in New Issue
Block a user