test: Ende-zu-Ende-Test der Zuweisung (Stapel, Gruppen, Überdeckung, Massenzuweisung, detach); Entscheidungsnotiz zu 4b
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
17af3b05df
commit
10bed73b24
@@ -35,7 +35,26 @@ Ansätze vorschlagen → Entwurf abschnittsweise freigeben → Spec schreiben
|
|||||||
- Pipeline `DesignChange` (alle Bereiche), Snapshots `SnapshotStore`, Bereich `presets`.
|
- Pipeline `DesignChange` (alle Bereiche), Snapshots `SnapshotStore`, Bereich `presets`.
|
||||||
- Tools: lit/divi-preset-get, lit/divi-presets-set, lit/divi-presets-delete, lit/divi-design-snapshots, lit/divi-design-restore (alle indirekt).
|
- Tools: lit/divi-preset-get, lit/divi-presets-set, lit/divi-presets-delete, lit/divi-design-snapshots, lit/divi-design-restore (alle indirekt).
|
||||||
- Schreiben über die Schrittfolge von `GlobalPresetController::sync` (Mirror `preset-sync`).
|
- Schreiben über die Schrittfolge von `GlobalPresetController::sync` (Mirror `preset-sync`).
|
||||||
- Offen für 4b: Fundstellen von Standard-Gruppen-Presets (Gruppenliste je Modul), lit/divi-design-detach.
|
- Offen für 4b (erledigt in 4b, R11 und Task 10): Fundstellen von Standard-Gruppen-Presets (Gruppenliste je Modul), lit/divi-design-detach.
|
||||||
|
|
||||||
|
## Etappe 4b (Plan 2026-10-18-etappe-4b-zuweisen.md)
|
||||||
|
- Tools: lit-divi-insert/-update/lit-content-create (preset-Stapel, group_presets, clear_overrides), lit/divi-presets-assign, lit/divi-design-detach (beide indirekt); Outline und node-get zeigen Gruppen-Presets.
|
||||||
|
- R1 Fundstellen: keine Klasse DesignUsages; GlobalUsages::reportFor()/rowsFor() plus ModuleUsageQuery (alle Module eines Typs).
|
||||||
|
- R2 Stapel: preset = String | Liste (1–10) | null; doppelte IDs und leere Liste sind Fehler; letzter im Stapel gewinnt bei gleicher Priorität.
|
||||||
|
- R3 Gruppen-Schlüssel: Kurzname, voller Name oder Attributpfad; mehrdeutiger Name → Fehler mit den Pfaden; gleichnamige Gruppen in einem Modul sind auch in lit/divi-presets-set und im Composer (group_presets) ein Fehler, dort hilft der Attributpfad als Schlüssel; GroupKeys ersetzt die private Suche im PresetComposer.
|
||||||
|
- R4 Überdeckungen (G9): Vergleich je Blatt (Pfad, Breakpoint, Zustand), nur ausdrücklich zugewiesene Presets, Warnung nur bei abweichendem Wert; clear_overrides entfernt alle lokalen Blätter auf Preset-Blättern.
|
||||||
|
- R5 Warnungstext je Preset eine Zeile, bis zu 5 Pfade.
|
||||||
|
- R6 Outline: group_presets je Zeile und in node-get; Fingerprint unverändert.
|
||||||
|
- R7 clear_overrides beim Einfügen wirkt nach set/attrs desselben Knotens; nicht-boolesch → Fehler.
|
||||||
|
- R8 Seiten-Umschreiber: globale Instanzen nie umgeschrieben (skipped; Bibliotheks-ID nur bei sichtbaren Bibliotheks-IDs, P13), Bibliothekseintrag ist eigene Fundstelle; nicht ladbare Seiten skipped; remaining zählt nur Seiten mit Änderungen.
|
||||||
|
- P8a mit post_ids: nur die genannten Seiten können das Schreiben blockieren, HARD_CAP gilt nicht, eine genannte Seite ohne Bearbeitungsrecht steht in skipped. Ohne post_ids verweigert jede blockierte Live-Fundstelle oder zu viele Fundstellen den ganzen Aufruf, nichts wird geschrieben.
|
||||||
|
- R9 Kein unfiltered_html-Zwang: der Umschreiber ändert nur Preset-Verweise und entfernt lokale Werte, Speichern über DiviSaver.
|
||||||
|
- R10 detach nur Presets: Eingabe preset = Objekt {module|group, preset}; variable → unsupported (4c); ohne post_ids zuerst verschachtelte Verweise über DesignChange (Snapshot, design_rev), danach Seiten (≤ 50); scheitert die erste Seite danach, nennt der Fehler Snapshot und diff; Standard-Presets nur ausdrückliche Verweise.
|
||||||
|
- lit/divi-presets-assign: preset: null und null in group_presets werden abgewiesen (Hinweis auf lit/divi-design-detach); ein leerer Probelauf ist ein normales „nichts zu tun“.
|
||||||
|
- R11 Standard-Gruppen-Presets: PresetUsageMatcher erkennt implizite Nutzung (Modul hat die Gruppe, kein ausdrücklicher Eintrag); Kandidaten fail closed über wp:divi/; der 4a-Hinweis „nicht aufgelistet“ entfällt.
|
||||||
|
- Grenze je Aufruf A6: 50 Seiten, remaining; Teilerfolg partial_write mit den gespeicherten Seiten.
|
||||||
|
- Offen für 4c: detach für Variablen (A7: Referenz durch den aktuellen Wert ersetzen, bei Farben entfällt detach), Wiederverwendung des PageRewriter/TreeRewrite dafür (NodeRewrite-Strategie `VariableDetachRewrite`).
|
||||||
|
- Offen für 4c/4e: Smoke divi-presets-assign-smoke.sh läuft nur mit deaktivierten Plugins postlos und asynclistry.
|
||||||
|
|
||||||
## Offene Kleinpunkte aus 4a (Reviews, nicht merge-relevant)
|
## Offene Kleinpunkte aus 4a (Reviews, nicht merge-relevant)
|
||||||
- Task 1: minor (deferred): Nachtrag verweist nicht auf §7 Punkt 4 („strenger als Divi“ gilt für Presets nicht mehr)
|
- Task 1: minor (deferred): Nachtrag verweist nicht auf §7 Punkt 4 („strenger als Divi“ gilt für Presets nicht mehr)
|
||||||
|
|||||||
+252
@@ -0,0 +1,252 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# End-to-end checks of Etappe 4b (assign presets to modules, overrides, mass assignment, detach, delete) through the
|
||||||
|
# OAuth-protected endpoint against the real Divi. Runs INSIDE the DDEV web container:
|
||||||
|
# cd /home/janniclas/Projekte/WordPress && timeout 900 ddev exec bash wp-content/plugins/WP-LIT-MCP/tests/Integration/divi-presets-assign-smoke.sh
|
||||||
|
# Runs only with the plugins postlos and asynclistry deactivated (Monolog 2 / deprecation output of the WP-CLI calls).
|
||||||
|
# Creates presets named "LIT Smoke <run> …" and two draft pages with one button each; the EXIT trap restores the
|
||||||
|
# preset inventory taken before the first change and deletes the pages (with revisions) by exact ID.
|
||||||
|
set -euo pipefail
|
||||||
|
cd /var/www/html
|
||||||
|
# shellcheck source=lib.sh
|
||||||
|
source wp-content/plugins/WP-LIT-MCP/tests/Integration/lib.sh
|
||||||
|
|
||||||
|
ADMIN_LOGIN=$(wp user list --role=administrator --field=user_login | head -1)
|
||||||
|
RUN="$(date +%s)-$$"
|
||||||
|
PREFIX="LIT Smoke $RUN"
|
||||||
|
ORIGINAL_PRESETS=$(wp eval 'echo wp_json_encode(ET\Builder\Packages\GlobalData\GlobalPreset::get_data());' 2>/dev/null)
|
||||||
|
PAGE1=""
|
||||||
|
PAGE2=""
|
||||||
|
NODE="s0.r0.c0.m0"
|
||||||
|
CONTENT='<!-- wp:divi/placeholder --><!-- wp:divi/section --><!-- wp:divi/row --><!-- wp:divi/column {"module":{"decoration":{"sizing":{"desktop":{"value":{"flexType":"24_24"}}}}}} --><!-- wp:divi/button {"button":{"innerContent":{"desktop":{"value":{"text":"Los"}}}}} /--><!-- /wp:divi/column --><!-- /wp:divi/row --><!-- /wp:divi/section --><!-- /wp:divi/placeholder -->'
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
wp eval '$d = json_decode(getenv("LIT_PRESETS"), true); et_update_option(ET\Builder\Packages\GlobalData\GlobalPreset::option_name(), $d, false, "", "", true);' \
|
||||||
|
--user="$ADMIN_LOGIN" >/dev/null 2>&1 || echo "WARN: preset inventory not restored"
|
||||||
|
for id in $PAGE1 $PAGE2; do
|
||||||
|
wp post delete "$id" --force >/dev/null 2>&1 || true
|
||||||
|
done
|
||||||
|
# Change-log rows about the test pages.
|
||||||
|
LIT_IDS="$PAGE1 $PAGE2" wp eval '
|
||||||
|
global $wpdb;
|
||||||
|
$table = $wpdb->prefix . "lit_mcp_log";
|
||||||
|
foreach (array_filter(explode(" ", (string) getenv("LIT_IDS"))) as $id) {
|
||||||
|
$wpdb->delete($table, ["object_type" => "page", "object_id" => $id]);
|
||||||
|
}' >/dev/null 2>&1 || true
|
||||||
|
cleanup_app_passwords_for "$ADMIN_LOGIN"
|
||||||
|
}
|
||||||
|
export LIT_PRESETS="$ORIGINAL_PRESETS"
|
||||||
|
trap 'rc=$?; cleanup; guard_exit "$rc" || exit $?' EXIT
|
||||||
|
|
||||||
|
connect "$ADMIN_LOGIN"
|
||||||
|
|
||||||
|
create_page() { # $1 = title -> prints the ID of a draft Divi 5 page with one button without preset
|
||||||
|
LIT_TITLE="$1" LIT_CONTENT="$CONTENT" wp --user="$ADMIN_LOGIN" eval '
|
||||||
|
$id = wp_insert_post(["post_type" => "page", "post_status" => "draft", "post_title" => getenv("LIT_TITLE"),
|
||||||
|
"post_content" => wp_slash((string) getenv("LIT_CONTENT"))]);
|
||||||
|
update_post_meta($id, "_et_pb_use_builder", "on");
|
||||||
|
update_post_meta($id, "_et_pb_use_divi_5", "on");
|
||||||
|
echo $id;' 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
button_attrs() { # $1 = post ID -> attributes (JSON) of the first divi/button block as stored
|
||||||
|
LIT_ID="$1" wp eval '
|
||||||
|
$find = static function (array $blocks) use (&$find) {
|
||||||
|
foreach ($blocks as $b) {
|
||||||
|
if ($b["blockName"] === "divi/button") { return $b["attrs"]; }
|
||||||
|
$r = $find($b["innerBlocks"]);
|
||||||
|
if ($r !== null) { return $r; }
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
echo wp_json_encode($find(parse_blocks(get_post((int) getenv("LIT_ID"))->post_content)));' 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
revisions_of() { # $1 = post ID -> number of revisions
|
||||||
|
LIT_ID="$1" wp eval 'echo count(wp_get_post_revisions((int) getenv("LIT_ID")));' 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
preset_stored() { # $1 = module|group, $2 = divi/<name>, $3 = preset ID -> exit 0 when Divi stores it
|
||||||
|
LIT_KIND="$1" LIT_SCOPE="$2" LIT_PID="$3" wp eval '
|
||||||
|
$d = ET\Builder\Packages\GlobalData\GlobalPreset::get_data();
|
||||||
|
exit(isset($d[getenv("LIT_KIND")][getenv("LIT_SCOPE")]["items"][getenv("LIT_PID")]) ? 0 : 1);' 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
preset_item() { # $1 = module preset ID -> the stored button preset item (JSON)
|
||||||
|
LIT_PID="$1" wp eval '
|
||||||
|
$d = ET\Builder\Packages\GlobalData\GlobalPreset::get_data();
|
||||||
|
echo wp_json_encode($d["module"]["divi/button"]["items"][getenv("LIT_PID")] ?? null);' 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
nested_groups() { # $1 = module preset ID -> groupPresets (JSON) of that button preset
|
||||||
|
LIT_PID="$1" wp eval '
|
||||||
|
$d = ET\Builder\Packages\GlobalData\GlobalPreset::get_data();
|
||||||
|
echo wp_json_encode($d["module"]["divi/button"]["items"][getenv("LIT_PID")]["groupPresets"] ?? new stdClass());' 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
timed() { # $1 = label; runs the rest of the arguments and prints the duration to stderr
|
||||||
|
local label=$1 start end
|
||||||
|
shift
|
||||||
|
start=$(date +%s.%N)
|
||||||
|
"$@"
|
||||||
|
end=$(date +%s.%N)
|
||||||
|
echo "time - $label: $(awk -v s="$start" -v e="$end" 'BEGIN { printf "%.2f", e - s }') s" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
details() { # $1 = tool()/ability() result -> details object of an error, or the result itself
|
||||||
|
echo "$1" | jq -c 'if has("__error") then ((.__error | fromjson?) // {}) else . end'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Runs lit/divi-presets-set with dry run and confirm; sets RESULT. $1 = input JSON without confirm.
|
||||||
|
presets_set() {
|
||||||
|
local dry rev
|
||||||
|
dry=$(ability lit/divi-presets-set "$1")
|
||||||
|
[ "$(error_code "$dry")" = "confirm_required" ] || fail "presets-set dry run: $dry"
|
||||||
|
rev=$(echo "$dry" | jq -r '.__error | fromjson | .design_rev')
|
||||||
|
RESULT=$(ability lit/divi-presets-set "$(echo "$1" | jq -c --arg r "$rev" '. + {confirm: true, design_rev: $r}')")
|
||||||
|
[ "$(echo "$RESULT" | jq -r '.ok')" = "true" ] || fail "presets-set confirm: $RESULT"
|
||||||
|
}
|
||||||
|
|
||||||
|
preset_id() { # $1 = module|group, $2 = short name ("button", "font"), $3 = preset name -> prints the ID
|
||||||
|
local id
|
||||||
|
id=$(ability lit/divi-preset-get "$(jq -cn --arg k "$1" --arg s "$2" --arg p "$3" '{($k): $s, preset: $p}')" | jq -r '.id // empty')
|
||||||
|
[ -n "$id" ] || fail "preset $3 not found"
|
||||||
|
echo "$id"
|
||||||
|
}
|
||||||
|
|
||||||
|
tree_rev() { # $1 = post ID
|
||||||
|
tool lit-divi-outline "{\"post_id\":$1}" | jq -r '.tree_rev'
|
||||||
|
}
|
||||||
|
|
||||||
|
# 1. Two draft pages with one button without preset each.
|
||||||
|
PAGE1=$(create_page "$PREFIX Seite 1")
|
||||||
|
PAGE2=$(create_page "$PREFIX Seite 2")
|
||||||
|
[ -n "$PAGE1" ] && [ -n "$PAGE2" ] || fail "pages not created"
|
||||||
|
for id in "$PAGE1" "$PAGE2"; do
|
||||||
|
button_attrs "$id" | jq -e '(.modulePreset // null) == null and (.groupPreset // null) == null' >/dev/null \
|
||||||
|
|| fail "page $id starts with a preset"
|
||||||
|
done
|
||||||
|
pass "two draft pages with a button without preset ($PAGE1, $PAGE2)"
|
||||||
|
|
||||||
|
# 2. Presets: two button module presets (A, B) and a font group preset (G); B nests G.
|
||||||
|
presets_set "$(jq -cn --arg a "$PREFIX A" --arg b "$PREFIX B" --arg g "$PREFIX G" '{items: [
|
||||||
|
{module: "button", name: $a, attrs: {"button.decoration.background": {desktop: {color: "#123456"}}}},
|
||||||
|
{module: "button", name: $b, attrs: {"button.decoration.background": {desktop: {color: "#654321"}}}},
|
||||||
|
{group: "font", name: $g, source_module: "button",
|
||||||
|
attrs: {"button.decoration.font.font": {desktop: {weight: "700"}}}}]}')"
|
||||||
|
PRESET_A=$(preset_id module button "$PREFIX A")
|
||||||
|
PRESET_B=$(preset_id module button "$PREFIX B")
|
||||||
|
PRESET_G=$(preset_id group font "$PREFIX G")
|
||||||
|
presets_set "$(jq -cn --arg b "$PREFIX B" --arg g "$PREFIX G" '{items: [
|
||||||
|
{module: "button", preset: $b, group_presets: {font: $g}}]}')"
|
||||||
|
nested_groups "$PRESET_B" | jq -e --arg g "$PRESET_G" '."button.decoration.font".presetId == [$g]' >/dev/null \
|
||||||
|
|| fail "preset B does not nest group preset G"
|
||||||
|
pass "module presets A, B and group preset G created, B nests G"
|
||||||
|
|
||||||
|
# 3. A stack and a group preset on page 1 through lit-divi-update.
|
||||||
|
TREE=$(tree_rev "$PAGE1")
|
||||||
|
UPDATE=$(tool lit-divi-update "$(jq -cn --argjson id "$PAGE1" --arg rev "$TREE" --arg n "$NODE" --arg a "$PREFIX A" \
|
||||||
|
--arg b "$PREFIX B" --arg g "$PREFIX G" '{post_id: $id, tree_rev: $rev, changes: [
|
||||||
|
{id: $n, preset: [$a, $b], group_presets: {font: $g}}]}')")
|
||||||
|
echo "$UPDATE" | jq -e '.ok == true and (.tree_rev | length) > 0 and ((.warnings // []) | map(select(contains("überdecken"))) | length) == 0' \
|
||||||
|
>/dev/null || fail "update with stack and group preset: $UPDATE"
|
||||||
|
button_attrs "$PAGE1" | jq -e --arg a "$PRESET_A" --arg b "$PRESET_B" --arg g "$PRESET_G" \
|
||||||
|
'.modulePreset == [$a, $b] and .groupPreset == {"button.decoration.font": {presetId: [$g], groupName: "divi/font"}}' >/dev/null \
|
||||||
|
|| fail "stored modulePreset/groupPreset of page 1: $(button_attrs "$PAGE1")"
|
||||||
|
OUTLINE=$(tool lit-divi-outline "{\"post_id\":$PAGE1}")
|
||||||
|
echo "$OUTLINE" | jq -e --arg n "$NODE" --arg g "font: $PREFIX G" \
|
||||||
|
'any(.nodes[]; .id == $n and ((.group_presets // []) | index($g) != null)) and (.outline | contains("Gruppen-Presets: " + $g))' \
|
||||||
|
>/dev/null || fail "outline lacks the group preset: $OUTLINE"
|
||||||
|
pass "stack [A, B] and group preset stored; outline shows the group preset"
|
||||||
|
|
||||||
|
# 4. Overrides: a differing local value is reported, clear_overrides removes it; a non-boolean value is refused.
|
||||||
|
TREE=$(tree_rev "$PAGE2")
|
||||||
|
UPDATE=$(tool lit-divi-update "$(jq -cn --argjson id "$PAGE2" --arg rev "$TREE" --arg n "$NODE" --arg a "$PREFIX A" \
|
||||||
|
'{post_id: $id, tree_rev: $rev, changes: [
|
||||||
|
{id: $n, preset: $a, attrs: {"button.decoration.background": {desktop: {color: "#abcdef"}}}}]}')")
|
||||||
|
echo "$UPDATE" | jq -e --arg n "$NODE" --arg a "$PREFIX A" \
|
||||||
|
'.ok == true and ((.warnings // []) | map(select(contains($n) and contains("überdecken") and contains($a) and contains("clear_overrides"))) | length) == 1' \
|
||||||
|
>/dev/null || fail "no override warning: $UPDATE"
|
||||||
|
button_attrs "$PAGE2" | jq -e --arg a "$PRESET_A" '.modulePreset == [$a] and .button.decoration.background != null' >/dev/null \
|
||||||
|
|| fail "page 2 should keep its local background: $(button_attrs "$PAGE2")"
|
||||||
|
TREE=$(echo "$UPDATE" | jq -r '.tree_rev')
|
||||||
|
BAD=$(tool lit-divi-update "$(jq -cn --argjson id "$PAGE2" --arg rev "$TREE" --arg n "$NODE" \
|
||||||
|
'{post_id: $id, tree_rev: $rev, changes: [{id: $n, clear_overrides: "ja"}]}')")
|
||||||
|
# The input schema (type boolean) refuses it before the tool runs, so the error carries no tool code.
|
||||||
|
echo "$BAD" | jq -e 'has("__error") and (.__error | contains("clear_overrides"))' >/dev/null \
|
||||||
|
|| fail "non-boolean clear_overrides: $BAD"
|
||||||
|
CLEARED=$(tool lit-divi-update "$(jq -cn --argjson id "$PAGE2" --arg rev "$TREE" --arg n "$NODE" --arg a "$PREFIX A" \
|
||||||
|
'{post_id: $id, tree_rev: $rev, changes: [{id: $n, preset: $a, clear_overrides: true}]}')")
|
||||||
|
echo "$CLEARED" | jq -e '.ok == true and ((.warnings // []) | map(select(contains("überdecken"))) | length) == 0' >/dev/null \
|
||||||
|
|| fail "clear_overrides: $CLEARED"
|
||||||
|
button_attrs "$PAGE2" | jq -e --arg a "$PRESET_A" '.modulePreset == [$a] and (.button.decoration.background // null) == null
|
||||||
|
and .button.innerContent.desktop.value.text == "Los"' >/dev/null \
|
||||||
|
|| fail "clear_overrides left or removed the wrong values: $(button_attrs "$PAGE2")"
|
||||||
|
pass "override warning, clear_overrides removes exactly the covering value, non-boolean refused by the schema"
|
||||||
|
|
||||||
|
# 5. Mass assignment over both pages: stack [B] and group preset G.
|
||||||
|
ASSIGN=$(jq -cn --argjson p1 "$PAGE1" --argjson p2 "$PAGE2" --arg b "$PREFIX B" --arg g "$PREFIX G" \
|
||||||
|
'{module: "button", preset: $b, group_presets: {font: $g}, post_ids: [$p1, $p2]}')
|
||||||
|
NONE=$(ability lit/divi-presets-assign "$(echo "$ASSIGN" | jq -c '. + {only_without_preset: true}')")
|
||||||
|
details "$NONE" | jq -e '(.pages_count // 0) == 0' >/dev/null || fail "only_without_preset should match no page: $NONE"
|
||||||
|
REVISIONS_BEFORE=$(revisions_of "$PAGE1")
|
||||||
|
DRY=$(timed "assign dry run" ability lit/divi-presets-assign "$ASSIGN")
|
||||||
|
[ "$(error_code "$DRY")" = "confirm_required" ] || fail "assign without confirm: $DRY"
|
||||||
|
details "$DRY" | jq -e --argjson p1 "$PAGE1" --argjson p2 "$PAGE2" \
|
||||||
|
'.pages_count == 2 and .nodes_count == 2 and ([.pages[].post_id] | sort) == ([$p1, $p2] | sort)
|
||||||
|
and ((.blocked_ids // []) | length) == 0' >/dev/null || fail "assign dry run: $DRY"
|
||||||
|
button_attrs "$PAGE1" | jq -e --arg a "$PRESET_A" --arg b "$PRESET_B" '.modulePreset == [$a, $b]' >/dev/null \
|
||||||
|
|| fail "dry run changed page 1"
|
||||||
|
[ "$(revisions_of "$PAGE1")" = "$REVISIONS_BEFORE" ] || fail "dry run created a revision"
|
||||||
|
ASSIGNED=$(timed "assign confirmed" ability lit/divi-presets-assign "$(echo "$ASSIGN" | jq -c '. + {confirm: true}')")
|
||||||
|
echo "$ASSIGNED" | jq -e --argjson p1 "$PAGE1" --argjson p2 "$PAGE2" \
|
||||||
|
'.ok == true and (.saved | length) == 2 and .remaining == 0 and ([.saved[].post_id] | sort) == ([$p1, $p2] | sort)' \
|
||||||
|
>/dev/null || fail "assign with confirm: $ASSIGNED"
|
||||||
|
for id in "$PAGE1" "$PAGE2"; do
|
||||||
|
button_attrs "$id" | jq -e --arg b "$PRESET_B" --arg g "$PRESET_G" \
|
||||||
|
'.modulePreset == [$b] and .groupPreset == {"button.decoration.font": {presetId: [$g], groupName: "divi/font"}}' \
|
||||||
|
>/dev/null || fail "page $id after mass assignment: $(button_attrs "$id")"
|
||||||
|
done
|
||||||
|
REVISIONS_AFTER=$(revisions_of "$PAGE1")
|
||||||
|
AGAIN=$(ability lit/divi-presets-assign "$ASSIGN")
|
||||||
|
[ "$(error_code "$AGAIN")" != "confirm_required" ] || fail "second dry run still finds changes: $AGAIN"
|
||||||
|
details "$AGAIN" | jq -e '(.pages_count // 0) == 0' >/dev/null || fail "second dry run lists pages: $AGAIN"
|
||||||
|
[ "$(revisions_of "$PAGE1")" = "$REVISIONS_AFTER" ] || fail "second dry run created a revision"
|
||||||
|
pass "mass assignment: dry run lists 2 pages, confirm saved 2 (remaining 0), second dry run finds nothing"
|
||||||
|
|
||||||
|
# 6. detach of the group preset: it is in use, a stale design_rev is refused, then dry run, confirm, delete.
|
||||||
|
GROUP_ITEM=$(jq -cn --arg g "$PRESET_G" '{items: [{group: "font", preset: $g}]}')
|
||||||
|
[ "$(error_code "$(ability lit/divi-presets-delete "$GROUP_ITEM")")" = "in_use" ] || fail "delete of a used group preset"
|
||||||
|
UNSUPPORTED=$(ability lit/divi-design-detach '{"variable": "Irgendeine Variable"}')
|
||||||
|
[ "$(error_code "$UNSUPPORTED")" = "unsupported" ] || fail "detach of a variable: $UNSUPPORTED"
|
||||||
|
DETACH=$(jq -cn --arg g "$PRESET_G" '{preset: {group: "font", preset: $g}}')
|
||||||
|
DRY=$(timed "detach dry run" ability lit/divi-design-detach "$DETACH")
|
||||||
|
[ "$(error_code "$DRY")" = "confirm_required" ] || fail "detach without confirm: $DRY"
|
||||||
|
DETACH_REV=$(details "$DRY" | jq -r '.design_rev')
|
||||||
|
details "$DRY" | jq -e '.pages_count == 2 and (.diff | length) > 0' >/dev/null || fail "detach dry run: $DRY"
|
||||||
|
STALE=$(ability lit/divi-design-detach "$(echo "$DETACH" | jq -c '. + {confirm: true, design_rev: "veraltet"}')")
|
||||||
|
[ "$(error_code "$STALE")" = "rev_mismatch" ] || fail "stale design_rev: $STALE"
|
||||||
|
nested_groups "$PRESET_B" | jq -e 'length > 0' >/dev/null || fail "stale detach changed preset B"
|
||||||
|
button_attrs "$PAGE1" | jq -e '(.groupPreset // null) != null' >/dev/null || fail "stale detach changed page 1"
|
||||||
|
pass "group preset is in use, variable detach unsupported, stale design_rev refused without writing"
|
||||||
|
|
||||||
|
echo "info - preset B before detach: $(preset_item "$PRESET_B")" >&2
|
||||||
|
DETACHED=$(timed "detach confirmed" ability lit/divi-design-detach "$(echo "$DETACH" | jq -c --arg r "$DETACH_REV" '. + {confirm: true, design_rev: $r}')")
|
||||||
|
echo "$DETACHED" | jq -e '.ok == true and (.saved | length) == 2 and .remaining == 0' >/dev/null \
|
||||||
|
|| fail "detach with confirm: $DETACHED"
|
||||||
|
nested_groups "$PRESET_B" | jq -e 'length == 0' >/dev/null || fail "preset B still nests the group preset"
|
||||||
|
echo "info - preset B after withoutNestedRef: $(preset_item "$PRESET_B")" >&2
|
||||||
|
for id in "$PAGE1" "$PAGE2"; do
|
||||||
|
button_attrs "$id" | jq -e --arg b "$PRESET_B" '.modulePreset == [$b] and (.groupPreset // null) == null' >/dev/null \
|
||||||
|
|| fail "page $id after detach: $(button_attrs "$id")"
|
||||||
|
done
|
||||||
|
pass "detach removed the nested reference (snapshot pipeline) and the page references"
|
||||||
|
|
||||||
|
DRY=$(ability lit/divi-presets-delete "$GROUP_ITEM")
|
||||||
|
[ "$(error_code "$DRY")" = "confirm_required" ] || fail "delete dry run after detach: $DRY"
|
||||||
|
DELETE_REV=$(details "$DRY" | jq -r '.design_rev')
|
||||||
|
DELETED=$(ability lit/divi-presets-delete "$(echo "$GROUP_ITEM" | jq -c --arg r "$DELETE_REV" '. + {confirm: true, design_rev: $r}')")
|
||||||
|
echo "$DELETED" | jq -e '.ok == true' >/dev/null || fail "delete after detach: $DELETED"
|
||||||
|
if preset_stored group divi/font "$PRESET_G"; then fail "group preset $PRESET_G is still stored"; fi
|
||||||
|
pass "group preset deletable after detach"
|
||||||
|
|
||||||
|
finish
|
||||||
Reference in New Issue
Block a user