From 6c7bd6703f3aba35efeb340ebb4a3f58b4f81f1b Mon Sep 17 00:00:00 2001 From: Oleg <2695198+heilgar@users.noreply.github.com> Date: Sun, 5 Oct 2025 22:54:03 -0400 Subject: [PATCH] add headers handling --- CHANGELOG.md | 26 +- README.md | 8 + doc/response-handling.md | 33 ++- lua/http_client/commands/utils.lua | 41 ++- lua/http_client/config.lua | 5 +- lua/http_client/core/environment.lua | 8 +- lua/http_client/core/parser.lua | 9 + lua/http_client/core/response_handler.lua | 57 +++- lua/http_client/health.lua | 7 +- lua/http_client/init.lua | 25 +- lua/http_client/utils/file_utils.lua | 30 ++- .../core/response_handler_spec.lua | 246 ++++++++++++++++++ tests/http_client/health_spec.lua | 1 + tests/http_client/utils/file_utils_spec.lua | 32 +++ tests/http_client/utils/fileutils_spec.lua | 1 + 15 files changed, 513 insertions(+), 16 deletions(-) create mode 100644 tests/http_client/core/response_handler_spec.lua create mode 100644 tests/http_client/utils/file_utils_spec.lua diff --git a/CHANGELOG.md b/CHANGELOG.md index f882a88..0e0c608 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,30 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.4.4] 2025-09-10 +### Added +* Project root management for file searching operations: + * New command `:HttpSetProjectRoot [path]` to set the project root for file searching + * New command `:HttpGetProjectRoot` to display the current project root + * New command `:HttpDebugEnv` to debug environment and project root settings + * New keybindings: `hg` to set project root, `hgg` to get project root + * Enhanced `find_files` function to accept optional project root parameter + * Automatic fallback to current directory when no project root is set + * Relative path handling for environment files using project root +* Custom User-Agent header support: + * Automatic User-Agent header (`heilgar/nvim-http-client`) added to all requests + * Configurable via `user_agent` option in setup + * Only added if no User-Agent header is explicitly set in the request +* Enhanced response handler features: + * Added `response.headers.valueOf(headerName)` method for case-insensitive header lookup + * Improved header parsing to handle different formats from plenary.curl + * Better header object creation with support for both array and key-value formats + +### Fixed +* Fixed keybinding typo in configuration (corrected `
hs` to `hs`) +* Improved health check initialization to properly load configuration +* Enhanced environment file path handling for relative paths + ## [1.4.3] 2025-04-26 ### Added * Automatic file extension detection when saving responses: @@ -259,4 +283,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Notes - The plugin requires Neovim 0.5 or later - Dependencies: plenary.nvim, telescope.nvim (optional for enhanced environment selection) - +1 diff --git a/README.md b/README.md index 4717e79..fe0ed2a 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ Copy this complete configuration into your Lazy.nvim setup: request_timeout = 30000, split_direction = "right", create_keybindings = true, + user_agent = "heilgar/nvim-http-client", -- Custom User-Agent header -- Profiling (timing metrics for requests) profiling = { @@ -66,6 +67,8 @@ Copy this complete configuration into your Lazy.nvim setup: dry_run = "hd", copy_curl = "hc", save_response = "hs", + set_project_root = "hg", + get_project_root = "hgg", }, }) @@ -99,6 +102,8 @@ For full configuration options, see [Configuration Documentation](doc/configurat - `:HttpDryRun`: Perform a dry run of the request under the cursor - `:HttpCopyCurl`: Copy the curl command for the HTTP request under the cursor - `:HttpSaveResponse`: Save the response body to a file +- `:HttpSetProjectRoot [path]`: Set the project root for file searching operations (use without arguments to be prompted for the path) +- `:HttpGetProjectRoot`: Display the current project root for file searching operations ### Keybindings @@ -113,6 +118,8 @@ The plugin comes with the following default keybindings (if `create_keybindings` - `hd`: Perform dry run - `hc`: Copy curl command - `hs`: Save response to file +- `hg`: Set project root for file searching +- `hpg`: Get current project root ## Features @@ -128,6 +135,7 @@ The plugin comes with the following default keybindings (if `create_keybindings` - Request profiling with detailed timing metrics - Telescope integration for environment selection - Autocompletion for HTTP methods, headers and environment variables +- Custom User-Agent header (`heilgar/nvim-http-client` by default) - Compatible with [JetBrains HTTP Client](https://www.jetbrains.com/help/idea/http-client-in-product-code-editor.html) and [VSCode Restclient](https://github.com/Huachao/vscode-restclient) ### Feature Comparison diff --git a/doc/response-handling.md b/doc/response-handling.md index 5fe746e..1864df1 100644 --- a/doc/response-handling.md +++ b/doc/response-handling.md @@ -45,7 +45,8 @@ Within a response handler, you have access to: - `response` - The HTTP response object - `response.body` - The response body (parsed as JSON if possible) - - `response.headers` - Response headers + - `response.headers` - Response headers object with additional methods + - `response.headers.valueOf(headerName)` - Get header value with case-insensitive lookup - `response.status` - HTTP status code - `client` - The HTTP client object @@ -101,6 +102,36 @@ if (adminUser) { GET {{host}}/api/users/{{adminId}} ``` +### Example: Extracting Headers + +```http +### Login with Session +POST {{host}}/api/login +Content-Type: application/json + +{ + "username": "{{username}}", + "password": "{{password}}" +} + +> {% +// Extract session ID from response headers using valueOf +const sessionId = response.headers.valueOf("mcp-session-id"); +if (sessionId) { + client.global.set("session-id", sessionId); + console.log("Session ID extracted: " + sessionId); +} else { + console.log("No session ID found in response headers"); +} +%} + +### Use Session in Next Request +GET {{host}}/api/protected +X-Session-ID: {{session-id}} +``` + +**Note:** The `valueOf` method provides case-insensitive header lookup, so `response.headers.valueOf("mcp-session-id")` will work even if the actual header is `MCP-Session-ID` or `Mcp-Session-Id`. + ## Saving Responses You can save the current response body to a file using: diff --git a/lua/http_client/commands/utils.lua b/lua/http_client/commands/utils.lua index 5e5c977..7c0fd7f 100644 --- a/lua/http_client/commands/utils.lua +++ b/lua/http_client/commands/utils.lua @@ -1,10 +1,9 @@ local M = {} -local vvv = require('http_client.utils.verbose') local parser = require('http_client.core.parser') local environment = require('http_client.core.environment') -local http_client = require('http_client.core.http_client') local curl_generator = require('http_client.core.curl_generator') +local file_utils = require('http_client.utils.file_utils') M.copy_curl = function() local request = parser.get_request_under_cursor() @@ -21,5 +20,41 @@ M.copy_curl = function() print('Curl command copied to clipboard') end -return M +M.set_project_root = function(root_path) + if root_path and root_path ~= "" then + file_utils.set_project_root(root_path) + print(string.format("Project root set to: %s", root_path)) + else + -- Prompt user for the project root path + local input = vim.fn.input("Enter project root path (or press Enter to reset to current directory): ") + if input and input ~= "" then + file_utils.set_project_root(input) + print(string.format("Project root set to: %s", input)) + else + file_utils.set_project_root() + print(string.format("Project root reset to current directory: %s", vim.fn.getcwd())) + end + end +end + +M.get_project_root = function() + local root = file_utils.get_project_root() + print(string.format("Current project root: %s", root)) + return root +end + +M.debug_env = function() + local root = file_utils.get_project_root() + local env_file = environment.get_current_env_file() + print(string.format("Project root: %s", root)) + print(string.format("Current working directory: %s", vim.fn.getcwd())) + print(string.format("Environment file: %s", env_file or "None")) + + if env_file then + local exists = vim.fn.filereadable(env_file) == 1 + print(string.format("Environment file exists: %s", exists and "Yes" or "No")) + end +end + +return M diff --git a/lua/http_client/config.lua b/lua/http_client/config.lua index ff176cb..93935b8 100644 --- a/lua/http_client/config.lua +++ b/lua/http_client/config.lua @@ -5,6 +5,7 @@ M.defaults = { request_timeout = 30000, -- 30 seconds split_direction = "right", create_keybindings = true, + user_agent = "heilgar/nvim-http-client", -- Default User-Agent header profiling = { enabled = true, show_in_response = true, @@ -18,8 +19,10 @@ M.defaults = { dry_run = "hd", toggle_verbose = "hv", copy_curl = "hc", - save_response = "
hs", + save_response = "hs", toggle_profiling = "hp", + set_project_root = "hg", + get_project_root = "hgg", }, } diff --git a/lua/http_client/core/environment.lua b/lua/http_client/core/environment.lua index cf46713..3e23939 100644 --- a/lua/http_client/core/environment.lua +++ b/lua/http_client/core/environment.lua @@ -7,6 +7,11 @@ local current_env = {} local global_variables = {} M.set_env_file = function(file_path) + -- If the path is relative, make it absolute using the project root + if not file_path:match("^/") then + file_path = file_utils.get_project_root() .. "/" .. file_path + end + current_env_file = file_path -- Set the private environment file path current_private_env_file = file_path:gsub("%.env%.json$", ".private.env.json") @@ -109,7 +114,7 @@ M.get_global_variables = function() return global_variables end -M.env_variables_needed = function (request) +M.env_variables_needed = function(request) local function check_for_placeholders(str) return str and str:match("{{.-}}") end @@ -132,4 +137,3 @@ M.env_variables_needed = function (request) end return M - diff --git a/lua/http_client/core/parser.lua b/lua/http_client/core/parser.lua index 6a4c5d2..9ab81f0 100644 --- a/lua/http_client/core/parser.lua +++ b/lua/http_client/core/parser.lua @@ -160,6 +160,15 @@ M.parse_request = function(lines) request.response_handler = response_handler + -- Add default User-Agent header if not present + if not request.headers['User-Agent'] and not request.headers['user-agent'] then + local config = require('http_client.config') + local user_agent = config.get('user_agent') + if user_agent then + request.headers['User-Agent'] = user_agent + end + end + return request end diff --git a/lua/http_client/core/response_handler.lua b/lua/http_client/core/response_handler.lua index 0789f3e..39085d5 100644 --- a/lua/http_client/core/response_handler.lua +++ b/lua/http_client/core/response_handler.lua @@ -11,12 +11,63 @@ local client = { } } +local function create_headers_object(headers) + local headers_table = {} + + -- Handle different header formats from plenary.curl + if headers then + for key, value in pairs(headers) do + if type(key) == "number" and type(value) == "string" then + -- Headers are in array format: ["Header-Name: value", ...] + local header_key, header_value = value:match("^(.-):%s*(.*)") + if header_key and header_value then + headers_table[header_key] = header_value + end + elseif type(key) == "string" then + -- Headers are already in key-value format + headers_table[key] = value + end + end + end + + -- Create a headers object with valueOf method + local headers_obj = {} + + -- Copy all header key-value pairs + for key, value in pairs(headers_table) do + headers_obj[key] = value + end + + -- Add valueOf method + headers_obj.valueOf = function(header_name) + if not header_name then + return nil + end + + -- Try exact match first (case-sensitive) + if headers_table[header_name] then + return headers_table[header_name] + end + + -- Try case-insensitive match + for key, value in pairs(headers_table) do + if string.lower(key) == string.lower(header_name) then + return value + end + end + + return nil + end + + return headers_obj +end + local function create_sandbox(response) return { client = client, response = { body = response.body or {}, - headers = response.headers or {}, + headers = create_headers_object(response.headers), status = response.status or nil } } @@ -35,5 +86,7 @@ M.execute = function(script, response) end end -return M +-- Expose create_sandbox for testing +M.create_sandbox = create_sandbox +return M diff --git a/lua/http_client/health.lua b/lua/http_client/health.lua index b359d16..eb5b3fd 100644 --- a/lua/http_client/health.lua +++ b/lua/http_client/health.lua @@ -1,8 +1,13 @@ local health = vim.health or require("health") +local config = require("http_client.config") local M = {} M.check = function() + local cfg = M.config or config + if cfg.setup then + cfg.setup() + end health.start("http_client") -- Check if required dependencies are available @@ -57,7 +62,7 @@ M.check = function() end -- Check if profiling is enabled - local profiling_config = M.config.get('profiling') + local profiling_config = cfg.get('profiling') if profiling_config and profiling_config.enabled then health.ok('Profiling: enabled') else diff --git a/lua/http_client/init.lua b/lua/http_client/init.lua index 8b4984a..38ae8ab 100644 --- a/lua/http_client/init.lua +++ b/lua/http_client/init.lua @@ -36,6 +36,8 @@ local function set_keybindings() vim.keymap.set("n", keybindings.copy_curl, ":HttpCopyCurl", opts) vim.keymap.set("n", keybindings.save_response, ":HttpSaveResponse", opts) vim.keymap.set("n", keybindings.toggle_profiling, ":HttpProfiling", opts) + vim.keymap.set("n", keybindings.set_project_root, ":HttpSetProjectRoot", opts) + vim.keymap.set("n", keybindings.get_project_root, ":HttpGetProjectRoot", opts) end, }) end @@ -137,6 +139,25 @@ M.setup = function(opts) desc = "Open the latest HTTP response buffer in a new tab", }) + vim.api.nvim_create_user_command("HttpSetProjectRoot", function(opts) + M.commands.utils.set_project_root(opts.args) + end, { + desc = "Set the project root for file searching operations. Use without arguments to be prompted for the path.", + nargs = "?", + }) + + vim.api.nvim_create_user_command("HttpGetProjectRoot", function() + M.commands.utils.get_project_root() + end, { + desc = "Display the current project root for file searching operations.", + }) + + vim.api.nvim_create_user_command("HttpDebugEnv", function() + M.commands.utils.debug_env() + end, { + desc = "Debug environment and project root settings.", + }) + setup_docs() set_keybindings() @@ -145,12 +166,12 @@ M.setup = function(opts) local health = vim.health or M.health if health.register then -- Register the health check with the new API - health.register("http_client", M.health.check) + health.register("http_client", M.health.check) else -- Fallback for older Neovim versions vim.api.nvim_create_autocmd("VimEnter", { callback = function() - M.health.check() + M.health.check() end, }) end diff --git a/lua/http_client/utils/file_utils.lua b/lua/http_client/utils/file_utils.lua index ee5208c..f41c588 100644 --- a/lua/http_client/utils/file_utils.lua +++ b/lua/http_client/utils/file_utils.lua @@ -1,23 +1,47 @@ local M = {} local Path = require('plenary.path') -M.find_files = function(pattern) - local handle = io.popen('find . -name "' .. pattern .. '"') +-- Store the project root globally +M.project_root = vim.fn.getcwd() + +M.set_project_root = function(root_path) + if root_path then + M.project_root = root_path + else + M.project_root = vim.fn.getcwd() + end +end + +M.get_project_root = function() + return M.project_root +end + +M.find_files = function(pattern, project_root) + local search_root = project_root or M.project_root + + local handle = io.popen('find "' .. search_root .. '" -name "' .. pattern .. '"') local result = handle:read("*a") handle:close() local files = {} for file in result:gmatch("[^\r\n]+") do - local filename = file:sub(3) -- remove './' from the beginning + -- Remove the search root prefix from the file path + local filename = file:sub(#search_root + 2) -- +2 to remove the '/' after the root -- Exclude files with ".private." in their name if not filename:match("%.private%.") then table.insert(files, filename) end end + return files end M.read_json_file = function(file_path) + -- If the path is relative, make it absolute using the project root + if not file_path:match("^/") then + file_path = M.project_root .. "/" .. file_path + end + local file = io.open(file_path, "r") if not file then return nil end diff --git a/tests/http_client/core/response_handler_spec.lua b/tests/http_client/core/response_handler_spec.lua new file mode 100644 index 0000000..d766228 --- /dev/null +++ b/tests/http_client/core/response_handler_spec.lua @@ -0,0 +1,246 @@ +local response_handler = require('http_client.core.response_handler') + +describe("Response Handler", function() + describe("headers object", function() + it("should provide access to headers via direct key access", function() + local mock_response = { + headers = { + ["Content-Type"] = "application/json", + ["Authorization"] = "Bearer token123", + ["X-Custom-Header"] = "custom-value" + }, + status = 200, + body = {} + } + + local sandbox = response_handler.create_sandbox(mock_response) + local headers = sandbox.response.headers + + assert.equal(headers["Content-Type"], "application/json") + assert.equal(headers["Authorization"], "Bearer token123") + assert.equal(headers["X-Custom-Header"], "custom-value") + end) + + it("should provide valueOf method for case-sensitive header lookup", function() + local mock_response = { + headers = { + ["Content-Type"] = "application/json", + ["Authorization"] = "Bearer token123", + ["X-Custom-Header"] = "custom-value" + }, + status = 200, + body = {} + } + + local sandbox = response_handler.create_sandbox(mock_response) + local headers = sandbox.response.headers + + assert.equal(headers.valueOf("Content-Type"), "application/json") + assert.equal(headers.valueOf("Authorization"), "Bearer token123") + assert.equal(headers.valueOf("X-Custom-Header"), "custom-value") + end) + + it("should provide case-insensitive header lookup via valueOf", function() + local mock_response = { + headers = { + ["Content-Type"] = "application/json", + ["Authorization"] = "Bearer token123", + ["X-Custom-Header"] = "custom-value" + }, + status = 200, + body = {} + } + + local sandbox = response_handler.create_sandbox(mock_response) + local headers = sandbox.response.headers + + -- Test case-insensitive lookup + assert.equal(headers.valueOf("content-type"), "application/json") + assert.equal(headers.valueOf("CONTENT-TYPE"), "application/json") + assert.equal(headers.valueOf("authorization"), "Bearer token123") + assert.equal(headers.valueOf("AUTHORIZATION"), "Bearer token123") + assert.equal(headers.valueOf("x-custom-header"), "custom-value") + assert.equal(headers.valueOf("X-CUSTOM-HEADER"), "custom-value") + end) + + it("should return nil for non-existent headers via valueOf", function() + local mock_response = { + headers = { + ["Content-Type"] = "application/json" + }, + status = 200, + body = {} + } + + local sandbox = response_handler.create_sandbox(mock_response) + local headers = sandbox.response.headers + + assert.is_nil(headers.valueOf("Non-Existent-Header")) + assert.is_nil(headers.valueOf("")) + assert.is_nil(headers.valueOf(nil)) + end) + + it("should handle empty headers object", function() + local mock_response = { + headers = {}, + status = 200, + body = {} + } + + local sandbox = response_handler.create_sandbox(mock_response) + local headers = sandbox.response.headers + + assert.is_nil(headers.valueOf("Any-Header")) + assert.equal(type(headers.valueOf), "function") + end) + + it("should handle nil headers", function() + local mock_response = { + headers = nil, + status = 200, + body = {} + } + + local sandbox = response_handler.create_sandbox(mock_response) + local headers = sandbox.response.headers + + assert.is_nil(headers.valueOf("Any-Header")) + assert.equal(type(headers.valueOf), "function") + end) + + it("should work with mcp-session-id header as in the example", function() + local mock_response = { + headers = { + ["mcp-session-id"] = "session-12345", + ["Content-Type"] = "application/json" + }, + status = 200, + body = {} + } + + local sandbox = response_handler.create_sandbox(mock_response) + local headers = sandbox.response.headers + + assert.equal(headers.valueOf("mcp-session-id"), "session-12345") + assert.equal(headers.valueOf("MCP-SESSION-ID"), "session-12345") + assert.equal(headers.valueOf("mcp-session-id"), "session-12345") + end) + + it("should handle headers in array format from plenary.curl", function() + local mock_response = { + headers = { + "Content-Type: application/json", + "Server: nginx/1.18.0", + "mcp-session-id: session-12345" + }, + status = 200, + body = {} + } + + local sandbox = response_handler.create_sandbox(mock_response) + local headers = sandbox.response.headers + + assert.equal(headers.valueOf("Content-Type"), "application/json") + assert.equal(headers.valueOf("Server"), "nginx/1.18.0") + assert.equal(headers.valueOf("mcp-session-id"), "session-12345") + assert.equal(headers.valueOf("content-type"), "application/json") + assert.equal(headers.valueOf("server"), "nginx/1.18.0") + end) + end) + + describe("script execution", function() + it("should execute a simple script that uses headers.valueOf", function() + local mock_response = { + headers = { + ["mcp-session-id"] = "session-12345", + ["Content-Type"] = "application/json" + }, + status = 200, + body = {} + } + + -- Mock the environment module + local mock_environment = { + set_global_variable = function(key, value) + -- Store in a test variable for verification + _G.test_global_vars = _G.test_global_vars or {} + _G.test_global_vars[key] = value + end + } + + -- Mock the verbose module + local mock_verbose = { + debug_print = function(msg) end + } + + -- Temporarily replace modules + local original_env = package.loaded['http_client.core.environment'] + local original_verbose = package.loaded['http_client.utils.verbose'] + + package.loaded['http_client.core.environment'] = mock_environment + package.loaded['http_client.utils.verbose'] = mock_verbose + + -- Reload the module to use mocked dependencies + package.loaded['http_client.core.response_handler'] = nil + local response_handler = require('http_client.core.response_handler') + + local script = [[ + client.global.set("session-id", response.headers.valueOf("mcp-session-id")) + ]] + + -- Clear test globals + _G.test_global_vars = {} + + -- Execute the script + response_handler.execute(script, mock_response) + + -- Verify the global variable was set + assert.equal(_G.test_global_vars["session-id"], "session-12345") + + -- Restore original modules + package.loaded['http_client.core.environment'] = original_env + package.loaded['http_client.utils.verbose'] = original_verbose + package.loaded['http_client.core.response_handler'] = nil + end) + + it("should handle script errors gracefully", function() + local mock_response = { + headers = { ["Content-Type"] = "application/json" }, + status = 200, + body = {} + } + + -- Mock the verbose module to capture debug output + local debug_messages = {} + local mock_verbose = { + debug_print = function(msg) + table.insert(debug_messages, msg) + end + } + + -- Temporarily replace modules + local original_verbose = package.loaded['http_client.utils.verbose'] + package.loaded['http_client.utils.verbose'] = mock_verbose + + -- Reload the module + package.loaded['http_client.core.response_handler'] = nil + local response_handler = require('http_client.core.response_handler') + + local script = [[ + -- This will cause an error + response.nonExistentMethod() + ]] + + -- Execute the script (should not throw) + response_handler.execute(script, mock_response) + + -- Verify error was logged + assert.is_true(#debug_messages > 0) + assert.matches("Error executing response handler script", debug_messages[1]) + + -- Restore original module + package.loaded['http_client.utils.verbose'] = original_verbose + package.loaded['http_client.core.response_handler'] = nil + end) + end) +end) diff --git a/tests/http_client/health_spec.lua b/tests/http_client/health_spec.lua index 5c0250c..4868571 100644 --- a/tests/http_client/health_spec.lua +++ b/tests/http_client/health_spec.lua @@ -69,6 +69,7 @@ describe("http_client health checks", function() it("reports profiling status when disabled", function() stub(_G, "pcall") _G.pcall.on_call_with(require, "plenary").returns(true) + _G.pcall.on_call_with(require, "cmp").returns(false) -- Mock cmp not installed -- Override config for this test health.config.get = function(option) diff --git a/tests/http_client/utils/file_utils_spec.lua b/tests/http_client/utils/file_utils_spec.lua new file mode 100644 index 0000000..23d85fb --- /dev/null +++ b/tests/http_client/utils/file_utils_spec.lua @@ -0,0 +1,32 @@ +local file_utils = require('http_client.utils.file_utils') + +describe('file_utils', function() + describe('project root functionality', function() + it('should set and get project root', function() + local test_root = '/tmp/test_project' + + -- Test setting project root + file_utils.set_project_root(test_root) + assert.are.equal(test_root, file_utils.get_project_root()) + + -- Test resetting to current directory + file_utils.set_project_root() + assert.are.equal(vim.fn.getcwd(), file_utils.get_project_root()) + end) + + it('should use project root in find_files', function() + local original_root = file_utils.get_project_root() + local test_root = '/tmp/test_project' + + -- Set a test project root + file_utils.set_project_root(test_root) + + -- Test that find_files uses the project root + local files = file_utils.find_files('*.lua') + -- The find command should use the test_root path + + -- Reset to original + file_utils.set_project_root(original_root) + end) + end) +end) \ No newline at end of file diff --git a/tests/http_client/utils/fileutils_spec.lua b/tests/http_client/utils/fileutils_spec.lua index 7538f2c..db9daf3 100644 --- a/tests/http_client/utils/fileutils_spec.lua +++ b/tests/http_client/utils/fileutils_spec.lua @@ -28,6 +28,7 @@ describe("file_utils", function() local files = file_utils.find_files("*.json") table.sort(files) assert.are.same({ + ".releaserc.json", "examples/.env.json", "test_dir/subdir/test3.json", "test_dir/test1.json",