// net 层端到端登录连通测试(真实站点)。 // 复刻已实测通过的流程:getImageCode -> verifyCodeCheck -> RSA -> login2, // 关键在 ApiClient 内单一 QNetworkAccessManager 共享 JSESSIONID 会话。 // 异步化:fetchCaptchaAsync/loginAsync 返回自管理句柄,QSignalSpy::wait 驱动事件循环等待。 // 需要 QCoreApplication 提供事件循环。网络不可达时本用例会失败(属环境问题,非逻辑问题)。 #include #include #include #include #include #include #include "ApiClient.hpp" #include "AuthLoads.hpp" #include "AuthService.hpp" namespace { // 读取整个文件内容(PEM 公钥)。 std::string slurp(const char* path) { std::ifstream f(path); std::stringstream s; s << f.rdbuf(); return s.str(); } } // namespace TEST(AuthLiveTest, FullLoginFlowReturnsToken) { int argc = 0; char** argv = nullptr; QCoreApplication app(argc, argv); geopro::net::ApiClient api("http://tenant.geomative.cn/pop-api"); geopro::net::AuthService auth( api, slurp("D:/Git/lanbingtech/geopro/resources/rsa_public_key.pem")); auto* cl = auth.fetchCaptchaAsync(); QSignalSpy capDone(cl, &geopro::net::CaptchaLoad::done); QSignalSpy capFail(cl, &geopro::net::CaptchaLoad::failed); ASSERT_TRUE(capDone.wait(10000) || capFail.count() > 0); ASSERT_EQ(capDone.count(), 1) << (capFail.count() ? capFail.takeFirst().at(0).toString().toStdString() : "captcha failed"); auto cap = capDone.takeFirst().at(0).value(); ASSERT_FALSE(cap.codeId.isEmpty()); ASSERT_FALSE(cap.code.isEmpty()); auto* ll = auth.loginAsync("sydk", "123456", cap.code, cap.codeId); QSignalSpy loginDone(ll, &geopro::net::LoginLoad::done); QSignalSpy loginFail(ll, &geopro::net::LoginLoad::failed); ASSERT_TRUE(loginDone.wait(10000) || loginFail.count() > 0); EXPECT_EQ(loginDone.count(), 1) << (loginFail.count() ? loginFail.takeFirst().at(0).toString().toStdString() : ""); if (loginDone.count()) { auto token = loginDone.takeFirst().at(0).toString(); EXPECT_TRUE(token.startsWith("Geomative ")) << token.toStdString(); } }