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;
}
}