Skip to content

Commit baa74ed

Browse files
committed
Playright
1 parent 6431561 commit baa74ed

25 files changed

+2143
-0
lines changed
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
using Microsoft.Playwright;
2+
using Microsoft.Playwright.NUnit;
3+
using NUnit.Framework;
4+
using System.Text.RegularExpressions;
5+
6+
namespace TextHub.Tests;
7+
8+
[TestFixture]
9+
public class AccessibilityAndPerformanceTests : PageTest
10+
{
11+
private string BaseUrl => GlobalSetup.GetBaseUrl();
12+
13+
[SetUp]
14+
public async Task SetUp()
15+
{
16+
await Page.GotoAsync(BaseUrl);
17+
await Page.WaitForLoadStateAsync(LoadState.NetworkIdle);
18+
}
19+
20+
[Test]
21+
public async Task Page_ShouldHaveProperHeadingStructure()
22+
{
23+
// Check for proper heading hierarchy
24+
var h1 = Page.Locator("h1");
25+
var h1Count = await h1.CountAsync();
26+
Assert.That(h1Count, Is.EqualTo(1), "Page should have exactly one H1 heading");
27+
28+
// Verify H1 is visible
29+
await Expect(h1.First).ToBeVisibleAsync();
30+
}
31+
32+
[Test]
33+
public async Task Page_ShouldHaveSkipNavigation()
34+
{
35+
// Check for skip navigation link
36+
var skipNav = Page.Locator("a[href='#main-content']");
37+
await Expect(skipNav).ToBeVisibleAsync();
38+
39+
// Test skip navigation functionality
40+
await skipNav.ClickAsync();
41+
await Expect(Page.Locator("#main-content")).ToBeFocusedAsync();
42+
}
43+
44+
[Test]
45+
public async Task Page_ShouldHaveProperARIALabels()
46+
{
47+
// Check for proper ARIA roles
48+
var banner = Page.Locator("header[role='banner']");
49+
await Expect(banner).ToBeVisibleAsync();
50+
51+
var main = Page.Locator("main[role='main']");
52+
await Expect(main).ToBeVisibleAsync();
53+
54+
var contentinfo = Page.Locator("footer[role='contentinfo']").First;
55+
await Expect(contentinfo).ToBeVisibleAsync();
56+
}
57+
58+
[Test]
59+
public async Task Page_ShouldBeKeyboardNavigable()
60+
{
61+
// Test keyboard navigation
62+
await Page.Keyboard.PressAsync("Tab");
63+
var focusedElement = Page.Locator(":focus");
64+
await Expect(focusedElement).ToBeVisibleAsync();
65+
66+
// Test tab order
67+
await Page.Keyboard.PressAsync("Tab");
68+
await Page.Keyboard.PressAsync("Tab");
69+
await Page.Keyboard.PressAsync("Tab");
70+
71+
// Verify we can still see focused elements
72+
await Expect(focusedElement).ToBeVisibleAsync();
73+
}
74+
75+
[Test]
76+
public async Task Page_ShouldLoadWithinAcceptableTime()
77+
{
78+
var startTime = DateTime.Now;
79+
80+
await Page.GotoAsync(BaseUrl);
81+
await Page.WaitForLoadStateAsync(LoadState.NetworkIdle);
82+
83+
var loadTime = DateTime.Now - startTime;
84+
85+
// Page should load within 5 seconds
86+
Assert.That(loadTime.TotalSeconds, Is.LessThan(5),
87+
$"Page took {loadTime.TotalSeconds:F2} seconds to load, which exceeds the 5-second limit");
88+
}
89+
90+
[Test]
91+
public async Task Page_ShouldHaveReasonableImageSizes()
92+
{
93+
// Check for images and their sizes
94+
var images = Page.Locator("img");
95+
var imageCount = await images.CountAsync();
96+
97+
if (imageCount > 0)
98+
{
99+
for (int i = 0; i < imageCount; i++)
100+
{
101+
var img = images.Nth(i);
102+
var src = await img.GetAttributeAsync("src");
103+
104+
// Skip data URLs and external images
105+
if (src != null && !src.StartsWith("data:") && !src.StartsWith("http"))
106+
{
107+
// Check if image has alt text
108+
var alt = await img.GetAttributeAsync("alt");
109+
Assert.That(alt, Is.Not.Null, $"Image {src} should have alt text");
110+
}
111+
}
112+
}
113+
}
114+
115+
[Test]
116+
public async Task Page_ShouldHaveProperColorContrast()
117+
{
118+
// This is a basic test - in a real scenario, you'd use a proper accessibility testing library
119+
// For now, we'll just verify that text elements are visible
120+
var textElements = Page.Locator("p, h1, h2, h3, h4, h5, h6, span, div");
121+
var textCount = await textElements.CountAsync();
122+
123+
Assert.That(textCount, Is.GreaterThan(0), "Page should have text content");
124+
125+
// Verify main text is visible
126+
var mainText = Page.Locator("main p, main h1, main h2, main h3");
127+
var mainTextCount = await mainText.CountAsync();
128+
Assert.That(mainTextCount, Is.GreaterThan(0), "Main content should have visible text");
129+
}
130+
131+
[Test]
132+
public async Task Page_ShouldWorkWithScreenReader()
133+
{
134+
// Test that important elements have proper labels
135+
var buttons = Page.Locator("button");
136+
var buttonCount = await buttons.CountAsync();
137+
138+
for (int i = 0; i < buttonCount; i++)
139+
{
140+
var button = buttons.Nth(i);
141+
var text = await button.TextContentAsync();
142+
var ariaLabel = await button.GetAttributeAsync("aria-label");
143+
144+
// Button should have either text content or aria-label
145+
Assert.That(!string.IsNullOrEmpty(text) || !string.IsNullOrEmpty(ariaLabel),
146+
"Buttons should have text content or aria-label for screen readers");
147+
}
148+
}
149+
150+
[Test]
151+
public async Task Page_ShouldHandleFocusManagement()
152+
{
153+
// Test focus management
154+
var focusableElements = Page.Locator("a, button, input, textarea, select");
155+
var focusableCount = await focusableElements.CountAsync();
156+
157+
if (focusableCount > 0)
158+
{
159+
// Test that we can focus on elements
160+
await focusableElements.First.FocusAsync();
161+
var focusedElement = Page.Locator(":focus");
162+
await Expect(focusedElement).ToBeVisibleAsync();
163+
}
164+
}
165+
166+
[Test]
167+
public async Task Page_ShouldHaveProperMetaTags()
168+
{
169+
// Check for essential meta tags
170+
var viewport = Page.Locator("meta[name='viewport']");
171+
await Expect(viewport).ToHaveAttributeAsync("content", new Regex(".*"));
172+
173+
var charset = Page.Locator("meta[charset]");
174+
await Expect(charset).ToHaveAttributeAsync("charset", new Regex(".*"));
175+
176+
// Check for description
177+
var description = Page.Locator("meta[name='description']");
178+
var descriptionContent = await description.GetAttributeAsync("content");
179+
Assert.That(descriptionContent, Is.Not.Null.And.Not.Empty,
180+
"Page should have a meta description");
181+
}
182+
}

