test(playwright): M8 import Map step + per-line diff coverage (#230)
This commit is contained in:
@@ -156,6 +156,55 @@ public static partial class CliRunner
|
||||
return RequireId(doc, "site area create");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a site via <c>site create</c> and returns its new <c>id</c>.
|
||||
/// </summary>
|
||||
/// <param name="name">Site display name (typically from <see cref="UniqueName"/>).</param>
|
||||
/// <param name="identifier">
|
||||
/// Stable <c>SiteIdentifier</c> the bundle subsystem matches on. Must be unique
|
||||
/// across the cluster; pass a <see cref="UniqueName"/>-derived value so the import
|
||||
/// preview finds no auto-match in the destination once the source site is deleted.
|
||||
/// </param>
|
||||
/// <returns>The id of the newly created site.</returns>
|
||||
/// <exception cref="InvalidOperationException">
|
||||
/// The CLI failed, or the response did not carry an integer <c>id</c>.
|
||||
/// </exception>
|
||||
public static async Task<int> CreateSiteAsync(string name, string identifier)
|
||||
{
|
||||
using var doc = await RunJsonAsync(
|
||||
"site", "create", "--name", name, "--identifier", identifier);
|
||||
return RequireId(doc, "site create");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the ids of all sites whose <c>siteIdentifier</c> starts with
|
||||
/// <paramref name="identifierPrefix"/> (ordinal), via <c>site list</c>. Used to
|
||||
/// drop any throwaway site a Transport test created (the create helper hands back
|
||||
/// the id, but teardown re-resolves defensively in case the test failed mid-flow).
|
||||
/// </summary>
|
||||
/// <param name="identifierPrefix">The <c>siteIdentifier</c> prefix to match.</param>
|
||||
public static async Task<IReadOnlyList<int>> ListSiteIdsByIdentifierPrefixAsync(string identifierPrefix)
|
||||
{
|
||||
using var doc = await RunJsonAsync("site", "list");
|
||||
var ids = new List<int>();
|
||||
if (doc.RootElement.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
foreach (var site in doc.RootElement.EnumerateArray())
|
||||
{
|
||||
if (site.TryGetProperty("siteIdentifier", out var idtf)
|
||||
&& idtf.ValueKind == JsonValueKind.String
|
||||
&& (idtf.GetString()?.StartsWith(identifierPrefix, StringComparison.Ordinal) ?? false)
|
||||
&& site.TryGetProperty("id", out var id)
|
||||
&& id.TryGetInt32(out var siteId))
|
||||
{
|
||||
ids.Add(siteId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolves a site's numeric id from its <c>siteIdentifier</c> (e.g.
|
||||
/// <c>"site-a"</c>) via <c>site list</c>.
|
||||
@@ -519,6 +568,27 @@ public static partial class CliRunner
|
||||
return RequireId(doc, "shared-script create");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates a shared script's <c>Code</c> via <c>shared-script update</c>. The
|
||||
/// CLI requires both <c>--name</c> and <c>--code</c>, so the (unchanged) name is
|
||||
/// passed through alongside the new body. Used by the Transport import line-diff
|
||||
/// test to diverge the destination's code from the bundle's after export, so the
|
||||
/// preview classifies the shared script as <c>Modified</c> and emits a per-line
|
||||
/// <c>lineDiff</c>. Surfaces CLI errors (the test asserts the update succeeded).
|
||||
/// </summary>
|
||||
/// <param name="id">Shared script id.</param>
|
||||
/// <param name="name">Shared script name (unchanged; the CLI requires it).</param>
|
||||
/// <param name="code">The new script body.</param>
|
||||
/// <exception cref="InvalidOperationException">The CLI failed.</exception>
|
||||
public static async Task UpdateSharedScriptCodeAsync(int id, string name, string code)
|
||||
{
|
||||
await RunAsync(
|
||||
"shared-script", "update",
|
||||
"--id", id.ToString(System.Globalization.CultureInfo.InvariantCulture),
|
||||
"--name", name,
|
||||
"--code", code);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an LDAP→role mapping via <c>security role-mapping create</c> and returns its new <c>id</c>.
|
||||
/// </summary>
|
||||
@@ -659,6 +729,62 @@ public static partial class CliRunner
|
||||
"--source-environment", sourceEnvironment);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exports a Transport bundle scoped to a single site via <c>bundle export
|
||||
/// --sites <siteIdentifier></c>. A bundle that carries a site produces a
|
||||
/// <c>RequiredSiteMapping</c> in the import preview, which is what makes the
|
||||
/// import wizard's Map step render. With the source site deleted before import,
|
||||
/// the mapping has no auto-match, so the Map row defaults to "Create new" and the
|
||||
/// operator must pick a target — exactly the path the Map-step test exercises.
|
||||
/// </summary>
|
||||
/// <param name="outputPath">Destination <c>.scadabundle</c> path.</param>
|
||||
/// <param name="siteIdentifier">The <c>SiteIdentifier</c> of the single site to export.</param>
|
||||
/// <param name="passphrase">Encryption passphrase for the bundle.</param>
|
||||
/// <param name="sourceEnvironment"><c>SourceEnvironment</c> value stamped into the bundle manifest.</param>
|
||||
/// <exception cref="InvalidOperationException">The CLI failed.</exception>
|
||||
public static async Task BundleExportSiteAsync(
|
||||
string outputPath, string siteIdentifier, string passphrase, string sourceEnvironment)
|
||||
{
|
||||
await RunAsync(
|
||||
"bundle", "export",
|
||||
"--output", outputPath,
|
||||
"--passphrase", passphrase,
|
||||
"--sites", siteIdentifier,
|
||||
"--source-environment", sourceEnvironment);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exports a Transport bundle scoped to a single shared script via
|
||||
/// <c>bundle export --shared-scripts <name></c>. A shared script carries a
|
||||
/// <c>Code</c> field, so when the destination's copy is later diverged the import
|
||||
/// preview classifies it as <c>Modified</c> and emits a structured per-line
|
||||
/// <c>lineDiff</c> — the payload the <c>LineDiffView</c> render asserts on.
|
||||
/// </summary>
|
||||
/// <param name="outputPath">Destination <c>.scadabundle</c> path.</param>
|
||||
/// <param name="sharedScriptName">Name of the single shared script to export.</param>
|
||||
/// <param name="passphrase">Encryption passphrase for the bundle.</param>
|
||||
/// <param name="sourceEnvironment"><c>SourceEnvironment</c> value stamped into the bundle manifest.</param>
|
||||
/// <exception cref="InvalidOperationException">
|
||||
/// The shared-script name contains a comma (it would split the comma-separated
|
||||
/// <c>--shared-scripts</c> selector), or the CLI failed.
|
||||
/// </exception>
|
||||
public static async Task BundleExportSharedScriptAsync(
|
||||
string outputPath, string sharedScriptName, string passphrase, string sourceEnvironment)
|
||||
{
|
||||
if (sharedScriptName.Contains(','))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Shared-script name '{sharedScriptName}' contains a comma and cannot be used with '--shared-scripts'.");
|
||||
}
|
||||
|
||||
await RunAsync(
|
||||
"bundle", "export",
|
||||
"--output", outputPath,
|
||||
"--passphrase", passphrase,
|
||||
"--shared-scripts", sharedScriptName,
|
||||
"--source-environment", sourceEnvironment);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolves a template's name from its id via <c>template list</c>.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user