128 行
4.1 KiB
C++
128 行
4.1 KiB
C++
#include <catch2/catch_test_macros.hpp>
|
|
|
|
#include "csp/db/sqlite_db.h"
|
|
#include "csp/services/auth_service.h"
|
|
#include "csp/services/kb_service.h"
|
|
#include "csp/services/user_service.h"
|
|
|
|
#include <string>
|
|
#include <unordered_set>
|
|
|
|
TEST_CASE("kb service list/detail") {
|
|
auto db = csp::db::SqliteDb::OpenMemory();
|
|
csp::db::ApplyMigrations(db);
|
|
csp::db::SeedDemoData(db);
|
|
|
|
csp::services::KbService svc(db);
|
|
const auto rows = svc.ListArticles();
|
|
REQUIRE(rows.size() >= 2);
|
|
|
|
const auto detail = svc.GetBySlug(rows.front().slug);
|
|
REQUIRE(detail.has_value());
|
|
REQUIRE(detail->article.slug == rows.front().slug);
|
|
}
|
|
|
|
TEST_CASE("kb skill claim requires prerequisites") {
|
|
auto db = csp::db::SqliteDb::OpenMemory();
|
|
csp::db::ApplyMigrations(db);
|
|
csp::db::SeedDemoData(db);
|
|
|
|
csp::services::AuthService auth(db);
|
|
const auto login = auth.Register("kb_pre_user", "password123");
|
|
|
|
csp::services::KbService svc(db);
|
|
const auto detail = svc.GetBySlug("cpp14-skill-tree");
|
|
REQUIRE(detail.has_value());
|
|
REQUIRE(detail->article.id > 0);
|
|
|
|
bool prerequisite_throw = false;
|
|
try {
|
|
(void)svc.ClaimSkillPoint(login.user_id, detail->article.id, detail->article.slug,
|
|
"cpp14-type-02");
|
|
} catch (const std::runtime_error& e) {
|
|
prerequisite_throw = true;
|
|
REQUIRE(std::string(e.what()).find("prerequisite not completed") != std::string::npos);
|
|
}
|
|
REQUIRE(prerequisite_throw);
|
|
|
|
const auto first =
|
|
svc.ClaimSkillPoint(login.user_id, detail->article.id, detail->article.slug,
|
|
"cpp14-io-01");
|
|
REQUIRE(first.claimed);
|
|
REQUIRE(first.reward == 1);
|
|
|
|
const auto second =
|
|
svc.ClaimSkillPoint(login.user_id, detail->article.id, detail->article.slug,
|
|
"cpp14-type-02");
|
|
REQUIRE(second.claimed);
|
|
REQUIRE(second.reward == 1);
|
|
|
|
const auto second_again =
|
|
svc.ClaimSkillPoint(login.user_id, detail->article.id, detail->article.slug,
|
|
"cpp14-type-02");
|
|
REQUIRE_FALSE(second_again.claimed);
|
|
REQUIRE(second_again.reward == 0);
|
|
}
|
|
|
|
TEST_CASE("kb weekly tasks auto-generate and bonus awarded at 100 percent") {
|
|
auto db = csp::db::SqliteDb::OpenMemory();
|
|
csp::db::ApplyMigrations(db);
|
|
csp::db::SeedDemoData(db);
|
|
|
|
csp::services::AuthService auth(db);
|
|
const auto login = auth.Register("kb_weekly_user", "password123");
|
|
|
|
csp::services::KbService svc(db);
|
|
csp::services::UserService users(db);
|
|
|
|
auto plan = svc.GetWeeklyPlan(login.user_id);
|
|
REQUIRE_FALSE(plan.tasks.empty());
|
|
REQUIRE(plan.tasks.size() <= 8);
|
|
REQUIRE(plan.completion_percent == 0);
|
|
|
|
std::unordered_set<std::string> unlocked;
|
|
for (const auto& task : plan.tasks) {
|
|
for (const auto& pre : task.prerequisites) {
|
|
REQUIRE(unlocked.count(pre) > 0);
|
|
}
|
|
unlocked.insert(task.knowledge_key);
|
|
}
|
|
|
|
bool bonus_throw = false;
|
|
try {
|
|
(void)svc.ClaimWeeklyBonus(login.user_id);
|
|
} catch (const std::runtime_error& e) {
|
|
bonus_throw = true;
|
|
REQUIRE(std::string(e.what()).find("100% completed") != std::string::npos);
|
|
}
|
|
REQUIRE(bonus_throw);
|
|
|
|
int weekly_reward_sum = 0;
|
|
for (const auto& task : plan.tasks) {
|
|
const auto claim = svc.ClaimSkillPoint(login.user_id, task.article_id,
|
|
task.article_slug, task.knowledge_key);
|
|
weekly_reward_sum += claim.reward;
|
|
REQUIRE(claim.claimed);
|
|
}
|
|
|
|
plan = svc.GetWeeklyPlan(login.user_id);
|
|
REQUIRE(plan.completion_percent == 100);
|
|
REQUIRE(plan.gained_reward == plan.total_reward);
|
|
|
|
const auto bonus = svc.ClaimWeeklyBonus(login.user_id);
|
|
REQUIRE(bonus.claimed);
|
|
REQUIRE(bonus.reward == plan.bonus_reward);
|
|
REQUIRE(bonus.completion_percent == 100);
|
|
REQUIRE(bonus.week_key == plan.week_key);
|
|
|
|
const auto user = users.GetById(login.user_id);
|
|
REQUIRE(user.has_value());
|
|
// Register auto-login grants +1 via login check-in task.
|
|
REQUIRE(user->rating == 1 + weekly_reward_sum + plan.bonus_reward);
|
|
|
|
const auto bonus_again = svc.ClaimWeeklyBonus(login.user_id);
|
|
REQUIRE_FALSE(bonus_again.claimed);
|
|
REQUIRE(bonus_again.reward == 0);
|
|
REQUIRE(bonus_again.rating_after == user->rating);
|
|
}
|