mirror of
https://github.com/Dvorinka/Devour.git
synced 2026-06-03 20:13:03 +00:00
266 lines
7.3 KiB
Go
266 lines
7.3 KiB
Go
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")
|
|
}
|
|
}
|