TextHub.Tests/ExampleToolTest.cs

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
using Microsoft.Playwright;
2+
using Microsoft.Playwright.NUnit;
3+
using NUnit.Framework;
4+
using System.Text.RegularExpressions;
5+
6+
namespace TextHub.Tests;
7+
8+
/// <summary>
9+
/// Example test demonstrating how to test a specific tool functionality
10+
/// This serves as a template for creating more specific tool tests
11+
/// </summary>
12+
[TestFixture]
13+
public class ExampleToolTest : PageTest
14+
{
15+
private string BaseUrl => GlobalSetup.GetBaseUrl();
16+
17+
[SetUp]
18+
public async Task SetUp()
19+
{
20+
await Page.GotoAsync(BaseUrl);
21+
await Page.WaitForLoadStateAsync(LoadState.NetworkIdle);
22+
}
23+
24+
[Test]
25+
public async Task Example_WordCounterTool_ShouldWorkCorrectly()
26+
{
27+
// Navigate to the word counter tool
28+
await Page.GotoAsync($"{BaseUrl}/word-counter");
29+
await Page.WaitForLoadStateAsync(LoadState.NetworkIdle);
30+
31+
// Verify the page title
32+
await Expect(Page).ToHaveTitleAsync("Word Counter - Text Hub");
33+
34+
// Find the text input area
35+
var textInput = Page.Locator("textarea, input[type='text']").First;
36+
await Expect(textInput).ToBeVisibleAsync();
37+
38+
// Test with sample text
39+
var testText = "Hello world! This is a test with 8 words.";
40+
await textInput.FillAsync(testText);
41+
42+
// Trigger any change events
43+
await textInput.BlurAsync();
44+
await Page.WaitForTimeoutAsync(500); // Wait for any async processing
45+
46+
// Look for word count display
47+
var wordCountElement = Page.Locator("[class*='count'], [class*='word'], [class*='result']").First;
48+
await Expect(wordCountElement).ToBeVisibleAsync();
49+
50+
// Get the displayed count
51+
var displayedCount = await wordCountElement.TextContentAsync();
52+
53+
// Verify the count is reasonable (exact count depends on implementation)
54+
Assert.That(displayedCount, Is.Not.Null.And.Not.Empty, "Word count should be displayed");
55+
56+
// You could add more specific assertions based on your implementation
57+
// For example, if the count is displayed as "8 words":
58+
// Assert.That(displayedCount, Does.Contain("8"));
59+
}
60+
61+
[Test]
62+
public async Task Example_TextCaseConversion_ShouldWorkCorrectly()
63+
{
64+
// Navigate to a text case conversion tool (e.g., camel case)
65+
await Page.GotoAsync($"{BaseUrl}/camel-case");
66+
await Page.WaitForLoadStateAsync(LoadState.NetworkIdle);
67+
68+
// Verify the page title
69+
await Expect(Page).ToHaveTitleAsync("camelCase Converter - Text Hub");
70+
71+
// Find the input and output areas
72+
var textInput = Page.Locator("textarea, input[type='text']").First;
73+
var textOutput = Page.Locator("[class*='output'], [class*='result'], [class*='converted']").First;
74+
75+
await Expect(textInput).ToBeVisibleAsync();
76+
await Expect(textOutput).ToBeVisibleAsync();
77+
78+
// Test with sample text
79+
var inputText = "hello world test";
80+
81+
await textInput.FillAsync(inputText);
82+
await textInput.BlurAsync();
83+
await Page.WaitForTimeoutAsync(500); // Wait for conversion
84+
85+
// Get the converted text
86+
var actualOutput = await textOutput.TextContentAsync();
87+
88+
// Verify the conversion worked
89+
Assert.That(actualOutput, Is.Not.Null.And.Not.Empty, "Converted text should be displayed");
90+
91+
// Note: The exact assertion depends on your implementation
92+
// You might need to adjust this based on how the output is formatted
93+
// Assert.That(actualOutput.Trim(), Is.EqualTo(expectedOutput));
94+
}
95+
96+
[Test]
97+
public async Task Example_JsonFormatter_ShouldFormatJson()
98+
{
99+
// Navigate to the JSON formatter tool
100+
await Page.GotoAsync($"{BaseUrl}/json-formatter");
101+
await Page.WaitForLoadStateAsync(LoadState.NetworkIdle);
102+
103+
// Verify the page title
104+
await Expect(Page).ToHaveTitleAsync("JSON Formatter - Text Hub");
105+
106+
// Find the input and output areas
107+
var jsonInput = Page.Locator("textarea, input[type='text']").First;
108+
var jsonOutput = Page.Locator("[class*='output'], [class*='result'], [class*='formatted']").First;
109+
110+
await Expect(jsonInput).ToBeVisibleAsync();
111+
await Expect(jsonOutput).ToBeVisibleAsync();
112+
113+
// Test with minified JSON
114+
var minifiedJson = "{\"name\":\"test\",\"value\":123,\"items\":[1,2,3]}";
115+
await jsonInput.FillAsync(minifiedJson);
116+
await jsonInput.BlurAsync();
117+
await Page.WaitForTimeoutAsync(500); // Wait for formatting
118+
119+
// Get the formatted JSON
120+
var formattedJson = await jsonOutput.TextContentAsync();
121+
122+
// Verify the formatting worked
123+
Assert.That(formattedJson, Is.Not.Null.And.Not.Empty, "Formatted JSON should be displayed");
124+
125+
// The formatted JSON should be different from the input (more readable)
126+
Assert.That(formattedJson, Is.Not.EqualTo(minifiedJson), "Formatted JSON should be different from input");
127+
}
128+
129+
[Test]
130+
public async Task Example_Tool_ShouldHandleEmptyInput()
131+
{
132+
// Navigate to any tool (using word counter as example)
133+
await Page.GotoAsync($"{BaseUrl}/word-counter");
134+
await Page.WaitForLoadStateAsync(LoadState.NetworkIdle);
135+
136+
// Find the text input
137+
var textInput = Page.Locator("textarea, input[type='text']").First;
138+
await Expect(textInput).ToBeVisibleAsync();
139+
140+
// Test with empty input
141+
await textInput.FillAsync("");
142+
await textInput.BlurAsync();
143+
await Page.WaitForTimeoutAsync(500);
144+
145+
// Verify the tool handles empty input gracefully
146+
// (No errors should occur, and output should show appropriate message)
147+
var output = Page.Locator("[class*='count'], [class*='result'], [class*='output']").First;
148+
await Expect(output).ToBeVisibleAsync();
149+
150+
// The output should indicate zero or empty result
151+
var outputText = await output.TextContentAsync();
152+
Assert.That(outputText, Is.Not.Null, "Output should be displayed even for empty input");
153+
}
154+
155+
[Test]
156+
public async Task Example_Tool_ShouldHandleLargeInput()
157+
{
158+
// Navigate to any tool (using word counter as example)
159+
await Page.GotoAsync($"{BaseUrl}/word-counter");
160+
await Page.WaitForLoadStateAsync(LoadState.NetworkIdle);
161+
162+
// Find the text input
163+
var textInput = Page.Locator("textarea, input[type='text']").First;
164+
await Expect(textInput).ToBeVisibleAsync();
165+
166+
// Test with large input
167+
var largeText = string.Join(" ", Enumerable.Repeat("word", 1000)); // 1000 words
168+
await textInput.FillAsync(largeText);
169+
await textInput.BlurAsync();
170+
await Page.WaitForTimeoutAsync(1000); // Wait longer for processing
171+
172+
// Verify the tool handles large input without issues
173+
var output = Page.Locator("[class*='count'], [class*='result'], [class*='output']").First;
174+
await Expect(output).ToBeVisibleAsync();
175+
176+
// The output should show the correct count
177+
var outputText = await output.TextContentAsync();
178+
Assert.That(outputText, Is.Not.Null.And.Not.Empty, "Output should be displayed for large input");
179+
}
180+
}

0 commit comments

Comments
 (0)