test: divi-loop-smoke – Schleifen-Inhalte, Kontext, dynamic-sources, Move-Warnung und Rendern gegen echtes Divi (Task 6)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
02e7c3e8ec
commit
cfc46e1c5e
Executable
+263
@@ -0,0 +1,263 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# End-to-end checks of Etappe 4e (loop content: loop_* options inside a Divi loop, refused outside and in a loop of
|
||||||
|
# another kind, dynamic sources per node, move warning, real frontend render) 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-loop-smoke.sh
|
||||||
|
# Runs only with the plugins postlos and asynclistry deactivated (Monolog 2 / deprecation output of the WP-CLI calls).
|
||||||
|
# Creates one draft page with a post loop, a plain row and a term loop (and one temporary published post when the site
|
||||||
|
# has none). The EXIT trap deletes the page and the temporary post by exact ID, removes their change-log rows and puts
|
||||||
|
# the options et_divi and et_divi_global_variables back byte-exact (serialized, base64 through the environment).
|
||||||
|
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)-$$"
|
||||||
|
# $1 = option name. An option that does not exist is captured as the sentinel string, so restore() can delete it again.
|
||||||
|
capture() { wp eval "echo base64_encode(serialize(get_option('$1', '__lit_absent__')));"; }
|
||||||
|
ORIGINAL_THEME=$(capture et_divi)
|
||||||
|
ORIGINAL_VARIABLES=$(capture et_divi_global_variables)
|
||||||
|
# Abort before any change: without a capture there is nothing to restore.
|
||||||
|
[ -n "$ORIGINAL_THEME" ] || { echo "FAIL: could not capture et_divi"; exit 1; }
|
||||||
|
[ -n "$ORIGINAL_VARIABLES" ] || { echo "FAIL: could not capture et_divi_global_variables"; exit 1; }
|
||||||
|
PAGE_ID=""
|
||||||
|
TEMP_POST_ID=""
|
||||||
|
|
||||||
|
restore() { # $1 = option name, $2 = name of the environment variable that holds the capture
|
||||||
|
local LIT_CAPTURE="$2"; export LIT_CAPTURE
|
||||||
|
LIT_OPTION="$1" wp eval '$n = getenv("LIT_OPTION"); $v = unserialize(base64_decode(getenv(getenv("LIT_CAPTURE")))); if ($v === "__lit_absent__") { delete_option($n); exit(get_option($n, "__lit_absent__") === $v ? 0 : 1); } update_option($n, $v); exit(serialize(get_option($n)) === serialize($v) ? 0 : 1);' >/dev/null 2>&1 \
|
||||||
|
|| { echo "FAIL: $1 not restored"; return 1; }
|
||||||
|
}
|
||||||
|
delete_content() { # deletes the page and the temporary post by exact ID (with revisions), then their change-log rows
|
||||||
|
local ids="$PAGE_ID $TEMP_POST_ID"
|
||||||
|
for id in $ids; do
|
||||||
|
wp post delete "$id" --force >/dev/null 2>&1 || true
|
||||||
|
done
|
||||||
|
LIT_IDS="$ids" wp eval '
|
||||||
|
global $wpdb;
|
||||||
|
$table = $wpdb->prefix . "lit_mcp_log";
|
||||||
|
foreach (array_filter(explode(" ", (string) getenv("LIT_IDS"))) as $id) {
|
||||||
|
$wpdb->delete($table, ["object_id" => $id]);
|
||||||
|
}' >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
cleanup() {
|
||||||
|
local failed=0
|
||||||
|
delete_content
|
||||||
|
restore et_divi LIT_THEME || failed=1
|
||||||
|
restore et_divi_global_variables LIT_VARIABLES || failed=1
|
||||||
|
wp eval 'ET_Core_PageResource::remove_static_resources("all", "all", true);' >/dev/null 2>&1 || true
|
||||||
|
cleanup_app_passwords_for "$ADMIN_LOGIN"
|
||||||
|
return "$failed"
|
||||||
|
}
|
||||||
|
export LIT_THEME="$ORIGINAL_THEME" LIT_VARIABLES="$ORIGINAL_VARIABLES"
|
||||||
|
trap 'rc=$?; cleanup || rc=1; guard_exit "$rc" || exit $?' EXIT
|
||||||
|
|
||||||
|
[ "$(wp eval 'echo get_template();')" = "Divi" ] || fail "Divi must be the active theme"
|
||||||
|
connect "$ADMIN_LOGIN"
|
||||||
|
|
||||||
|
# --- helpers -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Draft page: s0.r0 = column c0 with a POST loop (queryType post_types, post type "post") and one static text module,
|
||||||
|
# s0.r1 = column c0 WITHOUT a loop and one static text module (below the loop), s0.r2 = column c0 with a TERM loop
|
||||||
|
# (queryType post_taxonomies, taxonomy category) and one static text module. Loop attributes exactly as Divi's own
|
||||||
|
# builder stores them (module.advanced.loop.desktop.value, enable "on").
|
||||||
|
create_loop_page() { # prints the ID
|
||||||
|
LIT_TITLE="LIT Smoke $RUN Schleife" wp --user="$ADMIN_LOGIN" eval '
|
||||||
|
$b = static fn (string $n, array $a, array $k = []): array => ["blockName" => $n, "attrs" => $a, "innerBlocks" => $k,
|
||||||
|
"innerHTML" => "", "innerContent" => array_fill(0, count($k), null)];
|
||||||
|
$text = static fn (string $t): array => $b("divi/text", ["content" => ["innerContent" => ["desktop" => ["value" => $t]]]]);
|
||||||
|
$width = ["module" => ["decoration" => ["sizing" => ["desktop" => ["value" => ["flexType" => "24_24"]]]]]];
|
||||||
|
$loop = static fn (string $id, string $type, string $sub, string $label): array => array_replace_recursive($width, [
|
||||||
|
"module" => ["advanced" => ["loop" => ["desktop" => ["value" => ["enable" => "on", "loopId" => $id,
|
||||||
|
"queryType" => $type, "subTypes" => [["value" => $sub, "label" => $label]], "postPerPage" => "3"]]]]]]);
|
||||||
|
$row = static fn (array $column): array => $b("divi/row", [], [$column]);
|
||||||
|
$section = $b("divi/section", [], [
|
||||||
|
$row($b("divi/column", $loop("loop-litsmoke01", "post_types", "post", "Post"), [$text("<p>Schleife</p>")])),
|
||||||
|
$row($b("divi/column", $width, [$text("<p>Ausserhalb</p>")])),
|
||||||
|
$row($b("divi/column", $loop("loop-litsmoke02", "post_taxonomies", "category", "Categories"), [$text("<p>Terme</p>")])),
|
||||||
|
]);
|
||||||
|
$id = wp_insert_post(["post_type" => "page", "post_status" => "draft", "post_title" => getenv("LIT_TITLE"),
|
||||||
|
"post_content" => wp_slash(serialize_block($b("divi/placeholder", [], [$section])))]);
|
||||||
|
update_post_meta($id, "_et_pb_use_builder", "on");
|
||||||
|
update_post_meta($id, "_et_pb_use_divi_5", "on");
|
||||||
|
echo $id;' 2>/dev/null
|
||||||
|
}
|
||||||
|
stored() { wp post get "$PAGE_ID" --field=post_content; }
|
||||||
|
# Substring tests without a pipe: with pipefail, grep -q closing the pipe early would fail the pipeline (SIGPIPE).
|
||||||
|
stored_has() { local s; s=$(stored); [[ "$s" == *"$1"* ]]; }
|
||||||
|
has_line() { grep -qx -- "$2" <<<"$1"; } # $1 = lines, $2 = exact line
|
||||||
|
has_prefix() { grep -q -- "^$2" <<<"$1"; }
|
||||||
|
tree_rev() { tool lit-divi-outline "{\"post_id\":$PAGE_ID}" | jq -r '.tree_rev'; }
|
||||||
|
|
||||||
|
# insert <parent path id> <content value>: one text module with the given content (short form or $variable string).
|
||||||
|
insert_text() {
|
||||||
|
tool lit-divi-insert "$(jq -cn --argjson p "$PAGE_ID" --arg r "$(tree_rev)" --arg parent "$1" --arg c "$2" \
|
||||||
|
'{post_id: $p, tree_rev: $r, parent: $parent, nodes: [{type: "text", content: $c}]}')"
|
||||||
|
}
|
||||||
|
# refused_with <answer> <text>: the call was refused (an error, not the dry run of anything) and the error names <text>.
|
||||||
|
refused_with() {
|
||||||
|
echo "$1" | jq -e --arg t "$2" 'has("__error") and (.__error | contains($t))' >/dev/null
|
||||||
|
}
|
||||||
|
# variable_ref <option name> [settings JSON]: the full form $variable({...})$ of a content reference.
|
||||||
|
variable_ref() {
|
||||||
|
local settings="${2:-}"; [ -n "$settings" ] || settings='{}'
|
||||||
|
jq -rn --arg n "$1" --argjson s "$settings" \
|
||||||
|
'"$variable(" + ({type: "content", value: {name: $n, settings: ({before: "", after: ""} + $s)}} | tojson) + ")$"'
|
||||||
|
}
|
||||||
|
# loop_names <dynamic-sources answer>: every option name starting with loop_ anywhere in the answer, one per line.
|
||||||
|
# ADAPT (Task 5): the jq walk finds "name" keys in any nesting; narrow it when the answer has a fixed list.
|
||||||
|
loop_names() { echo "$1" | jq -r '[.. | objects | .name? // empty | strings | select(startswith("loop_"))] | unique[]'; }
|
||||||
|
|
||||||
|
# --- 1. The loop page --------------------------------------------------------------------------------------------
|
||||||
|
PAGE_ID=$(create_loop_page)
|
||||||
|
[ -n "$PAGE_ID" ] || fail "loop page not created"
|
||||||
|
OUTLINE=$(tool lit-divi-outline "{\"post_id\":$PAGE_ID}")
|
||||||
|
echo "$OUTLINE" | jq -e '.tree_rev | type == "string"' >/dev/null || fail "outline of the loop page: $OUTLINE"
|
||||||
|
for NODE in s0.r0.c0.m0 s0.r1.c0.m0 s0.r2.c0.m0; do
|
||||||
|
[[ "$OUTLINE" == *"$NODE"* ]] || fail "outline lacks $NODE: $OUTLINE"
|
||||||
|
done
|
||||||
|
stored_has '"enable":"on"' || fail "stored page has no enabled loop"
|
||||||
|
pass "loop page $PAGE_ID created (post loop, plain row, term loop)"
|
||||||
|
|
||||||
|
# --- 2. {{loop:post_date}} inside the post loop is accepted and stored -----------------------------------------------
|
||||||
|
# ADAPT (Task 4): the new module is the second child of the loop column, so its path id is s0.r0.c0.m1.
|
||||||
|
LOOP_NODE=s0.r0.c0.m1
|
||||||
|
DONE=$(insert_text s0.r0.c0 '{{loop:post_date}}')
|
||||||
|
[ "$(echo "$DONE" | jq -r '.ok')" = "true" ] || fail "{{loop:post_date}} in the loop refused: $DONE"
|
||||||
|
stored_has 'loop_post_date' || fail "stored content lacks loop_post_date after the insert"
|
||||||
|
# Full form with a German date format (the select of Divi offers no German format, so "custom"): update the module.
|
||||||
|
FULL=$(variable_ref loop_post_date '{"loop_position":"","date_format":"custom","custom_date_format":"d.m.Y"}')
|
||||||
|
DONE=$(tool lit-divi-update "$(jq -cn --argjson p "$PAGE_ID" --arg r "$(tree_rev)" --arg n "$LOOP_NODE" --arg c "$FULL" \
|
||||||
|
'{post_id: $p, tree_rev: $r, changes: [{id: $n, set: {content: $c}}]}')")
|
||||||
|
[ "$(echo "$DONE" | jq -r '.ok')" = "true" ] || fail "full-form loop_post_date in the loop refused: $DONE"
|
||||||
|
stored_has 'custom_date_format' || fail "stored content lacks the date format of the full form"
|
||||||
|
# Positive control for the security boundary below: the post meta key option belongs to a post loop.
|
||||||
|
META=$(variable_ref loop_post_meta_key_manual_custom_field \
|
||||||
|
'{"select_loop_meta_key":"loop_post_meta_key_manual_custom_field_value","loop_meta_key":"lit_smoke_key"}')
|
||||||
|
DONE=$(insert_text s0.r0.c0 "$META")
|
||||||
|
[ "$(echo "$DONE" | jq -r '.ok')" = "true" ] || fail "post meta key option in a post loop refused: $DONE"
|
||||||
|
pass "loop_post_date (short and full form) and the post meta key option accepted in the post loop"
|
||||||
|
|
||||||
|
# --- 3. The same content OUTSIDE any loop is refused ---------------------------------------------------------------
|
||||||
|
BEFORE=$(stored | md5sum)
|
||||||
|
for VALUE in '{{loop:post_date}}' "$FULL"; do
|
||||||
|
BAD=$(insert_text s0.r1.c0 "$VALUE")
|
||||||
|
refused_with "$BAD" 'braucht eine Divi-Schleife' || fail "loop content outside a loop not refused with the loop message: $BAD"
|
||||||
|
refused_with "$BAD" 'loop_post_date' || fail "refusal does not name the option: $BAD"
|
||||||
|
done
|
||||||
|
# Updating the static module outside the loop is refused as well, and so is a module whose parent is the section row.
|
||||||
|
BAD=$(tool lit-divi-update "$(jq -cn --argjson p "$PAGE_ID" --arg r "$(tree_rev)" --arg c "$FULL" \
|
||||||
|
'{post_id: $p, tree_rev: $r, changes: [{id: "s0.r1.c0.m0", set: {content: $c}}]}')")
|
||||||
|
refused_with "$BAD" 'braucht eine Divi-Schleife' || fail "update outside a loop not refused: $BAD"
|
||||||
|
[ "$(stored | md5sum)" = "$BEFORE" ] || fail "a refused call changed the stored page"
|
||||||
|
pass "loop content outside a loop refused (insert short and full form, update), page unchanged"
|
||||||
|
|
||||||
|
# --- 4. A term loop refuses post-kind options (security boundary: meta keys read foreign objects) -----------------------
|
||||||
|
BEFORE=$(stored | md5sum)
|
||||||
|
POST_META=$(variable_ref loop_post_meta_key_manual_custom_field \
|
||||||
|
'{"select_loop_meta_key":"loop_post_meta_key_manual_custom_field_value","loop_meta_key":"lit_smoke_key"}')
|
||||||
|
USER_META=$(variable_ref loop_user_meta_key_manual_custom_field \
|
||||||
|
'{"select_loop_meta_key":"loop_user_meta_key_manual_custom_field_value","loop_meta_key":"lit_smoke_key"}')
|
||||||
|
for VALUE in '{{loop:post_date}}' "$FULL" "$POST_META" "$USER_META"; do
|
||||||
|
BAD=$(insert_text s0.r2.c0 "$VALUE")
|
||||||
|
refused_with "$BAD" 'passt nicht zur Schleife' || fail "post/user-kind option in a term loop not refused: $BAD"
|
||||||
|
refused_with "$BAD" 'Terme' || fail "refusal does not name the loop kind (Terme): $BAD"
|
||||||
|
done
|
||||||
|
[ "$(stored | md5sum)" = "$BEFORE" ] || fail "a refused call changed the stored page"
|
||||||
|
# The reverse direction: a user-kind option in the POST loop.
|
||||||
|
BAD=$(insert_text s0.r0.c0 "$USER_META")
|
||||||
|
refused_with "$BAD" 'passt nicht zur Schleife' || fail "user meta key option in a post loop not refused: $BAD"
|
||||||
|
# Positive control: an option of the term kind is accepted in the term loop (ADAPT (Task 3): short name term_name).
|
||||||
|
DONE=$(insert_text s0.r2.c0 '{{loop:term_name}}')
|
||||||
|
[ "$(echo "$DONE" | jq -r '.ok')" = "true" ] || fail "{{loop:term_name}} in the term loop refused: $DONE"
|
||||||
|
stored_has 'loop_term_name' || fail "stored content lacks loop_term_name"
|
||||||
|
pass "post/user-kind options (incl. meta keys) refused in the wrong loop kind, term option accepted in the term loop"
|
||||||
|
|
||||||
|
# --- 4b. A node that switches on its OWN term loop in the same call gets no loop content (fail closed) ----------------------
|
||||||
|
# Security regressions of the Task 4 review: the loop of a new node counts only once saved, and the check runs on the
|
||||||
|
# composed blocks, not on the client text (a control character inside {{ }} is stripped on write, a leading space
|
||||||
|
# before $variable( is trimmed). Both must still be refused in the same call that switches the term loop on.
|
||||||
|
BEFORE=$(stored | md5sum)
|
||||||
|
TERM_LOOP_ATTRS='{"module.advanced.loop":{"desktop":{"enable":"on","queryType":"post_taxonomies"}}}'
|
||||||
|
SNEAKY=$'{\x01{loop:post_title}}'
|
||||||
|
SPACED=" $(variable_ref loop_post_meta_key_manual_custom_field \
|
||||||
|
'{"select_loop_meta_key":"loop_post_meta_key_manual_custom_field_value","loop_meta_key":"lit_smoke_key"}')"
|
||||||
|
for VALUE in "$SNEAKY" "$SPACED"; do
|
||||||
|
BAD=$(tool lit-divi-insert "$(jq -cn --argjson p "$PAGE_ID" --arg r "$(tree_rev)" --arg c "$VALUE" --argjson a "$TERM_LOOP_ATTRS" \
|
||||||
|
'{post_id: $p, tree_rev: $r, parent: "s0.r0.c0", nodes: [{type: "text", content: $c, attrs: $a}]}')")
|
||||||
|
echo "$BAD" | jq -e 'has("__error")' >/dev/null || fail "loop content under a loop of the same call was accepted: $BAD"
|
||||||
|
done
|
||||||
|
[ "$(stored | md5sum)" = "$BEFORE" ] || fail "a refused call changed the stored page"
|
||||||
|
pass "loop content (control character inside the braces, leading space before \$variable) refused under a loop of the same call"
|
||||||
|
|
||||||
|
# --- 5. lit/divi-dynamic-sources per node -------------------------------------------------------------------------
|
||||||
|
# ADAPT (Task 5): input post_type + post_id + node; the answer lists the loop options; without a loop context it says so.
|
||||||
|
sources() { ability lit/divi-dynamic-sources "$(jq -cn --argjson p "$PAGE_ID" --arg n "$1" '{post_type: "page", post_id: $p, node: $n}')"; }
|
||||||
|
IN_LOOP=$(sources "$LOOP_NODE")
|
||||||
|
IN_LOOP_NAMES=$(loop_names "$IN_LOOP")
|
||||||
|
has_line "$IN_LOOP_NAMES" loop_post_date || fail "no loop_post_date for the module in the post loop: $IN_LOOP"
|
||||||
|
has_line "$IN_LOOP_NAMES" loop_post_meta_key_manual_custom_field || fail "no post meta key option in the post loop: $IN_LOOP"
|
||||||
|
! has_prefix "$IN_LOOP_NAMES" 'loop_term_\|^loop_user_' || fail "post loop lists term/user options: $IN_LOOP"
|
||||||
|
IN_TERM=$(sources s0.r2.c0.m0)
|
||||||
|
IN_TERM_NAMES=$(loop_names "$IN_TERM")
|
||||||
|
has_line "$IN_TERM_NAMES" loop_term_name || fail "no loop_term_name for the module in the term loop: $IN_TERM"
|
||||||
|
! has_prefix "$IN_TERM_NAMES" loop_post_ || fail "term loop lists post options: $IN_TERM"
|
||||||
|
OUTSIDE=$(sources s0.r1.c0.m0)
|
||||||
|
[ -z "$(loop_names "$OUTSIDE")" ] || fail "loop options listed for a node outside any loop: $OUTSIDE"
|
||||||
|
[[ "$OUTSIDE" == *'Schleifen-Kontext'* ]] || fail "no hint about the missing loop context: $OUTSIDE"
|
||||||
|
pass "dynamic sources: post options in the post loop, term options in the term loop, none outside"
|
||||||
|
|
||||||
|
# --- 7. Frontend render (before the move: afterwards the module is outside the loop and renders empty) ------------------
|
||||||
|
# At least one published post must exist; otherwise one temporary post is created (and deleted by exact ID).
|
||||||
|
if [ "$(wp post list --post_type=post --post_status=publish --format=count)" = "0" ]; then
|
||||||
|
TEMP_POST_ID=$(wp post create --post_type=post --post_status=publish --post_title="LIT Smoke $RUN Beitrag" --porcelain)
|
||||||
|
fi
|
||||||
|
HTML=$(LIT_ID="$PAGE_ID" wp eval 'global $post; $post = get_post((int) getenv("LIT_ID")); setup_postdata($post); echo apply_filters("the_content", $post->post_content);' 2>&1)
|
||||||
|
[ -n "$HTML" ] || fail "the page rendered nothing"
|
||||||
|
if grep -Eqi 'Fatal error|Parse error|Warning:|Notice:|Deprecated:|Stack trace|Uncaught' <<<"$HTML"; then
|
||||||
|
fail "PHP error text in the rendered page: $(grep -Eio '.{0,80}(Fatal error|Parse error|Warning:|Notice:|Deprecated:|Stack trace|Uncaught).{0,120}' <<<"$HTML" | head -3)"
|
||||||
|
fi
|
||||||
|
[[ "$HTML" != *'$variable('* ]] || fail "an unresolved \$variable reference is in the rendered page"
|
||||||
|
[[ "$HTML" != *loop_post_date* ]] || fail "the option name loop_post_date is in the rendered page"
|
||||||
|
# The module renders the date of a published post in d.m.Y (the loop shows up to 3 of them, newest first).
|
||||||
|
DATES=$(wp eval 'foreach (get_posts(["post_type" => "post", "post_status" => "publish", "numberposts" => -1, "fields" => "ids"]) as $i) { echo get_the_date("d.m.Y", $i), "\n"; }')
|
||||||
|
[ -n "$DATES" ] || fail "no published post to compare against"
|
||||||
|
grep -qF -f <(echo "$DATES") <<<"$HTML" \
|
||||||
|
|| fail "the rendered page shows no formatted date (d.m.Y) of a published post; dates: $(echo "$DATES" | head -3 | tr '\n' ' ')"
|
||||||
|
pass "frontend render shows a formatted post date, no PHP error text"
|
||||||
|
|
||||||
|
# --- 6. Moving loop content out of the loop: warning, not refusal ----------------------------------------------------
|
||||||
|
# ADAPT (Task 4): the warning is a string in .warnings that names the loop content ("Schleife").
|
||||||
|
MOVED=$(tool lit-divi-move "$(jq -cn --argjson p "$PAGE_ID" --arg r "$(tree_rev)" --arg n "$LOOP_NODE" \
|
||||||
|
'{post_id: $p, tree_rev: $r, id: $n, parent: "s0.r1.c0"}')")
|
||||||
|
[ "$(echo "$MOVED" | jq -r '.ok')" = "true" ] || fail "moving loop content out of the loop was refused: $MOVED"
|
||||||
|
echo "$MOVED" | jq -e '(.warnings // []) | map(select(test("Schleife"))) | length > 0' >/dev/null \
|
||||||
|
|| fail "move out of the loop carries no warning about loop content: $MOVED"
|
||||||
|
stored_has 'loop_post_date' || fail "the moved module lost its loop content"
|
||||||
|
pass "move out of the loop answers ok with a loop warning"
|
||||||
|
|
||||||
|
# --- 6b. Switching the loop kind under unchanged loop content: ok with a warning ---------------------------------------------
|
||||||
|
# The post meta key module (s0.r0.c0.m1 after the move) keeps loop_post_meta_key_*; the container becomes a term loop.
|
||||||
|
DONE=$(tool lit-divi-update "$(jq -cn --argjson p "$PAGE_ID" --arg r "$(tree_rev)" --argjson a "$TERM_LOOP_ATTRS" \
|
||||||
|
'{post_id: $p, tree_rev: $r, changes: [{id: "s0.r0.c0", attrs: $a}]}')")
|
||||||
|
[ "$(echo "$DONE" | jq -r '.ok')" = "true" ] || fail "switching the loop kind was refused: $DONE"
|
||||||
|
echo "$DONE" | jq -e '(.warnings // []) | map(select(startswith("s0.r0.c0:") and contains("Schleife") and contains("loop_post_meta_key"))) | length > 0' \
|
||||||
|
>/dev/null || fail "switching the loop kind carries no warning naming the node and the loop content: $DONE"
|
||||||
|
pass "update of the loop kind under unchanged loop content answers ok with a warning naming node and option"
|
||||||
|
|
||||||
|
# --- 8. Everything restored, no leftover pages ----------------------------------------------------------------------
|
||||||
|
GONE_PAGE=$PAGE_ID
|
||||||
|
GONE_POST=$TEMP_POST_ID
|
||||||
|
delete_content
|
||||||
|
PAGE_ID=""
|
||||||
|
TEMP_POST_ID=""
|
||||||
|
[ -z "$(wp post list --post_type=any --post_status=any --post__in="$GONE_PAGE" --format=ids)" ] || fail "page $GONE_PAGE still exists"
|
||||||
|
[ -z "$GONE_POST" ] || [ -z "$(wp post list --post_type=any --post_status=any --post__in="$GONE_POST" --format=ids)" ] \
|
||||||
|
|| fail "temporary post $GONE_POST still exists"
|
||||||
|
[ -z "$(wp post list --post_type=any --post_status=any --s="LIT Smoke $RUN" --format=ids)" ] || fail "a post of this run is left"
|
||||||
|
[ "$(capture et_divi)" = "$ORIGINAL_THEME" ] || fail "et_divi differs from its state before the run"
|
||||||
|
[ "$(capture et_divi_global_variables)" = "$ORIGINAL_VARIABLES" ] || fail "et_divi_global_variables differs from its state before the run"
|
||||||
|
pass "page and temporary post deleted, options unchanged"
|
||||||
|
|
||||||
|
finish
|
||||||
Reference in New Issue
Block a user