namespace NpgsqlRestClient.Testing; /// Kind of a parsed test step. public enum TestStepKind { /// A SQL statement (or DO block) executed on the test connection. Sql, /// An embedded HTTP request (a /* ... */ block whose first line is a request line). Http, /// An include line (\i file or \ir file) — expanded into the included file's steps. Include, } /// One ordered step in a parsed .test.sql file. public abstract class TestStep { public TestStepKind Kind { get; } /// 1-based line in the source file where this step starts (for error reporting). public int LineNumber { get; } /// /// Full path of the file this step came from when it was spliced in via \i/\ir; /// null when the step belongs to the file being executed itself. /// public string? SourceFile { get; set; } protected TestStep(TestStepKind kind, int lineNumber) { Kind = kind; LineNumber = lineNumber; } } /// /// An include line: \i path (path relative to the current working directory, like every other /// configured path) or \ir path (relative to the file containing the include) — psql semantics. /// Expanded by into the included file's steps, as if the content were pasted. /// public sealed class IncludeStep : TestStep { public string Path { get; } /// True for \ir (relative to the including file), false for \i (cwd-relative). public bool RelativeToFile { get; } public IncludeStep(string path, bool relativeToFile, int lineNumber) : base(TestStepKind.Include, lineNumber) { Path = path; RelativeToFile = relativeToFile; } } /// A SQL statement step — executed via ExecuteReader; a boolean first column is an assertion. public sealed class SqlStep : TestStep { public string Text { get; } public bool IsDoBlock { get; } public SqlStep(string text, bool isDoBlock, int lineNumber) : base(TestStepKind.Sql, lineNumber) { Text = text; IsDoBlock = isDoBlock; } } /// An embedded single-request HTTP step parsed from a block comment. public sealed class HttpStep : TestStep { /// HTTP method (upper-cased): GET, PUT, POST, DELETE. public string Method { get; } /// Request target verbatim, including any query string. Always starts with '/'. public string Path { get; } /// Request headers in declared order (duplicates allowed). public IReadOnlyList<(string Name, string Value)> Headers { get; } /// Claims for the acting principal (from # @claim name=value), in declared order. public IReadOnlyList<(string Name, string Value)> Claims { get; } /// Request body (verbatim), or null when none. public string? Body { get; } /// Response temp-table name override from # @response name, or null (use the configured default). public string? ResponseTable { get; } public HttpStep( string method, string path, IReadOnlyList<(string Name, string Value)> headers, IReadOnlyList<(string Name, string Value)> claims, string? body, string? responseTable, int lineNumber) : base(TestStepKind.Http, lineNumber) { Method = method; Path = path; Headers = headers; Claims = claims; Body = body; ResponseTable = responseTable; } }