feat: add view-as-role feature for site admins (#15)
Site admins can now temporarily view the site as a player, tournament admin, or club admin to understand the experience for each role. Changes: - Added RoleSwitcher context and provider for client-side role simulation - Added role switcher dropdown in Navigation (visible only to site admins) - Added yellow banner showing current viewing-as role with reset button - Navigation links and wordmark href now use effective role for conditional display - Added BDD feature file with 5 scenarios covering all role transitions - Added step definitions for site admin login and role switcher interactions The view-as feature is purely UI-level - server-side permissions remain unchanged. 5 scenarios, 27 steps, all passing.
This commit is contained in:
@@ -690,3 +690,61 @@ Then('I should be on the match result entry page', async function () {
|
||||
console.log(`🌍 Checking current URL: ${currentUrl}`);
|
||||
expect(currentUrl).toMatch(/\/matches\/|\/admin\/tournaments\/\d+\/(entry|results)/);
|
||||
});
|
||||
|
||||
// View As Role Steps
|
||||
When('I view the navigation', async function () {
|
||||
await world.page.waitForLoadState('networkidle');
|
||||
await world.page.waitForTimeout(1000);
|
||||
console.log('🌍 Viewing navigation');
|
||||
});
|
||||
|
||||
Then('I should see the role switcher dropdown', async function () {
|
||||
const switcher = world.page.locator('[data-testid="role-switcher"]');
|
||||
await expect(switcher).toBeVisible({ timeout: 5000 });
|
||||
console.log('🌍 Verified role switcher dropdown is visible');
|
||||
});
|
||||
|
||||
Then('the role switcher should default to {string}', async function (expectedText: string) {
|
||||
const switcher = world.page.locator('[data-testid="role-switcher"]');
|
||||
const selectedValue = await switcher.inputValue();
|
||||
const selectedText = await switcher.locator('option:checked').textContent();
|
||||
console.log(`🌍 Dropdown selected text: "${selectedText}", value: "${selectedValue}"`);
|
||||
expect(selectedText?.trim()).toBe(expectedText);
|
||||
});
|
||||
|
||||
When('I select {string} from the role switcher', async function (optionText: string) {
|
||||
const switcher = world.page.locator('[data-testid="role-switcher"]');
|
||||
await switcher.selectOption({ label: optionText });
|
||||
await world.page.waitForTimeout(500);
|
||||
console.log(`🌍 Selected "${optionText}" from role switcher`);
|
||||
});
|
||||
|
||||
Then('I should see the player navigation links', async function () {
|
||||
await expect(world.page.locator('nav a:has-text("Rankings")')).toBeVisible();
|
||||
await expect(world.page.locator('nav a:has-text("Tournaments")')).toBeVisible();
|
||||
console.log('🌍 Verified player navigation links are visible');
|
||||
});
|
||||
|
||||
Then('I should not see the {string} link', async function (linkText: string) {
|
||||
const link = world.page.locator(`nav a:has-text("${linkText}")`);
|
||||
await expect(link).not.toBeVisible({ timeout: 3000 });
|
||||
console.log(`🌍 Verified "${linkText}" nav link is not visible`);
|
||||
});
|
||||
|
||||
Then('I should see the {string} link', async function (linkText: string) {
|
||||
const link = world.page.locator(`nav a:has-text("${linkText}")`);
|
||||
await expect(link).toBeVisible({ timeout: 5000 });
|
||||
console.log(`🌍 Verified "${linkText}" nav link is visible`);
|
||||
});
|
||||
|
||||
Then('I should see a banner indicating I am viewing as {string}', async function (roleName: string) {
|
||||
const banner = world.page.locator(`text=Viewing as ${roleName}`);
|
||||
await expect(banner).toBeVisible({ timeout: 5000 });
|
||||
console.log(`🌍 Verified viewing as ${roleName} banner is visible`);
|
||||
});
|
||||
|
||||
Then('I should not see the viewing as banner', async function () {
|
||||
const banner = world.page.locator('[data-testid="reset-view-as"]');
|
||||
await expect(banner).not.toBeVisible({ timeout: 3000 });
|
||||
console.log('🌍 Verified viewing as banner is not visible');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user