참고소스 수정본
This commit is contained in:
3
참고/firecrawl-main/apps/elixir-sdk/.formatter.exs
Normal file
3
참고/firecrawl-main/apps/elixir-sdk/.formatter.exs
Normal file
@@ -0,0 +1,3 @@
|
||||
[
|
||||
inputs: ["{mix,.formatter}.exs", "generate.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||
]
|
||||
25
참고/firecrawl-main/apps/elixir-sdk/.gitignore
vendored
Normal file
25
참고/firecrawl-main/apps/elixir-sdk/.gitignore
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# The directory Mix will write compiled artifacts to.
|
||||
/_build/
|
||||
|
||||
# If you run "mix test --cover", coverage assets end up here.
|
||||
/cover/
|
||||
|
||||
# The directory Mix downloads your dependencies sources to.
|
||||
/deps/
|
||||
|
||||
# Where third-party dependencies like ExDoc output generated docs.
|
||||
/doc/
|
||||
|
||||
# Temporary files, for example, from tests.
|
||||
/tmp/
|
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||
erl_crash.dump
|
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build").
|
||||
*.ez
|
||||
|
||||
# Ignore package tarball (built via "mix hex.build").
|
||||
firecrawl-*.tar
|
||||
firecrawl-*/
|
||||
|
||||
21
참고/firecrawl-main/apps/elixir-sdk/LICENSE
Normal file
21
참고/firecrawl-main/apps/elixir-sdk/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Sideguide Technologies Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
104
참고/firecrawl-main/apps/elixir-sdk/README.md
Normal file
104
참고/firecrawl-main/apps/elixir-sdk/README.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# Firecrawl
|
||||
|
||||
Auto-generated Elixir client for the [Firecrawl API v2](https://docs.firecrawl.dev/api-reference).
|
||||
|
||||
Built with [`Req`](https://hexdocs.pm/req) — minimal, idiomatic, auto-generated from the OpenAPI spec with [`NimbleOptions`](https://hexdocs.pm/nimble_options) validation.
|
||||
|
||||
## Installation
|
||||
|
||||
Add `firecrawl` to your list of dependencies in `mix.exs`:
|
||||
|
||||
```elixir
|
||||
def deps do
|
||||
[
|
||||
{:firecrawl, "~> 1.0"}
|
||||
]
|
||||
end
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Set your API key in application config:
|
||||
|
||||
```elixir
|
||||
config :firecrawl, api_key: "fc-your-api-key"
|
||||
```
|
||||
|
||||
Or pass it as an option to any function:
|
||||
|
||||
```elixir
|
||||
Firecrawl.scrape_and_extract_from_url([url: "https://example.com"], api_key: "fc-your-api-key")
|
||||
```
|
||||
|
||||
If no API key is found in config or options, a `RuntimeError` is raised with instructions.
|
||||
|
||||
## Usage
|
||||
|
||||
All params are passed as keyword lists with snake_case keys. Invalid keys, missing required params, and type errors are caught immediately by `NimbleOptions`.
|
||||
|
||||
```elixir
|
||||
# Scrape a URL
|
||||
{:ok, response} = Firecrawl.scrape_and_extract_from_url(
|
||||
url: "https://example.com",
|
||||
formats: ["markdown"]
|
||||
)
|
||||
|
||||
# Crawl a site
|
||||
{:ok, response} = Firecrawl.crawl_urls(
|
||||
url: "https://example.com",
|
||||
limit: 100,
|
||||
sitemap: :skip
|
||||
)
|
||||
|
||||
# Map URLs
|
||||
{:ok, response} = Firecrawl.map_urls(url: "https://example.com")
|
||||
|
||||
# Search
|
||||
{:ok, response} = Firecrawl.search_and_scrape(query: "firecrawl web scraping")
|
||||
|
||||
# Check crawl status
|
||||
{:ok, response} = Firecrawl.get_crawl_status("job-uuid")
|
||||
|
||||
# Parse a file (PDF, DOCX, HTML, etc.)
|
||||
{:ok, response} = Firecrawl.parse_file(
|
||||
[filename: "report.pdf", data: File.read!("report.pdf"), content_type: "application/pdf"],
|
||||
formats: ["markdown"]
|
||||
)
|
||||
|
||||
# Self-hosted instance
|
||||
{:ok, response} = Firecrawl.scrape_and_extract_from_url(
|
||||
[url: "https://example.com"],
|
||||
base_url: "https://your-instance.com/v2"
|
||||
)
|
||||
```
|
||||
|
||||
### Bang variants
|
||||
|
||||
Every function has a `!` variant that raises on error instead of returning `{:error, _}`:
|
||||
|
||||
```elixir
|
||||
response = Firecrawl.scrape_and_extract_from_url!(url: "https://example.com")
|
||||
```
|
||||
|
||||
## Regenerating from the OpenAPI Spec
|
||||
|
||||
The entire client is auto-generated from the Firecrawl OpenAPI specification. To regenerate after spec changes:
|
||||
|
||||
```bash
|
||||
mix run generate.exs
|
||||
```
|
||||
|
||||
This will:
|
||||
|
||||
1. Fetch the latest OpenAPI JSON from GitHub
|
||||
2. Generate all API wrapper functions in `lib/firecrawl.ex`
|
||||
3. Bump the version in `mix.exs` using semver (only if the generated code changed):
|
||||
- **Major** bump if public functions were removed (breaking change)
|
||||
- **Minor** bump if new public functions were added
|
||||
- **Patch** bump for any other changes (signatures, docs, etc.)
|
||||
|
||||
Re-running when nothing changed is a no-op — the version is not bumped.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
1101
참고/firecrawl-main/apps/elixir-sdk/generate.exs
Normal file
1101
참고/firecrawl-main/apps/elixir-sdk/generate.exs
Normal file
File diff suppressed because it is too large
Load Diff
1552
참고/firecrawl-main/apps/elixir-sdk/lib/firecrawl.ex
Normal file
1552
참고/firecrawl-main/apps/elixir-sdk/lib/firecrawl.ex
Normal file
File diff suppressed because it is too large
Load Diff
32
참고/firecrawl-main/apps/elixir-sdk/lib/firecrawl/error.ex
Normal file
32
참고/firecrawl-main/apps/elixir-sdk/lib/firecrawl/error.ex
Normal file
@@ -0,0 +1,32 @@
|
||||
defmodule Firecrawl.Error do
|
||||
@moduledoc """
|
||||
Exception raised when the Firecrawl API returns an error response (HTTP 4xx/5xx).
|
||||
|
||||
## Fields
|
||||
|
||||
* `:status` - The HTTP status code
|
||||
* `:body` - The decoded response body (typically a map with `"error"` key)
|
||||
"""
|
||||
|
||||
defexception [:status, :body]
|
||||
|
||||
@type t :: %__MODULE__{
|
||||
status: pos_integer(),
|
||||
body: term()
|
||||
}
|
||||
|
||||
@impl true
|
||||
def message(%__MODULE__{status: status, body: body}) when is_map(body) do
|
||||
error_msg =
|
||||
case body["error"] || body["message"] do
|
||||
msg when is_binary(msg) -> msg
|
||||
_ -> inspect(body)
|
||||
end
|
||||
|
||||
"Firecrawl API error (HTTP #{status}): #{error_msg}"
|
||||
end
|
||||
|
||||
def message(%__MODULE__{status: status, body: body}) do
|
||||
"Firecrawl API error (HTTP #{status}): #{inspect(body)}"
|
||||
end
|
||||
end
|
||||
48
참고/firecrawl-main/apps/elixir-sdk/mix.exs
Normal file
48
참고/firecrawl-main/apps/elixir-sdk/mix.exs
Normal file
@@ -0,0 +1,48 @@
|
||||
defmodule Firecrawl.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
@version "1.3.1"
|
||||
@source_url "https://github.com/firecrawl/firecrawl/tree/main/apps/elixir-sdk"
|
||||
|
||||
def project do
|
||||
[
|
||||
app: :firecrawl,
|
||||
version: @version,
|
||||
elixir: "~> 1.15",
|
||||
start_permanent: Mix.env() == :prod,
|
||||
deps: deps(),
|
||||
package: package(),
|
||||
name: "Firecrawl",
|
||||
description: "Auto-generated Elixir client for the Firecrawl API v2",
|
||||
source_url: @source_url,
|
||||
docs: [
|
||||
main: "Firecrawl",
|
||||
extras: ["README.md"]
|
||||
]
|
||||
]
|
||||
end
|
||||
|
||||
def application do
|
||||
[
|
||||
extra_applications: [:logger]
|
||||
]
|
||||
end
|
||||
|
||||
defp deps do
|
||||
[
|
||||
{:req, "~> 0.5"},
|
||||
{:nimble_options, "~> 1.1"},
|
||||
{:ex_doc, "~> 0.34", only: :dev, runtime: false}
|
||||
]
|
||||
end
|
||||
|
||||
defp package do
|
||||
[
|
||||
files: ~w(lib .formatter.exs mix.exs README.md LICENSE),
|
||||
licenses: ["MIT"],
|
||||
links: %{
|
||||
"GitHub" => @source_url
|
||||
}
|
||||
]
|
||||
end
|
||||
end
|
||||
17
참고/firecrawl-main/apps/elixir-sdk/mix.lock
Normal file
17
참고/firecrawl-main/apps/elixir-sdk/mix.lock
Normal file
@@ -0,0 +1,17 @@
|
||||
%{
|
||||
"earmark_parser": {:hex, :earmark_parser, "1.4.44", "f20830dd6b5c77afe2b063777ddbbff09f9759396500cdbe7523efd58d7a339c", [:mix], [], "hexpm", "4778ac752b4701a5599215f7030989c989ffdc4f6df457c5f36938cc2d2a2750"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.40.1", "67542e4b6dde74811cfd580e2c0149b78010fd13001fda7cfeb2b2c2ffb1344d", [:mix], [{:earmark_parser, "~> 1.4.44", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "bcef0e2d360d93ac19f01a85d58f91752d930c0a30e2681145feea6bd3516e00"},
|
||||
"finch": {:hex, :finch, "0.21.0", "b1c3b2d48af02d0c66d2a9ebfb5622be5c5ecd62937cf79a88a7f98d48a8290c", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "87dc6e169794cb2570f75841a19da99cfde834249568f2a5b121b809588a4377"},
|
||||
"hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"},
|
||||
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},
|
||||
"makeup": {:hex, :makeup, "1.2.1", "e90ac1c65589ef354378def3ba19d401e739ee7ee06fb47f94c687016e3713d1", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "d36484867b0bae0fea568d10131197a4c2e47056a6fbe84922bf6ba71c8d17ce"},
|
||||
"makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"},
|
||||
"makeup_erlang": {:hex, :makeup_erlang, "1.0.3", "4252d5d4098da7415c390e847c814bad3764c94a814a0b4245176215615e1035", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "953297c02582a33411ac6208f2c6e55f0e870df7f80da724ed613f10e6706afd"},
|
||||
"mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"},
|
||||
"mint": {:hex, :mint, "1.7.1", "113fdb2b2f3b59e47c7955971854641c61f378549d73e829e1768de90fc1abf1", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "fceba0a4d0f24301ddee3024ae116df1c3f4bb7a563a731f45fdfeb9d39a231b"},
|
||||
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
|
||||
"nimble_parsec": {:hex, :nimble_parsec, "1.4.2", "8efba0122db06df95bfaa78f791344a89352ba04baedd3849593bfce4d0dc1c6", [:mix], [], "hexpm", "4b21398942dda052b403bbe1da991ccd03a053668d147d53fb8c4e0efe09c973"},
|
||||
"nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"},
|
||||
"req": {:hex, :req, "0.5.17", "0096ddd5b0ed6f576a03dde4b158a0c727215b15d2795e59e0916c6971066ede", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.17", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "0b8bc6ffdfebbc07968e59d3ff96d52f2202d0536f10fef4dc11dc02a2a43e39"},
|
||||
"telemetry": {:hex, :telemetry, "1.4.1", "ab6de178e2b29b58e8256b92b382ea3f590a47152ca3651ea857a6cae05ac423", [:rebar3], [], "hexpm", "2172e05a27531d3d31dd9782841065c50dd5c3c7699d95266b2edd54c2dafa1c"},
|
||||
}
|
||||
249
참고/firecrawl-main/apps/elixir-sdk/test/firecrawl_test.exs
Normal file
249
참고/firecrawl-main/apps/elixir-sdk/test/firecrawl_test.exs
Normal file
@@ -0,0 +1,249 @@
|
||||
defmodule FirecrawlTest do
|
||||
use ExUnit.Case
|
||||
|
||||
test "raises when no API key is configured" do
|
||||
old = Application.get_env(:firecrawl, :api_key)
|
||||
Application.delete_env(:firecrawl, :api_key)
|
||||
on_exit(fn -> if old, do: Application.put_env(:firecrawl, :api_key, old) end)
|
||||
|
||||
assert_raise RuntimeError, ~r/Firecrawl API key not found/, fn ->
|
||||
Firecrawl.get_credit_usage()
|
||||
end
|
||||
end
|
||||
|
||||
test "does not raise when API key is in application config" do
|
||||
Application.put_env(:firecrawl, :api_key, "test-config-key")
|
||||
on_exit(fn -> Application.delete_env(:firecrawl, :api_key) end)
|
||||
|
||||
result = Firecrawl.get_queue_status(base_url: "http://localhost:1", retry: false)
|
||||
assert {:error, _} = result
|
||||
end
|
||||
|
||||
test "does not raise when API key is passed as option" do
|
||||
old = Application.get_env(:firecrawl, :api_key)
|
||||
Application.delete_env(:firecrawl, :api_key)
|
||||
on_exit(fn -> if old, do: Application.put_env(:firecrawl, :api_key, old) end)
|
||||
|
||||
result =
|
||||
Firecrawl.get_queue_status(
|
||||
api_key: "test-opt-key",
|
||||
base_url: "http://localhost:1",
|
||||
retry: false
|
||||
)
|
||||
|
||||
assert {:error, _} = result
|
||||
end
|
||||
|
||||
test "non-bang returns {:error, _} for missing required params" do
|
||||
Application.put_env(:firecrawl, :api_key, "test-key")
|
||||
on_exit(fn -> Application.delete_env(:firecrawl, :api_key) end)
|
||||
|
||||
assert {:error, %NimbleOptions.ValidationError{}} =
|
||||
Firecrawl.scrape_and_extract_from_url([])
|
||||
end
|
||||
|
||||
test "non-bang returns {:error, _} for unknown keys (typo detection)" do
|
||||
Application.put_env(:firecrawl, :api_key, "test-key")
|
||||
on_exit(fn -> Application.delete_env(:firecrawl, :api_key) end)
|
||||
|
||||
assert {:error, %NimbleOptions.ValidationError{message: msg}} =
|
||||
Firecrawl.scrape_and_extract_from_url(url: "https://example.com", typo_option: true)
|
||||
|
||||
assert msg =~ "unknown options"
|
||||
end
|
||||
|
||||
test "non-bang returns {:error, _} for wrong types" do
|
||||
Application.put_env(:firecrawl, :api_key, "test-key")
|
||||
on_exit(fn -> Application.delete_env(:firecrawl, :api_key) end)
|
||||
|
||||
assert {:error, %NimbleOptions.ValidationError{}} =
|
||||
Firecrawl.crawl_urls(url: "https://example.com", limit: "not an integer")
|
||||
end
|
||||
|
||||
test "bang raises for missing required params" do
|
||||
Application.put_env(:firecrawl, :api_key, "test-key")
|
||||
on_exit(fn -> Application.delete_env(:firecrawl, :api_key) end)
|
||||
|
||||
assert_raise NimbleOptions.ValidationError, ~r/required/, fn ->
|
||||
Firecrawl.scrape_and_extract_from_url!([])
|
||||
end
|
||||
end
|
||||
|
||||
test "bang raises for unknown keys" do
|
||||
Application.put_env(:firecrawl, :api_key, "test-key")
|
||||
on_exit(fn -> Application.delete_env(:firecrawl, :api_key) end)
|
||||
|
||||
assert_raise NimbleOptions.ValidationError, ~r/unknown options/, fn ->
|
||||
Firecrawl.scrape_and_extract_from_url!(url: "https://example.com", typo_option: true)
|
||||
end
|
||||
end
|
||||
|
||||
test "accepts atom values for enum params" do
|
||||
Application.put_env(:firecrawl, :api_key, "test-key")
|
||||
on_exit(fn -> Application.delete_env(:firecrawl, :api_key) end)
|
||||
|
||||
result =
|
||||
Firecrawl.crawl_urls(
|
||||
[url: "https://example.com", sitemap: :skip],
|
||||
base_url: "http://localhost:1",
|
||||
retry: false
|
||||
)
|
||||
|
||||
assert {:error, _} = result
|
||||
end
|
||||
|
||||
test "accepts string values for enum params (model)" do
|
||||
Application.put_env(:firecrawl, :api_key, "test-key")
|
||||
on_exit(fn -> Application.delete_env(:firecrawl, :api_key) end)
|
||||
|
||||
result =
|
||||
Firecrawl.start_agent(
|
||||
[prompt: "test", model: "spark-1-mini"],
|
||||
base_url: "http://localhost:1",
|
||||
retry: false
|
||||
)
|
||||
|
||||
assert {:error, err} = result
|
||||
refute match?(%NimbleOptions.ValidationError{}, err),
|
||||
"Expected connection error, got validation error: #{inspect(err)}"
|
||||
end
|
||||
|
||||
test "accepts string values for enum params (sitemap)" do
|
||||
Application.put_env(:firecrawl, :api_key, "test-key")
|
||||
on_exit(fn -> Application.delete_env(:firecrawl, :api_key) end)
|
||||
|
||||
result =
|
||||
Firecrawl.crawl_urls(
|
||||
[url: "https://example.com", sitemap: "skip"],
|
||||
base_url: "http://localhost:1",
|
||||
retry: false
|
||||
)
|
||||
|
||||
assert {:error, err} = result
|
||||
refute match?(%NimbleOptions.ValidationError{}, err),
|
||||
"Expected connection error, got validation error: #{inspect(err)}"
|
||||
end
|
||||
|
||||
test "parse_file returns error tuple when filename is empty" do
|
||||
Application.put_env(:firecrawl, :api_key, "test-key")
|
||||
on_exit(fn -> Application.delete_env(:firecrawl, :api_key) end)
|
||||
|
||||
assert {:error, %ArgumentError{message: msg}} =
|
||||
Firecrawl.parse_file([filename: "", data: "x"])
|
||||
|
||||
assert msg =~ "filename cannot be empty"
|
||||
end
|
||||
|
||||
test "parse_file returns error tuple when data is nil" do
|
||||
Application.put_env(:firecrawl, :api_key, "test-key")
|
||||
on_exit(fn -> Application.delete_env(:firecrawl, :api_key) end)
|
||||
|
||||
assert {:error, %ArgumentError{message: msg}} =
|
||||
Firecrawl.parse_file([filename: "doc.pdf", data: nil])
|
||||
|
||||
assert msg =~ "file data cannot be empty"
|
||||
end
|
||||
|
||||
test "parse_file rejects unknown options" do
|
||||
Application.put_env(:firecrawl, :api_key, "test-key")
|
||||
on_exit(fn -> Application.delete_env(:firecrawl, :api_key) end)
|
||||
|
||||
assert {:error, %NimbleOptions.ValidationError{message: msg}} =
|
||||
Firecrawl.parse_file(
|
||||
[filename: "doc.pdf", data: "x"],
|
||||
typo_option: true
|
||||
)
|
||||
|
||||
assert msg =~ "unknown options"
|
||||
end
|
||||
|
||||
test "non-bang returns {:error, %Firecrawl.Error{}} for API errors" do
|
||||
adapter = fn request ->
|
||||
resp = Req.Response.new(
|
||||
status: 402,
|
||||
headers: %{"content-type" => ["application/json"]},
|
||||
body: Jason.encode!(%{"success" => false, "error" => "Payment required"})
|
||||
)
|
||||
{request, resp}
|
||||
end
|
||||
|
||||
result =
|
||||
Firecrawl.scrape_and_extract_from_url(
|
||||
[url: "https://example.com"],
|
||||
api_key: "test-key",
|
||||
adapter: adapter
|
||||
)
|
||||
|
||||
assert {:error, %Firecrawl.Error{status: 402}} = result
|
||||
end
|
||||
|
||||
test "bang raises Firecrawl.Error for API errors" do
|
||||
adapter = fn request ->
|
||||
resp = Req.Response.new(
|
||||
status: 401,
|
||||
headers: %{"content-type" => ["application/json"]},
|
||||
body: Jason.encode!(%{"success" => false, "error" => "Unauthorized"})
|
||||
)
|
||||
{request, resp}
|
||||
end
|
||||
|
||||
assert_raise Firecrawl.Error, ~r/Unauthorized/, fn ->
|
||||
Firecrawl.scrape_and_extract_from_url!(
|
||||
[url: "https://example.com"],
|
||||
api_key: "test-key",
|
||||
adapter: adapter
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
test "non-bang returns {:ok, response} for successful API calls" do
|
||||
adapter = fn request ->
|
||||
resp = Req.Response.new(
|
||||
status: 200,
|
||||
headers: %{"content-type" => ["application/json"]},
|
||||
body: Jason.encode!(%{"success" => true, "data" => %{}})
|
||||
)
|
||||
{request, resp}
|
||||
end
|
||||
|
||||
result =
|
||||
Firecrawl.get_credit_usage(
|
||||
api_key: "test-key",
|
||||
adapter: adapter
|
||||
)
|
||||
|
||||
assert {:ok, %Req.Response{status: 200}} = result
|
||||
end
|
||||
|
||||
test "all expected API functions are defined with bang variants" do
|
||||
functions = Firecrawl.__info__(:functions)
|
||||
|
||||
expected = [
|
||||
{:scrape_and_extract_from_url, 0},
|
||||
{:scrape_and_extract_from_url, 1},
|
||||
{:scrape_and_extract_from_url, 2},
|
||||
{:scrape_and_extract_from_url!, 0},
|
||||
{:scrape_and_extract_from_url!, 1},
|
||||
{:scrape_and_extract_from_url!, 2},
|
||||
{:crawl_urls, 0},
|
||||
{:crawl_urls!, 0},
|
||||
{:get_credit_usage, 0},
|
||||
{:get_credit_usage!, 0},
|
||||
{:get_queue_status, 0},
|
||||
{:get_queue_status!, 0},
|
||||
{:cancel_crawl, 1},
|
||||
{:cancel_crawl!, 1},
|
||||
{:parse_file, 1},
|
||||
{:parse_file, 2},
|
||||
{:parse_file, 3},
|
||||
{:parse_file!, 1},
|
||||
{:parse_file!, 2},
|
||||
{:parse_file!, 3}
|
||||
]
|
||||
|
||||
for {name, arity} <- expected do
|
||||
assert {name, arity} in functions,
|
||||
"Expected #{name}/#{arity} to be defined in Firecrawl"
|
||||
end
|
||||
end
|
||||
end
|
||||
1
참고/firecrawl-main/apps/elixir-sdk/test/test_helper.exs
Normal file
1
참고/firecrawl-main/apps/elixir-sdk/test/test_helper.exs
Normal file
@@ -0,0 +1 @@
|
||||
ExUnit.start()
|
||||
Reference in New Issue
Block a user