diff --git a/docs/api.md b/docs/api.md
index ae54c7c..f43c7a8 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -316,6 +316,17 @@ Matches request *form data*, excluding files, using [eq](#eq) as default lookup.
 respx.post("https://example.org/", data={"foo": "bar"})
 ```
 
+### Files
+Matches files within request *form data*, using [contains](#contains) as default lookup.
+> Key: `files`  
+> Lookups: [contains](#contains), [eq](#eq)
+``` python
+respx.post("https://example.org/", files={"some_file": b"..."})
+respx.post("https://example.org/", files={"some_file": ANY})
+respx.post("https://example.org/", files={"some_file": ("filename.txt", b"...")})
+respx.post("https://example.org/", files={"some_file": ("filename.txt", ANY)})
+```
+
 ### JSON
 Matches request *json* content, using [eq](#eq) as default lookup.
 > Key: `json`  
diff --git a/respx/patterns.py b/respx/patterns.py
index 75cb815..d8b00b5 100644
--- a/respx/patterns.py
+++ b/respx/patterns.py
@@ -1,5 +1,6 @@
 import json as jsonlib
 import operator
+import pathlib
 import re
 from abc import ABC
 from enum import Enum
@@ -12,6 +13,7 @@ from typing import (
     ClassVar,
     Dict,
     List,
+    Mapping,
     Optional,
     Pattern as RegexPattern,
     Sequence,
@@ -30,8 +32,10 @@ from respx.utils import MultiItems, decode_data
 from .types import (
     URL as RawURL,
     CookieTypes,
+    FileTypes,
     HeaderTypes,
     QueryParamTypes,
+    RequestFiles,
     URLPatternTypes,
 )
 
@@ -551,6 +555,38 @@ class Data(MultiItemsMixin, Pattern):
         return data
 
 
+class Files(MultiItemsMixin, Pattern):
+    lookups = (Lookup.CONTAINS, Lookup.EQUAL)
+    key = "files"
+    value: MultiItems
+
+    def _normalize_file_value(self, value: FileTypes) -> Tuple[Any, ...]:
+        # Mimic httpx `FileField` to normalize `files` kwarg to shortest tuple style
+        if isinstance(value, tuple):
+            filename, fileobj = value[:2]
+        else:
+            try:
+                filename = pathlib.Path(str(getattr(value, "name"))).name  # noqa: B009
+            except AttributeError:
+                filename = ANY
+            fileobj = value
+
+        return filename, fileobj
+
+    def clean(self, value: RequestFiles) -> MultiItems:
+        if isinstance(value, Mapping):
+            value = list(value.items())
+
+        files = MultiItems(
+            (name, self._normalize_file_value(file_value)) for name, file_value in value
+        )
+        return files
+
+    def parse(self, request: httpx.Request) -> Any:
+        _, files = decode_data(request)
+        return files
+
+
 def M(*patterns: Pattern, **lookups: Any) -> Pattern:
     extras = None
 
diff --git a/respx/types.py b/respx/types.py
index 0ce2101..1cf3e0c 100644
--- a/respx/types.py
+++ b/respx/types.py
@@ -1,4 +1,5 @@
 from typing import (
+    IO,
     Any,
     AsyncIterable,
     Awaitable,
@@ -7,6 +8,7 @@ from typing import (
     Iterable,
     Iterator,
     List,
+    Mapping,
     Optional,
     Pattern,
     Sequence,
@@ -53,3 +55,17 @@ SideEffectTypes = Union[
     Type[Exception],
     Iterator[SideEffectListTypes],
 ]
+
+# Borrowed from HTTPX's "private" types.
+FileContent = Union[IO[bytes], bytes, str]
+FileTypes = Union[
+    # file (or bytes)
+    FileContent,
+    # (filename, file (or bytes))
+    Tuple[Optional[str], FileContent],
+    # (filename, file (or bytes), content_type)
+    Tuple[Optional[str], FileContent, Optional[str]],
+    # (filename, file (or bytes), content_type, headers)
+    Tuple[Optional[str], FileContent, Optional[str], Mapping[str, str]],
+]
+RequestFiles = Union[Mapping[str, FileTypes], Sequence[Tuple[str, FileTypes]]]

diff --git a/tests/test_api.py b/tests/test_api.py
index 597c589..ef1dddd 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -272,6 +272,16 @@ def test_data_post_body():
         assert route.called
 
 
+def test_files_post_body():
+    with respx.mock:
+        url = "https://foo.bar/"
+        file = ("file", ("filename.txt", b"...", "text/plain", {"X-Foo": "bar"}))
+        route = respx.post(url, files={"file": mock.ANY}) % 201
+        response = httpx.post(url, files=[file])
+        assert response.status_code == 201
+        assert route.called
+
+
 async def test_raising_content(client):
     async with MockRouter() as respx_mock:
         url = "https://foo.bar/"
diff --git a/tests/test_patterns.py b/tests/test_patterns.py
index f492307..dda7914 100644
--- a/tests/test_patterns.py
+++ b/tests/test_patterns.py
@@ -10,6 +10,7 @@ from respx.patterns import (
     Content,
     Cookies,
     Data,
+    Files,
     Headers,
     Host,
     Lookup,
@@ -389,6 +390,112 @@ def test_data_pattern(lookup, data, request_data, expected):
     assert bool(match) is expected
 
 
+@pytest.mark.parametrize(
+    ("lookup", "files", "request_files", "expected"),
+    [
+        (
+            Lookup.EQUAL,
+            [("file_1", b"foo..."), ("file_2", b"bar...")],
+            None,
+            True,
+        ),
+        (
+            Lookup.EQUAL,
+            {"file_1": b"foo...", "file_2": b"bar..."},
+            None,
+            True,
+        ),
+        (
+            Lookup.EQUAL,
+            {"file_1": ANY},
+            {"file_1": b"foobar..."},
+            True,
+        ),
+        (
+            Lookup.EQUAL,
+            {
+                "file_1": ("filename_1.txt", b"foo..."),
+                "file_2": ("filename_2.txt", b"bar..."),
+            },
+            None,
+            True,
+        ),
+        (
+            Lookup.EQUAL,
+            {"file_1": ("filename_1.txt", ANY)},
+            {"file_1": ("filename_1.txt", b"...")},
+            True,
+        ),
+        (
+            Lookup.EQUAL,
+            {"upload": b"foo..."},
+            {"upload": b"bar..."},  # Wrong file data
+            False,
+        ),
+        (
+            Lookup.EQUAL,
+            {
+                "file_1": ("filename_1.txt", b"foo..."),
+                "file_2": ("filename_2.txt", b"bar..."),
+            },
+            {
+                "file_1": ("filename_1.txt", b"foo..."),
+                "file_2": ("filename_2.txt", b"ham..."),  # Wrong file data
+            },
+            False,
+        ),
+        (
+            Lookup.CONTAINS,
+            {
+                "file_1": ("filename_1.txt", b"foo..."),
+            },
+            {
+                "file_1": ("filename_1.txt", b"foo..."),
+                "file_2": ("filename_2.txt", b"bar..."),
+            },
+            True,
+        ),
+        (
+            Lookup.CONTAINS,
+            {
+                "file_1": ("filename_1.txt", ANY),
+            },
+            {
+                "file_1": ("filename_1.txt", b"foo..."),
+                "file_2": ("filename_2.txt", b"bar..."),
+            },
+            True,
+        ),
+        (
+            Lookup.CONTAINS,
+            [("file_1", ANY)],
+            {
+                "file_1": ("filename_1.txt", b"foo..."),
+                "file_2": ("filename_2.txt", b"bar..."),
+            },
+            True,
+        ),
+        (
+            Lookup.CONTAINS,
+            [("file_1", b"ham...")],
+            {
+                "file_1": ("filename_1.txt", b"foo..."),
+                "file_2": ("filename_2.txt", b"bar..."),
+            },
+            False,
+        ),
+    ],
+)
+def test_files_pattern(lookup, files, request_files, expected):
+    request = httpx.Request(
+        "POST",
+        "https://foo.bar/",
+        files=request_files or files,
+    )
+    match = Files(files, lookup=lookup).match(request)
+    assert bool(match) is expected
+
+
 @pytest.mark.parametrize(
     ("lookup", "value", "json", "expected"),
     [

Add a files pattern?
As mentioned in #87, it might be of interest to allow matching a request on files being sent.

- What do we want to match on?
- Is it even possible once internal `HTTPX` request is built.

```py
route = respx.post("https://example.org/", files=?)
```

Since uploading files with `HTTPX` supports multiple arg types, it might *only* be possible to match on file names, if given. Reading a file object's content could affect `HTTPX` internals, if not handled properly, like reseting seek point etc.

Needs further investigation, [multiple files](https://github.com/encode/httpx/pull/1032/files).
tests/test_api.py::test_http_methods tests/test_api.py::test_url_match[https://foo.bar-https://foo.bar] tests/test_api.py::test_url_match[https://foo.bar/baz/-None] tests/test_api.py::test_url_match[https://foo.bar/baz/-] tests/test_api.py::test_url_match[https://foo.bar/baz/-https://foo.bar/baz/] tests/test_api.py::test_url_match[https://foo.bar/baz/-^https://foo.bar/\\w+/$] tests/test_api.py::test_url_match[https://foo.bar/baz/-pattern5] tests/test_api.py::test_url_match[https://foo.bar:443/baz/-pattern6] tests/test_api.py::test_url_match[https://foo.bar/%08-https://foo.bar/%08] tests/test_api.py::test_invalid_url_pattern tests/test_api.py::test_repeated_pattern tests/test_api.py::test_status_code tests/test_api.py::test_headers[headers0-None-expected0] tests/test_api.py::test_headers[headers1-None-expected1] tests/test_api.py::test_headers[headers2-ham/spam-expected2] tests/test_api.py::test_text_encoding[eldr\xc3\xa4v-eldr\xe4v] tests/test_api.py::test_text_encoding[\xe4pple-\xe4pple] tests/test_api.py::test_text_encoding[Geh&#xE4;usegr\xf6\xdfe-Geh&#xE4;usegr\xf6\xdfe] tests/test_api.py::test_content_variants[content-foobar-None0] tests/test_api.py::test_content_variants[content-foobar-None1] tests/test_api.py::test_content_variants[json-value2-application/json] tests/test_api.py::test_content_variants[json-value3-application/json] tests/test_api.py::test_content_variants[text-foobar-text/plain; tests/test_api.py::test_content_variants[html-<strong>foobar</strong>-text/html; tests/test_api.py::test_json_content[content0-headers0-expected_headers0] tests/test_api.py::test_json_content[content1-headers1-expected_headers1] tests/test_api.py::test_json_post_body tests/test_api.py::test_data_post_body tests/test_api.py::test_files_post_body tests/test_api.py::test_raising_content tests/test_api.py::test_callable_content tests/test_api.py::test_request_callback tests/test_api.py::test_pass_through[httpcore-route0-True] tests/test_api.py::test_pass_through[httpx-route1-True] tests/test_api.py::test_pass_through[httpcore-route2-False] tests/test_api.py::test_pass_through[httpcore-route3-True] tests/test_api.py::test_parallel_requests tests/test_api.py::test_method_case[DELETE-delete] tests/test_api.py::test_method_case[delete-delete] tests/test_api.py::test_method_case[GET-get] tests/test_api.py::test_method_case[get-get] tests/test_api.py::test_method_case[HEAD-head] tests/test_api.py::test_method_case[head-head] tests/test_api.py::test_method_case[OPTIONS-options] tests/test_api.py::test_method_case[options-options] tests/test_api.py::test_method_case[PATCH-patch] tests/test_api.py::test_method_case[patch-patch] tests/test_api.py::test_method_case[POST-post] tests/test_api.py::test_method_case[post-post] tests/test_api.py::test_method_case[PUT-put] tests/test_api.py::test_method_case[put-put] tests/test_api.py::test_pop tests/test_api.py::test_params_match[https://foo/-foo=bar-https://foo/-foo=bar0] tests/test_api.py::test_params_match[https://foo/-foo=bar-https://foo/-foo=bar1] tests/test_api.py::test_params_match[https://foo/-params2-https://foo/-call_params2] tests/test_api.py::test_params_match[https://foo/-params3-https://foo/-call_params3] tests/test_api.py::test_params_match[https://foo/-params4-https://foo/-call_params4] tests/test_api.py::test_params_match[https://foo?foo=bar-baz=qux-https://foo?foo=bar-baz=qux] tests/test_api.py::test_params_match[https://foo?foo=bar-baz=qux-https://foo?foo=bar&baz=qux-None] tests/test_api.py::test_params_match[https://foo/(\\w+)/-foo=bar-https://foo/bar/-foo=bar] tests/test_api.py::test_params_match[url8-foo=bar-https://foo/-foo=bar] tests/test_api.py::test_params_match[url9-baz=qux-https://foo?foo=bar&baz=qux-None] tests/test_api.py::test_build_url_base[None-https://foo.bar/baz/] tests/test_api.py::test_build_url_base[-https://foo.bar/baz/] tests/test_api.py::test_build_url_base[https://foo.bar-baz/] tests/test_api.py::test_build_url_base[https://foo.bar/-baz/] tests/test_api.py::test_build_url_base[https://foo.bar/-/baz/] tests/test_api.py::test_build_url_base[https://foo.bar/baz/-None] tests/test_api.py::test_build_url_base[https://foo.bar/-/(\\w+)/] tests/test_api.py::test_add tests/test_api.py::test_respond tests/test_api.py::test_async_post_content[kwargs0] tests/test_api.py::test_async_post_content[kwargs1] tests/test_api.py::test_async_post_content[kwargs2] tests/test_api.py::test_async_post_content[kwargs3] tests/test_api.py::test_async_post_content[kwargs4] tests/test_patterns.py::test_bitwise_and tests/test_patterns.py::test_bitwise_operators[GET-https://foo.bar/-True] tests/test_patterns.py::test_bitwise_operators[GET-https://foo.bar/baz/-False] tests/test_patterns.py::test_bitwise_operators[POST-https://foo.bar/-True] tests/test_patterns.py::test_bitwise_operators[POST-https://ham.spam/-True] tests/test_patterns.py::test_bitwise_operators[PATCH-https://foo.bar/-True] tests/test_patterns.py::test_bitwise_operators[PUT-https://foo.bar/-False] tests/test_patterns.py::test_match_context tests/test_patterns.py::test_noop_pattern tests/test_patterns.py::test_m_pattern[kwargs0-https://foo.bar/-True] tests/test_patterns.py::test_m_pattern[kwargs1-https://foo.bar/?x=y-False] tests/test_patterns.py::test_m_pattern[kwargs2-https://foo.bar/?x=y-True] tests/test_patterns.py::test_method_pattern[Lookup.EQUAL-GET-True] tests/test_patterns.py::test_method_pattern[Lookup.EQUAL-get-True] tests/test_patterns.py::test_method_pattern[Lookup.EQUAL-POST-False] tests/test_patterns.py::test_method_pattern[Lookup.IN-value3-True] tests/test_patterns.py::test_method_pattern[Lookup.IN-value4-False] tests/test_patterns.py::test_headers_pattern[Lookup.CONTAINS-headers0-request_headers0-True] tests/test_patterns.py::test_headers_pattern[Lookup.CONTAINS-headers1--False] tests/test_patterns.py::test_headers_pattern_hash tests/test_patterns.py::test_cookies_pattern[Lookup.CONTAINS-cookies0-request_cookies0-True] tests/test_patterns.py::test_cookies_pattern[Lookup.CONTAINS-cookies1-request_cookies1-False] tests/test_patterns.py::test_cookies_pattern[Lookup.EQUAL-cookies2-request_cookies2-True] tests/test_patterns.py::test_cookies_pattern[Lookup.EQUAL-cookies3-request_cookies3-True] tests/test_patterns.py::test_cookies_pattern[Lookup.EQUAL-cookies4-request_cookies4-True] tests/test_patterns.py::test_cookies_pattern[Lookup.EQUAL-cookies5-None-True] tests/test_patterns.py::test_cookies_pattern[Lookup.EQUAL-cookies6-request_cookies6-False] tests/test_patterns.py::test_cookies_pattern__hash tests/test_patterns.py::test_scheme_pattern[Lookup.EQUAL-https-True] tests/test_patterns.py::test_scheme_pattern[Lookup.EQUAL-HTTPS-True] tests/test_patterns.py::test_scheme_pattern[Lookup.EQUAL-http-False] tests/test_patterns.py::test_scheme_pattern[Lookup.IN-scheme3-True] tests/test_patterns.py::test_host_pattern[Lookup.EQUAL-foo.bar-True] tests/test_patterns.py::test_host_pattern[Lookup.EQUAL-ham.spam-False] tests/test_patterns.py::test_host_pattern[Lookup.REGEX-.+\\.bar-True] tests/test_patterns.py::test_port_pattern[Lookup.EQUAL-443-https://foo.bar/-True] tests/test_patterns.py::test_port_pattern[Lookup.EQUAL-80-https://foo.bar/-False] tests/test_patterns.py::test_port_pattern[Lookup.EQUAL-80-http://foo.bar/-True] tests/test_patterns.py::test_port_pattern[Lookup.EQUAL-8080-https://foo.bar:8080/baz/-True] tests/test_patterns.py::test_port_pattern[Lookup.EQUAL-8080-https://foo.bar/baz/-False] tests/test_patterns.py::test_port_pattern[Lookup.EQUAL-22-//foo.bar:22/baz/-True] tests/test_patterns.py::test_port_pattern[Lookup.EQUAL-None-//foo.bar/-True] tests/test_patterns.py::test_port_pattern[Lookup.IN-port7-http://foo.bar/-True] tests/test_patterns.py::test_port_pattern[Lookup.IN-port8-https://foo.bar/-True] tests/test_patterns.py::test_port_pattern[Lookup.IN-port9-https://foo.bar:8080/-False] tests/test_patterns.py::test_path_pattern tests/test_patterns.py::test_params_pattern[Lookup.CONTAINS--https://foo.bar/-True] tests/test_patterns.py::test_params_pattern[Lookup.CONTAINS-x=1-https://foo.bar/?x=1-True] tests/test_patterns.py::test_params_pattern[Lookup.CONTAINS-x=-https://foo.bar/?x=1-False] tests/test_patterns.py::test_params_pattern[Lookup.CONTAINS-x=-https://foo.bar/?x=-True] tests/test_patterns.py::test_params_pattern[Lookup.CONTAINS-y=2-https://foo.bar/?x=1-False] tests/test_patterns.py::test_params_pattern[Lookup.CONTAINS-params5-https://foo.bar/?x=1-True] tests/test_patterns.py::test_params_pattern[Lookup.CONTAINS-params6-https://foo.bar/?x=1-True] tests/test_patterns.py::test_params_pattern[Lookup.CONTAINS-params7-https://foo.bar/?x=1-False] tests/test_patterns.py::test_params_pattern[Lookup.CONTAINS-params8-https://foo.bar/?x=1&y=2-True] tests/test_patterns.py::test_params_pattern[Lookup.CONTAINS-params9-https://foo.bar/?x=1-False] tests/test_patterns.py::test_params_pattern[Lookup.CONTAINS-params10-https://foo.bar/?x=1&x=2-True] tests/test_patterns.py::test_params_pattern[Lookup.CONTAINS-params11-https://foo.bar/?x=2&x=3-False] tests/test_patterns.py::test_params_pattern[Lookup.CONTAINS-x=1&y=2-https://foo.bar/?x=1-False] tests/test_patterns.py::test_params_pattern[Lookup.EQUAL--https://foo.bar/-True] tests/test_patterns.py::test_params_pattern[Lookup.EQUAL-x-https://foo.bar/?x-True] tests/test_patterns.py::test_params_pattern[Lookup.EQUAL-x=-https://foo.bar/?x=-True] tests/test_patterns.py::test_params_pattern[Lookup.EQUAL-x=1-https://foo.bar/?x=1-True] tests/test_patterns.py::test_params_pattern[Lookup.EQUAL-y=2-https://foo.bar/?x=1-False] tests/test_patterns.py::test_params_pattern[Lookup.EQUAL-params18-https://foo.bar/?x=1-True] tests/test_patterns.py::test_params_pattern[Lookup.EQUAL-params19-https://foo.bar/?x=1-False] tests/test_patterns.py::test_params_pattern[Lookup.EQUAL-params20-https://foo.bar/?x=1-False] tests/test_patterns.py::test_params_pattern[Lookup.EQUAL-params21-https://foo.bar/-True] tests/test_patterns.py::test_params_pattern[Lookup.EQUAL-x=1&y=2-https://foo.bar/?x=1-False] tests/test_patterns.py::test_params_pattern[Lookup.EQUAL-y=2&x=1-https://foo.bar/?x=1&y=2-True] tests/test_patterns.py::test_params_pattern[Lookup.EQUAL-y=3&x=2&x=1-https://foo.bar/?x=1&x=2&y=3-False] tests/test_patterns.py::test_params_pattern[Lookup.EQUAL-y=3&x=1&x=2-https://foo.bar/?x=1&x=2&y=3-True] tests/test_patterns.py::test_params_pattern[Lookup.CONTAINS-x=2&x=1-https://foo.bar/?x=1&x=2&y=3-False] tests/test_patterns.py::test_params_pattern[Lookup.CONTAINS-x=1&x=2-https://foo.bar/?x=1&x=2&x=3-False] tests/test_patterns.py::test_params_pattern[Lookup.CONTAINS-x=1&x=2-https://foo.bar/?x=1&x=2&y=3-True] tests/test_patterns.py::test_params_pattern_hash tests/test_patterns.py::test_url_pattern[Lookup.REGEX-https?://a.b/(?P<c>\\w+)/-context0-http://a.b/c/-True] tests/test_patterns.py::test_url_pattern[Lookup.REGEX-^https://a.b/.+$-context1-https://a.b/c/-True] tests/test_patterns.py::test_url_pattern[Lookup.REGEX-https://a.b/c/-context2-https://x.y/c/-False] tests/test_patterns.py::test_url_pattern[Lookup.EQUAL-https://a.b/c/-context3-https://a.b/c/-True] tests/test_patterns.py::test_url_pattern[Lookup.EQUAL-https://a.b/x/-context4-https://a.b/c/-False] tests/test_patterns.py::test_url_pattern[Lookup.EQUAL-https://a.b?x=y-context5-https://a.b/?x=y-True] tests/test_patterns.py::test_url_pattern[Lookup.EQUAL-https://a.b/?x=y-context6-https://a.b?x=y-True] tests/test_patterns.py::test_url_pattern[Lookup.STARTS_WITH-https://a.b/b-context7-https://a.b/baz/-True] tests/test_patterns.py::test_url_pattern[Lookup.STARTS_WITH-http://a.b/baz/-context8-https://a.b/baz/-False] tests/test_patterns.py::test_url_pattern[Lookup.EQUAL-value9-context9-https://[FE80::1]-True] tests/test_patterns.py::test_url_pattern_invalid tests/test_patterns.py::test_url_pattern_hash tests/test_patterns.py::test_content_pattern[Lookup.EQUAL-foobar-True0] tests/test_patterns.py::test_content_pattern[Lookup.EQUAL-foobar-True1] tests/test_patterns.py::test_content_pattern[Lookup.CONTAINS-bar-True0] tests/test_patterns.py::test_content_pattern[Lookup.CONTAINS-bar-True1] tests/test_patterns.py::test_content_pattern[Lookup.CONTAINS-baz-False] tests/test_patterns.py::test_data_pattern[Lookup.EQUAL-data0-None-True] tests/test_patterns.py::test_data_pattern[Lookup.EQUAL-data1-request_data1-True] tests/test_patterns.py::test_data_pattern[Lookup.EQUAL-data2-None-True] tests/test_patterns.py::test_data_pattern[Lookup.EQUAL-data3-None-True] tests/test_patterns.py::test_data_pattern[Lookup.EQUAL-data4-request_data4-False] tests/test_patterns.py::test_data_pattern[Lookup.EQUAL-data5-request_data5-False] tests/test_patterns.py::test_data_pattern[Lookup.CONTAINS-data6-request_data6-True] tests/test_patterns.py::test_files_pattern[Lookup.EQUAL-files0-None-True] tests/test_patterns.py::test_files_pattern[Lookup.EQUAL-files1-None-True] tests/test_patterns.py::test_files_pattern[Lookup.EQUAL-files2-request_files2-True] tests/test_patterns.py::test_files_pattern[Lookup.EQUAL-files3-None-True] tests/test_patterns.py::test_files_pattern[Lookup.EQUAL-files4-request_files4-True] tests/test_patterns.py::test_files_pattern[Lookup.EQUAL-files5-request_files5-False] tests/test_patterns.py::test_files_pattern[Lookup.EQUAL-files6-request_files6-False] tests/test_patterns.py::test_files_pattern[Lookup.CONTAINS-files7-request_files7-True] tests/test_patterns.py::test_files_pattern[Lookup.CONTAINS-files8-request_files8-True] tests/test_patterns.py::test_files_pattern[Lookup.CONTAINS-files9-request_files9-True] tests/test_patterns.py::test_files_pattern[Lookup.CONTAINS-files10-request_files10-False] tests/test_patterns.py::test_json_pattern[Lookup.EQUAL-value0-json0-True] tests/test_patterns.py::test_json_pattern[Lookup.EQUAL-value1-json1-False] tests/test_patterns.py::test_json_pattern[Lookup.EQUAL-value2-json2-True] tests/test_patterns.py::test_json_pattern[Lookup.EQUAL-value3-json3-False] tests/test_patterns.py::test_json_pattern[Lookup.EQUAL-json-string-json-string-True] tests/test_patterns.py::test_json_pattern_path[json0-foo__bar-baz-True] tests/test_patterns.py::test_json_pattern_path[json1-x-value1-True] tests/test_patterns.py::test_json_pattern_path[json2-ham__1__egg-yolk-True] tests/test_patterns.py::test_json_pattern_path[json3-0__name-jonas-True] tests/test_patterns.py::test_json_pattern_path[json4-pk-123-True] tests/test_patterns.py::test_json_pattern_path[json5-foo__ham-spam-False] tests/test_patterns.py::test_json_pattern_path[json6-1__name-lundberg-False] tests/test_patterns.py::test_invalid_pattern tests/test_patterns.py::test_iter_pattern tests/test_patterns.py::test_parse_url_patterns tests/test_patterns.py::test_merge_patterns tests/test_patterns.py::test_unique_pattern_key