Selenium+Specflow单点登录测试:页面跳转后LocalStorage丢失求助
问题描述
我正在用Selenium和Specflow开发冒烟测试的单点登录方案,目前已能从响应中提取Access Token并存入FeatureContext,后续测试时重新写入LocalStorage以跳过登录。但遇到一个问题:页面跳转后LocalStorage会被清空,导致跳转新页面时回到登录页。我不想用每次点击都重设LocalStorage的笨方法,求更优雅的解决方案。
注:测试的网站仅使用token,不依赖cookie,cookie相关方案不适用。
获取Token的代码
string loginToken = ExtractAuthTokenFromResponseBody(); featureContext["auth"] = loginToken;
当前设置LocalStorage的代码
我觉得其中设置请求头的操作可能不正确,但移除后无法正常运行,原因未知:
// 导航到页面 loginPage.Navigate(testConfiguration.URL); // 设置LocalStorage string nameOfLocalStorage = "Hard coded for know until work more cleanly"; string newTokenValue = featureContext["auth"].ToString(); string script = "var newTokenValue = '" + newTokenValue + "';" + "localStorage.setItem('" + nameOfLocalStorage + "', newTokenValue);"; ((IJavaScriptExecutor)webDriver).ExecuteScript(script); // 添加请求头的操作 var client = new HttpClient(); JObject json = JObject.Parse(newTokenValue); string idToken = (string)json["id_token"]; client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", idToken); HttpResponseMessage response = await client.GetAsync(testConfiguration.URL); response.EnsureSuccessStatusCode(); string responseBody = await response.Content.ReadAsStringAsync(); webDriver.Navigate().GoToUrl(testConfiguration.Url);
当前现象:调用GoToUrl能正常进入主页,但点击跳转新页面时LocalStorage为空,被迫回到登录页。
解决方案
1. 修正LocalStorage键名
你当前硬编码的nameOfLocalStorage大概率和前端实际读取的键名不匹配,导致前端无法识别token,进而触发重新登录。先排查前端代码(或通过浏览器开发者工具查看),找到实际存储token的键名,替换硬编码值。
2. 移除冗余的HttpClient请求
你用HttpClient发起的请求是独立于Selenium浏览器会话的,这部分操作对浏览器的LocalStorage和会话状态没有任何帮助,反而可能造成状态不一致。移除这部分代码,调整LocalStorage设置逻辑:
// 导航到目标页面 loginPage.Navigate(testConfiguration.URL); // 等待页面完全加载 WebDriverWait wait = new WebDriverWait(webDriver, TimeSpan.FromSeconds(10)); wait.Until(d => ((IJavaScriptExecutor)d).ExecuteScript("return document.readyState").ToString() == "complete"); // 设置LocalStorage(替换为实际键名) string tokenKey = "auth_token"; // 示例键名,替换为实际值 string newTokenValue = featureContext["auth"].ToString(); string script = $"localStorage.setItem('{tokenKey}', '{newTokenValue}');"; ((IJavaScriptExecutor)webDriver).ExecuteScript(script); // 刷新页面,让前端读取LocalStorage中的token webDriver.Navigate().Refresh();
3. 使用DevTools API持久化LocalStorage(推荐)
对于Chrome/Edge等现代浏览器,利用Selenium的DevTools API直接操作浏览器存储,比JavaScript执行更可靠,且能确保同域名下页面跳转时LocalStorage不丢失:
// 初始化DevTools会话 var devTools = webDriver as IDevTools; var session = devTools.CreateDevToolsSession(); // 启用Storage模块 await session.SendCommandAsync(new StorageEnableCommandSettings()); // 设置LocalStorage项 await session.SendCommandAsync(new StorageSetLocalStorageItemCommandSettings { Key = "实际的token键名", Value = featureContext["auth"].ToString(), Origin = testConfiguration.URL // 目标页面的域名,确保同源 }); // 导航到页面,此时LocalStorage已提前配置完成 webDriver.Navigate().GoToUrl(testConfiguration.URL);
4. 检查页面跳转的同源性
如果跳转的页面属于不同域名,浏览器同源策略会阻止LocalStorage共享。这种情况下:
- 确认所有测试页面是否属于同一主域名,若跨域则需前端配置token跨域共享(不属于测试代码调整范围)
- 若必须跨域测试,可针对每个域名单独执行一次LocalStorage设置逻辑(但比点击重设更高效,可封装成公共方法)
内容的提问来源于stack exchange,提问作者oisin1min

