mirror of
https://github.com/Dvorinka/Devour.git
synced 2026-06-04 04:23:02 +00:00
first commit
This commit is contained in:
@@ -0,0 +1,265 @@
|
||||
package rustdocs
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
)
|
||||
|
||||
const testStructPageHTML = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<main>
|
||||
<div class="main-heading">
|
||||
<div class="rustdoc-breadcrumbs"><a href="../index.html">std</a>::<wbr><a href="index.html">simd</a></div>
|
||||
<h1>Struct <span class="struct">Mask</span></h1>
|
||||
<span class="sub-heading"><span class="since" title="Stable since Rust version 1.0.0">1.0.0</span></span>
|
||||
</div>
|
||||
<pre class="rust item-decl"><code>pub struct Mask<T, const N: usize>(<span class="comment">/* private fields */</span>)</code></pre>
|
||||
<details class="toggle top-doc" open="">
|
||||
<div class="docblock"><p>A SIMD vector mask for N elements.</p></div>
|
||||
</details>
|
||||
<h2 id="implementations">Implementations</h2>
|
||||
<details class="toggle implementors-toggle" open="">
|
||||
<details class="toggle method-toggle" open="">
|
||||
<section id="method.test" class="method">
|
||||
<h4 class="code-header">pub fn <a href="#method.test" class="fn">test</a>(&self, index: usize) -> bool</h4>
|
||||
</section>
|
||||
<div class="docblock"><p>Tests the value of the specified element.</p></div>
|
||||
</details>
|
||||
</details>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
|
||||
const testSearchHTML = `
|
||||
<div id="results">
|
||||
<ul class="search-results active">
|
||||
<a class="result-method" href="../std/simd/struct.Mask.html#method.test">
|
||||
<span class="result-name">
|
||||
<span class="typename">method</span>
|
||||
<div class="path"><span>std::</span><span>simd::</span><span class="method">Mask::</span><span class="fn">test</span></div>
|
||||
</span>
|
||||
<div class="desc">Tests the value of the specified element.</div>
|
||||
</a>
|
||||
<a class="result-struct" href="../std/vec/struct.Vec.html">
|
||||
<span class="result-name">
|
||||
<span class="typename">struct</span>
|
||||
<div class="path"><span>std::</span><span>vec::</span><span class="struct">Vec</span></div>
|
||||
</span>
|
||||
<div class="desc">A contiguous growable array type.</div>
|
||||
</a>
|
||||
<a class="result-fn" href="../std/io/fn.stdout.html">
|
||||
<span class="result-name">
|
||||
<span class="typename">fn</span>
|
||||
<div class="path"><span>std::</span><span>io::</span><span class="fn">stdout</span></div>
|
||||
</span>
|
||||
<div class="desc">Constructs a new handle to the standard output.</div>
|
||||
</a>
|
||||
</ul>
|
||||
</div>
|
||||
`
|
||||
|
||||
const testCratePageHTML = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<main>
|
||||
<div class="main-heading">
|
||||
<h1>Crate <span>serde</span></h1>
|
||||
<span class="sub-heading"><span class="since">1.0.0</span></span>
|
||||
</div>
|
||||
<details class="toggle top-doc">
|
||||
<div class="docblock"><p>A framework for serializing and deserializing Rust data structures.</p></div>
|
||||
</details>
|
||||
<h2 id="modules">Modules</h2>
|
||||
<div class="item-table">
|
||||
<div class="module-item"><a class="mod" href="de/index.html">de</a><div class="desc">Deserialize implementation.</div></div>
|
||||
</div>
|
||||
<h2 id="structs">Structs</h2>
|
||||
<div class="item-table">
|
||||
<div class="struct"><a class="struct" href="struct.Serializer.html">Serializer</a><div class="desc">A structure for serializing Rust values.</div></div>
|
||||
</div>
|
||||
<h2 id="enums">Enums</h2>
|
||||
<div class="item-table">
|
||||
<div class="enum"><a class="enum" href="enum.Error.html">Error</a><div class="desc">Errors during serialization.</div></div>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
|
||||
func TestParseItemPage(t *testing.T) {
|
||||
parser := NewParser()
|
||||
symbol, err := parser.ParseItemPage(testStructPageHTML, "https://docs.rs/std/simd/struct.Mask.html")
|
||||
if err != nil {
|
||||
t.Fatalf("ParseItemPage failed: %v", err)
|
||||
}
|
||||
|
||||
if symbol.Name != "Mask" {
|
||||
t.Errorf("Expected name 'Mask', got '%s'", symbol.Name)
|
||||
}
|
||||
|
||||
if symbol.Kind != ItemKindStruct {
|
||||
t.Errorf("Expected kind 'struct', got '%s'", symbol.Kind)
|
||||
}
|
||||
|
||||
if symbol.Doc == "" {
|
||||
t.Error("Expected non-empty doc")
|
||||
}
|
||||
|
||||
if !strings.Contains(symbol.Signature, "struct Mask") {
|
||||
t.Errorf("Expected signature to contain 'struct Mask', got '%s'", symbol.Signature)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseSearchResults(t *testing.T) {
|
||||
parser := NewParser()
|
||||
results, err := parser.ParseSearchResults(testSearchHTML)
|
||||
if err != nil {
|
||||
t.Fatalf("ParseSearchResults failed: %v", err)
|
||||
}
|
||||
|
||||
if len(results) < 3 {
|
||||
t.Fatalf("Expected at least 3 results, got %d", len(results))
|
||||
}
|
||||
|
||||
method := results[0]
|
||||
if method.Kind != "fn" {
|
||||
t.Errorf("Expected kind 'fn' for method, got '%s'", method.Kind)
|
||||
}
|
||||
if method.Description == "" {
|
||||
t.Error("Expected non-empty description")
|
||||
}
|
||||
|
||||
structResult := results[1]
|
||||
if structResult.Kind != "struct" {
|
||||
t.Errorf("Expected kind 'struct', got '%s'", structResult.Kind)
|
||||
}
|
||||
|
||||
fnResult := results[2]
|
||||
if fnResult.Kind != "fn" {
|
||||
t.Errorf("Expected kind 'fn', got '%s'", fnResult.Kind)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseCratePage(t *testing.T) {
|
||||
parser := NewParser()
|
||||
crate, err := parser.ParseCratePage(testCratePageHTML, "https://docs.rs/serde")
|
||||
if err != nil {
|
||||
t.Fatalf("ParseCratePage failed: %v", err)
|
||||
}
|
||||
|
||||
if crate.Name == "" {
|
||||
t.Error("Expected non-empty name")
|
||||
}
|
||||
|
||||
if crate.Description == "" {
|
||||
t.Error("Expected non-empty description")
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractKindFromClasses(t *testing.T) {
|
||||
tests := []struct {
|
||||
classes string
|
||||
expected string
|
||||
}{
|
||||
{"result-struct", "struct"},
|
||||
{"result-enum", "enum"},
|
||||
{"result-trait", "trait"},
|
||||
{"result-fn", "fn"},
|
||||
{"result-macro", "macro"},
|
||||
{"result-const", "const"},
|
||||
{"result-static", "static"},
|
||||
{"result-mod", "mod"},
|
||||
{"result-method", "fn"},
|
||||
{"result-externcrate", "mod"},
|
||||
{"unknown-class", ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.classes, func(t *testing.T) {
|
||||
got := extractKindFromClasses(tt.classes)
|
||||
if got != tt.expected {
|
||||
t.Errorf("extractKindFromClasses(%q) = %q, want %q", tt.classes, got, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveURL(t *testing.T) {
|
||||
tests := []struct {
|
||||
base string
|
||||
href string
|
||||
expected string
|
||||
}{
|
||||
{"https://docs.rs", "/serde/struct.Serializer.html", "https://docs.rs/serde/struct.Serializer.html"},
|
||||
{"https://docs.rs", "https://example.com/page", "https://example.com/page"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.href, func(t *testing.T) {
|
||||
got := resolveURL(tt.base, tt.href)
|
||||
if got != tt.expected {
|
||||
t.Errorf("resolveURL(%q, %q) = %q, want %q", tt.base, tt.href, got, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCleanText(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{" hello world ", "hello world"},
|
||||
{"single", "single"},
|
||||
{"\n\ttabs\t\n", "tabs"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.input, func(t *testing.T) {
|
||||
if got := cleanText(tt.input); got != tt.expected {
|
||||
t.Errorf("cleanText(%q) = %q, want %q", tt.input, got, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractItemPath(t *testing.T) {
|
||||
parser := NewParser()
|
||||
|
||||
html := `<div class="rustdoc-breadcrumbs"><a href="../index.html">std</a>::<a href="index.html">simd</a></div>`
|
||||
doc, err := goquery.NewDocumentFromReader(strings.NewReader(html))
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to parse HTML: %v", err)
|
||||
}
|
||||
|
||||
got := parser.extractItemPath(doc, "https://docs.rs/std/simd/struct.Mask.html")
|
||||
|
||||
if !strings.Contains(got, "std") || !strings.Contains(got, "simd") {
|
||||
t.Errorf("extractItemPath() = %q, expected to contain std and simd", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractMethods(t *testing.T) {
|
||||
parser := NewParser()
|
||||
|
||||
doc, err := goquery.NewDocumentFromReader(strings.NewReader(testStructPageHTML))
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to parse HTML: %v", err)
|
||||
}
|
||||
|
||||
methods := parser.ExtractMethods(doc)
|
||||
if len(methods) == 0 {
|
||||
t.Error("Expected at least one method")
|
||||
return
|
||||
}
|
||||
|
||||
if methods[0].Name == "" {
|
||||
t.Error("Expected non-empty method name")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user