The browser fixture opens phones from Playwright's own device presets (360x800, iPhone SE 375x667, Pixel 7 412x839, and the Pixel 7 held sideways), with touch, a coarse pointer and reduced motion, and a phone session fails at once if the page doesn't see a touch screen. Mobile/fit.js measures a page one screen at a time down its main scroller: sideways scroll, boxes past the screen's sides, open menus and dialogs cut or outside the screen, targets without a 44px hit area (hit-tested at their centre and 21px around it, so a crowding neighbour fails them too) and control text under 12px. RouteSweepTests runs every feed tab, threads of each kind the town holds, profiles, search, Explore, lists, groups, filters, scheduled posts, settings and administration (every section opened) and the login page on the three portrait phones, as client.mobile.fit.* and client.mobile.touch.* cells; screenshots, findings and a contact sheet go to tests/e2e/out/mobile/. DesktopUnchangedTests holds desktop's control sizes. Category=Mobile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
55 lines
1.7 KiB
C#
55 lines
1.7 KiB
C#
using decePubClient.E2E.Support;
|
|
|
|
namespace decePubClient.E2E.Mobile
|
|
{
|
|
// Every page at every portrait phone: nothing scrolls sideways or lies past the screen, every open menu and dialog is
|
|
// whole, every target has a 44px hit area and no control's text is under 12px. Two cells per page and phone,
|
|
// client.mobile.fit.* and client.mobile.touch.*; the screenshots and findings go to tests/e2e/out/mobile/.
|
|
[Trait("Category", "Mobile")]
|
|
public sealed class RouteSweepTests(Browser browser)
|
|
{
|
|
public static TheoryData<string, string> Cases()
|
|
{
|
|
var data = new TheoryData<string, string>();
|
|
foreach (var phone in Phone.Portrait)
|
|
foreach (var route in Route.All)
|
|
data.Add(phone.Key, route.Slug);
|
|
return data;
|
|
}
|
|
|
|
[Theory]
|
|
[MemberData(nameof(Cases))]
|
|
public async Task Fits_a_phone(string phoneKey, string slug)
|
|
{
|
|
var phone = Phone.ByKey(phoneKey);
|
|
var route = Route.Get(slug);
|
|
var persona = route.Persona();
|
|
await using var session = route.SignedOut ? await browser.Open(phone: phone) : await SignIn.As(browser, persona, phone);
|
|
await route.Open(session.Page, persona);
|
|
var report = await Fit.Sweep(session.Page, phone, slug, route.Screens);
|
|
if (!route.Gating)
|
|
return;
|
|
|
|
var problems = new List<string>();
|
|
foreach (var (feature, check) in new (string, Action<Fit.Report>)[]
|
|
{
|
|
($"client.mobile.fit.{slug}", Fit.AssertFits), ($"client.mobile.touch.{slug}", Fit.AssertTouchable)
|
|
})
|
|
try
|
|
{
|
|
await Results.Cell(feature, "privapub", phone.Key, () =>
|
|
{
|
|
check(report);
|
|
return Task.CompletedTask;
|
|
});
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
problems.Add(e.Message);
|
|
}
|
|
await session.AssertGuards();
|
|
Assert.True(problems.Count == 0, string.Join("\n\n", problems));
|
|
}
|
|
}
|
|
}
|