Merge branch 'master' into codex/puzzle-clear-template-runtime-fixes
This commit is contained in:
@@ -5,10 +5,10 @@ set -euo pipefail
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
用法:
|
||||
./scripts/deploy/production-api-deploy.sh --source-dir build/<version> [--version <version>] [--release-root /opt/genarrative/releases] [--current-link /opt/genarrative/current] [--service genarrative-api.service] [--health-url http://127.0.0.1:8082/healthz] [--api-env-file /etc/genarrative/api-server.env] [--database genarrative-prod] [--spacetime-server-url http://127.0.0.1:3101]
|
||||
./scripts/deploy/production-api-deploy.sh --source-dir build/<version> [--version <version>] [--release-root /opt/genarrative/releases] [--current-link /opt/genarrative/current] [--service genarrative-api.service] [--health-url http://127.0.0.1:8082/readyz] [--api-env-file /etc/genarrative/api-server.env] [--database genarrative-prod] [--spacetime-server-url http://127.0.0.1:3101]
|
||||
|
||||
说明:
|
||||
进入维护模式,校验并发布 api-server 单文件,更新 current 链接,重启 systemd 服务并执行 healthz 检查。
|
||||
进入维护模式,校验并发布 api-server 单文件,更新 current 链接,重启 systemd 服务并执行 readiness 检查。
|
||||
若传入 --database,会在重启前把 GENARRATIVE_SPACETIME_DATABASE 写入 api-server 环境文件,避免服务继续读取旧库。
|
||||
失败时保留维护模式。
|
||||
EOF
|
||||
@@ -209,6 +209,7 @@ ensure_runtime_env_and_dirs() {
|
||||
|
||||
# 旧生产环境文件会被 server-provision 保留,不一定包含新增的运行态写入路径。
|
||||
# 发布前只补缺省值,不覆盖线上已经定制过的目录或开关。
|
||||
ensure_env_value "${api_env_file}" "GENARRATIVE_API_SHUTDOWN_OUTBOX_FLUSH_TIMEOUT_MS" "5000"
|
||||
ensure_env_value "${api_env_file}" "GENARRATIVE_TRACKING_OUTBOX_ENABLED" "true"
|
||||
ensure_env_value "${api_env_file}" "GENARRATIVE_TRACKING_OUTBOX_DIR" "/var/lib/genarrative/tracking-outbox"
|
||||
ensure_env_value "${api_env_file}" "GENARRATIVE_TRACKING_OUTBOX_BATCH_SIZE" "500"
|
||||
@@ -228,7 +229,7 @@ VERSION=""
|
||||
RELEASE_ROOT="/opt/genarrative/releases"
|
||||
CURRENT_LINK="/opt/genarrative/current"
|
||||
SERVICE_NAME="genarrative-api.service"
|
||||
HEALTH_URL="http://127.0.0.1:8082/healthz"
|
||||
HEALTH_URL="http://127.0.0.1:8082/readyz"
|
||||
API_ENV_FILE="/etc/genarrative/api-server.env"
|
||||
DATABASE=""
|
||||
SPACETIME_SERVER_URL=""
|
||||
@@ -362,7 +363,7 @@ ln -sfn "${RELEASE_DIR}" "${CURRENT_LINK}"
|
||||
echo "[production-api-deploy] 重启服务: ${SERVICE_NAME}"
|
||||
systemctl restart "${SERVICE_NAME}"
|
||||
|
||||
echo "[production-api-deploy] 等待 healthz: ${HEALTH_URL}"
|
||||
echo "[production-api-deploy] 等待 readiness: ${HEALTH_URL}"
|
||||
for _ in {1..30}; do
|
||||
if curl -fsS "${HEALTH_URL}" >/dev/null; then
|
||||
"${SCRIPT_DIR}/maintenance-off.sh"
|
||||
@@ -373,5 +374,5 @@ for _ in {1..30}; do
|
||||
sleep 2
|
||||
done
|
||||
|
||||
echo "[production-api-deploy] healthz 检查超时: ${HEALTH_URL}" >&2
|
||||
echo "[production-api-deploy] readiness 检查超时: ${HEALTH_URL}" >&2
|
||||
exit 1
|
||||
|
||||
@@ -28,7 +28,7 @@ if [[ -z "${RUSTUP_HOME:-}" && -n "${ORIGINAL_HOME}" && -d "${ORIGINAL_HOME}/.ru
|
||||
fi
|
||||
|
||||
# HOME 会在下面切到组件级缓存目录,因此这里先把真实用户的 Rust 工具链目录补进 PATH。
|
||||
# Server-Provision 通过 cargo install 安装的 sccache 通常会落在 /root/.cargo/bin。
|
||||
# Jenkins 构建节点预装的 Rust 工具和 sccache 通常会落在 /root/.cargo/bin。
|
||||
for tool_dir in "${ORIGINAL_HOME}/.cargo/bin" /root/.cargo/bin /usr/local/cargo/bin; do
|
||||
if [[ -d "${tool_dir}" && ":${PATH}:" != *":${tool_dir}:"* ]]; then
|
||||
export PATH="${tool_dir}:${PATH}"
|
||||
|
||||
@@ -4,6 +4,10 @@ set -euo pipefail
|
||||
PROVISION_TOOLS_DIR="${PROVISION_TOOLS_DIR:-provision-tools}"
|
||||
SPACETIME_BIN_SOURCE="${SPACETIME_BIN_SOURCE:-${PROVISION_TOOLS_DIR}/spacetime/spacetime}"
|
||||
OTELCOL_BIN_SOURCE="${OTELCOL_BIN_SOURCE:-${PROVISION_TOOLS_DIR}/otelcol-contrib}"
|
||||
GENARRATIVE_OPENSSL_VERSION="${GENARRATIVE_OPENSSL_VERSION:-3.2.0}"
|
||||
GENARRATIVE_OPENSSL_PREFIX="${GENARRATIVE_OPENSSL_PREFIX:-/opt/genarrative/openssl-3.2.0}"
|
||||
GENARRATIVE_OPENSSL_SOURCE_URL="${GENARRATIVE_OPENSSL_SOURCE_URL:-https://github.com/openssl/openssl/releases/download/openssl-${GENARRATIVE_OPENSSL_VERSION}/openssl-${GENARRATIVE_OPENSSL_VERSION}.tar.gz}"
|
||||
GENARRATIVE_OPENSSL_SOURCE_SHA256="${GENARRATIVE_OPENSSL_SOURCE_SHA256:-14c826f07c7e433706fb5c69fa9e25dab95684844b4c962a2cf1bf183eb4690e}"
|
||||
|
||||
require_non_root_relative_path() {
|
||||
local label="$1"
|
||||
@@ -27,6 +31,14 @@ require_path() {
|
||||
fi
|
||||
}
|
||||
|
||||
require_cmd() {
|
||||
local name="$1"
|
||||
if ! command -v "${name}" >/dev/null 2>&1; then
|
||||
echo "[server-provision] 缺少命令: ${name}" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
normalize_server_aliases() {
|
||||
printf "%s" "${SERVER_ALIASES:-}" | tr ',' ' ' | xargs
|
||||
}
|
||||
@@ -56,6 +68,18 @@ run_cmd() {
|
||||
fi
|
||||
}
|
||||
|
||||
require_root_for_real_provision() {
|
||||
if [[ "${DRY_RUN}" == "true" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "$(id -u)" != "0" ]]; then
|
||||
echo "[server-provision] 非 dry-run 会安装系统包、写入 systemd/Nginx 和创建系统用户,必须在 root agent 上执行。" >&2
|
||||
echo "[server-provision] 当前用户: $(id -un) uid=$(id -u)。请确认 DEPLOY_TARGET=${DEPLOY_TARGET:-} 对应的目标服务器 agent 以 root 运行,或保持 DRY_RUN=true。" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
install_file() {
|
||||
local source="$1"
|
||||
local target="$2"
|
||||
@@ -66,21 +90,6 @@ install_file() {
|
||||
fi
|
||||
}
|
||||
|
||||
install_build_dependencies() {
|
||||
echo "[server-provision] 安装 Linux 构建依赖: clang, lld, pkg-config, OpenSSL headers"
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
run_cmd apt-get update
|
||||
run_cmd apt-get install -y clang lld pkg-config libssl-dev ca-certificates
|
||||
elif command -v dnf >/dev/null 2>&1; then
|
||||
run_cmd dnf install -y clang lld pkgconf-pkg-config openssl-devel ca-certificates
|
||||
elif command -v yum >/dev/null 2>&1; then
|
||||
run_cmd yum install -y clang lld pkgconf-pkg-config openssl-devel ca-certificates
|
||||
else
|
||||
echo "[server-provision] 未找到 apt-get/dnf/yum,无法自动安装 clang/lld。请手动安装后重跑构建。" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
install_nginx_brotli_modules() {
|
||||
echo "[server-provision] 安装 Nginx Brotli 动态模块依赖"
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
@@ -90,39 +99,111 @@ install_nginx_brotli_modules() {
|
||||
fi
|
||||
}
|
||||
|
||||
install_sccache() {
|
||||
for tool_dir in "${HOME:-}/.cargo/bin" /root/.cargo/bin /usr/local/cargo/bin; do
|
||||
if [[ -d "${tool_dir}" && ":${PATH}:" != *":${tool_dir}:"* ]]; then
|
||||
export PATH="${tool_dir}:${PATH}"
|
||||
download_file() {
|
||||
local url="$1"
|
||||
local output="$2"
|
||||
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
curl -fsSL --retry 3 --retry-delay 2 "${url}" -o "${output}"
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -O "${output}" "${url}"
|
||||
else
|
||||
echo "[server-provision] 需要 curl 或 wget 下载: ${url}" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
openssl_lib_dir_candidates() {
|
||||
printf "%s\n" \
|
||||
"${GENARRATIVE_OPENSSL_PREFIX}/lib64" \
|
||||
"${GENARRATIVE_OPENSSL_PREFIX}/lib"
|
||||
}
|
||||
|
||||
find_genarrative_openssl_lib_dir() {
|
||||
local lib_dir
|
||||
while IFS= read -r lib_dir; do
|
||||
if [[ -f "${lib_dir}/libssl.so.3" && -f "${lib_dir}/libcrypto.so.3" ]]; then
|
||||
printf "%s" "${lib_dir}"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
done < <(openssl_lib_dir_candidates)
|
||||
return 1
|
||||
}
|
||||
|
||||
if command -v sccache >/dev/null 2>&1; then
|
||||
echo "[server-provision] sccache 已存在: $(command -v sccache)"
|
||||
return
|
||||
genarrative_openssl_has_required_symbol() {
|
||||
local lib_dir
|
||||
lib_dir="$(find_genarrative_openssl_lib_dir 2>/dev/null || true)"
|
||||
if [[ -z "${lib_dir}" ]]; then
|
||||
return 1
|
||||
fi
|
||||
grep -a -q "OPENSSL_${GENARRATIVE_OPENSSL_VERSION}" "${lib_dir}/libssl.so.3"
|
||||
}
|
||||
|
||||
if [[ -x /root/.cargo/bin/sccache ]]; then
|
||||
echo "[server-provision] sccache 已存在: /root/.cargo/bin/sccache"
|
||||
return
|
||||
verify_genarrative_openssl_install() {
|
||||
local lib_dir
|
||||
lib_dir="$(find_genarrative_openssl_lib_dir 2>/dev/null || true)"
|
||||
if [[ -z "${lib_dir}" ]]; then
|
||||
echo "[server-provision] OpenSSL ${GENARRATIVE_OPENSSL_VERSION} 安装后缺少 libssl.so.3/libcrypto.so.3: ${GENARRATIVE_OPENSSL_PREFIX}" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -a -q "OPENSSL_${GENARRATIVE_OPENSSL_VERSION}" "${lib_dir}/libssl.so.3"; then
|
||||
echo "[server-provision] OpenSSL 动态库缺少 OPENSSL_${GENARRATIVE_OPENSSL_VERSION} 符号: ${lib_dir}/libssl.so.3" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! env "LD_LIBRARY_PATH=${lib_dir}" "${GENARRATIVE_OPENSSL_PREFIX}/bin/openssl" version | grep -q "OpenSSL ${GENARRATIVE_OPENSSL_VERSION}"; then
|
||||
echo "[server-provision] OpenSSL ${GENARRATIVE_OPENSSL_VERSION} 安装后命令验证失败: ${GENARRATIVE_OPENSSL_PREFIX}/bin/openssl" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "[server-provision] OpenSSL ${GENARRATIVE_OPENSSL_VERSION} 已就绪: ${lib_dir}"
|
||||
}
|
||||
|
||||
echo "[server-provision] 未找到 sccache,准备通过 cargo install sccache 安装。"
|
||||
install_genarrative_openssl_runtime() {
|
||||
local tmp_dir archive source_dir jobs lib_dir
|
||||
|
||||
echo "[server-provision] 检查 api-server/libcurl 运行时 OpenSSL ${GENARRATIVE_OPENSSL_VERSION}"
|
||||
if [[ "${DRY_RUN}" == "true" ]]; then
|
||||
echo "+ cargo install sccache --locked"
|
||||
echo "+ install OpenSSL ${GENARRATIVE_OPENSSL_VERSION} into ${GENARRATIVE_OPENSSL_PREFIX}"
|
||||
echo "+ verify OPENSSL_${GENARRATIVE_OPENSSL_VERSION} symbol for api-server/libcurl"
|
||||
return
|
||||
fi
|
||||
|
||||
if ! command -v cargo >/dev/null 2>&1; then
|
||||
echo "[server-provision] 未找到 cargo,无法自动安装 sccache。请先安装 Rust 工具链后重跑 Server-Provision。" >&2
|
||||
exit 1
|
||||
if genarrative_openssl_has_required_symbol; then
|
||||
verify_genarrative_openssl_install
|
||||
return
|
||||
fi
|
||||
|
||||
cargo install sccache --locked
|
||||
if ! command -v sccache >/dev/null 2>&1 && [[ ! -x /root/.cargo/bin/sccache ]]; then
|
||||
echo "[server-provision] sccache 安装后仍不可用,请检查 cargo bin 目录是否在 PATH 中。" >&2
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
run_cmd apt-get install -y build-essential ca-certificates curl perl tar
|
||||
else
|
||||
echo "[server-provision] 当前系统未使用 apt,无法自动构建 OpenSSL ${GENARRATIVE_OPENSSL_VERSION};请手动安装到 ${GENARRATIVE_OPENSSL_PREFIX}。" >&2
|
||||
exit 1
|
||||
fi
|
||||
require_cmd sha256sum
|
||||
require_cmd tar
|
||||
|
||||
tmp_dir="$(mktemp -d)"
|
||||
archive="${tmp_dir}/openssl-${GENARRATIVE_OPENSSL_VERSION}.tar.gz"
|
||||
echo "[server-provision] 下载 OpenSSL ${GENARRATIVE_OPENSSL_VERSION}: ${GENARRATIVE_OPENSSL_SOURCE_URL}"
|
||||
download_file "${GENARRATIVE_OPENSSL_SOURCE_URL}" "${archive}"
|
||||
printf "%s %s\n" "${GENARRATIVE_OPENSSL_SOURCE_SHA256}" "${archive}" | sha256sum -c -
|
||||
|
||||
tar -xzf "${archive}" -C "${tmp_dir}"
|
||||
source_dir="${tmp_dir}/openssl-${GENARRATIVE_OPENSSL_VERSION}"
|
||||
jobs="$(nproc 2>/dev/null || echo 2)"
|
||||
(
|
||||
cd "${source_dir}"
|
||||
./config --prefix="${GENARRATIVE_OPENSSL_PREFIX}" --openssldir="${GENARRATIVE_OPENSSL_PREFIX}/ssl" shared
|
||||
make -j "${jobs}"
|
||||
make install_sw
|
||||
)
|
||||
rm -rf "${tmp_dir}"
|
||||
|
||||
lib_dir="$(find_genarrative_openssl_lib_dir 2>/dev/null || true)"
|
||||
if [[ -n "${lib_dir}" ]]; then
|
||||
chmod 0755 "${GENARRATIVE_OPENSSL_PREFIX}" "${lib_dir}" || true
|
||||
chmod 0644 "${lib_dir}/libssl.so.3" "${lib_dir}/libcrypto.so.3" || true
|
||||
fi
|
||||
verify_genarrative_openssl_install
|
||||
}
|
||||
|
||||
sync_otelcol_install() {
|
||||
@@ -142,7 +223,7 @@ sync_otelcol_install() {
|
||||
|
||||
if [[ ! -x "${resolved_source}" ]]; then
|
||||
echo "[server-provision] otelcol-contrib 不存在或不可执行: ${source_bin}" >&2
|
||||
echo "[server-provision] 请先在构建机准备好 otelcol-contrib ${version},再通过 provision-tools 上传到目标机。" >&2
|
||||
echo "[server-provision] 请确认 Prepare Provision Tools 已在目标 agent 生成 otelcol-contrib ${version}: ${source_bin}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -671,9 +752,8 @@ require_non_root_relative_path "PROVISION_TOOLS_DIR" "${PROVISION_TOOLS_DIR}"
|
||||
echo "[server-provision] target=${DEPLOY_TARGET}, dry_run=${DRY_RUN}, nginx_config_mode=${NGINX_CONFIG_MODE}, source_commit=$(cat .jenkins-source-commit)"
|
||||
|
||||
run_cmd id
|
||||
install_build_dependencies
|
||||
require_root_for_real_provision
|
||||
install_nginx_brotli_modules
|
||||
install_sccache
|
||||
run_cmd mkdir -p "${SPACETIME_ROOT}" "${RELEASE_ROOT}" "$(dirname "${CURRENT_LINK}")" "$(dirname "${WEB_LINK}")" /etc/genarrative /var/lib/genarrative/maintenance /var/lib/genarrative/auth /var/lib/genarrative/tracking-outbox /var/lib/genarrative/database-backups
|
||||
|
||||
if ! id spacetimedb >/dev/null 2>&1; then
|
||||
@@ -690,6 +770,7 @@ fi
|
||||
|
||||
run_cmd chown -R spacetimedb:spacetimedb "${SPACETIME_ROOT}"
|
||||
run_cmd chown -R genarrative:genarrative /opt/genarrative /var/lib/genarrative /srv/genarrative
|
||||
install_genarrative_openssl_runtime
|
||||
|
||||
if [[ ! -x "${SPACETIME_BIN_SOURCE}" ]]; then
|
||||
echo "[server-provision] spacetime CLI 不存在或不可执行: ${SPACETIME_BIN_SOURCE}" >&2
|
||||
|
||||
@@ -17,18 +17,24 @@ type MiniProgramPage = {
|
||||
data: Record<string, unknown>;
|
||||
setData: (patch: Record<string, unknown>) => void;
|
||||
onLoad: (query?: Record<string, string>) => Promise<void>;
|
||||
onShareAppMessage: () => Record<string, unknown>;
|
||||
onShareTimeline: () => Record<string, unknown>;
|
||||
onShow: () => void;
|
||||
consumePayResult: () => void;
|
||||
};
|
||||
|
||||
function createWxMock() {
|
||||
return {
|
||||
getAccountInfoSync: vi.fn(() => ({
|
||||
miniProgram: { envVersion: 'release' },
|
||||
})),
|
||||
getStorageSync: vi.fn(() => ''),
|
||||
getSystemInfoSync: vi.fn(() => ({ platform: 'ios' })),
|
||||
login: vi.fn(),
|
||||
navigateBack: vi.fn(),
|
||||
removeStorageSync: vi.fn(),
|
||||
request: vi.fn(),
|
||||
showShareMenu: vi.fn(),
|
||||
setStorageSync: vi.fn(),
|
||||
};
|
||||
}
|
||||
@@ -54,6 +60,8 @@ function loadWebViewPage(
|
||||
if (requestPath === '../../config') {
|
||||
return {
|
||||
API_BASE_URL: 'https://www.genarrative.world/',
|
||||
DEV_API_BASE_URL: 'https://dev.genarrative.world/',
|
||||
DEV_WEB_VIEW_ENTRY_URL: 'https://dev.genarrative.world/',
|
||||
MINI_PROGRAM_APP_ID: 'wx-test-app',
|
||||
MINI_PROGRAM_ENV: 'release',
|
||||
WEB_VIEW_ENTRY_URL: 'https://www.genarrative.world/',
|
||||
@@ -91,7 +99,7 @@ describe('mini-program web-view auth page', () => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test('默认进入时刷新微信小程序登录态后打开 web-view', async () => {
|
||||
test('默认进入时不预登录,直接打开未登录 web-view', async () => {
|
||||
const wxMock = createWxMock();
|
||||
wxMock.login.mockImplementation(({ success }) => {
|
||||
success({ code: 'wx-login-code' });
|
||||
@@ -109,19 +117,58 @@ describe('mini-program web-view auth page', () => {
|
||||
|
||||
await page.onLoad({});
|
||||
|
||||
expect(wxMock.login).toHaveBeenCalledTimes(1);
|
||||
expect(wxMock.request).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
url: 'https://www.genarrative.world/api/auth/wechat/miniprogram-login',
|
||||
method: 'POST',
|
||||
data: { code: 'wx-login-code' },
|
||||
}),
|
||||
);
|
||||
expect(wxMock.login).not.toHaveBeenCalled();
|
||||
expect(wxMock.request).not.toHaveBeenCalled();
|
||||
expect(page.data.loading).toBe(false);
|
||||
expect(page.data.phoneBindingRequired).toBe(false);
|
||||
expect(page.data.webViewUrl).toBe(
|
||||
'https://www.genarrative.world/?clientType=mini_program&clientRuntime=wechat_mini_program#auth_provider=wechat&auth_token=jwt-active-wechat&auth_binding_status=active',
|
||||
'https://www.genarrative.world/?clientType=mini_program&clientRuntime=wechat_mini_program',
|
||||
);
|
||||
expect(wxMock.showShareMenu).toHaveBeenCalledWith({
|
||||
withShareTicket: true,
|
||||
menus: ['shareAppMessage', 'shareTimeline'],
|
||||
});
|
||||
});
|
||||
|
||||
test('默认进入时即便微信新身份待绑手机号,也不弹出绑定手机号页', async () => {
|
||||
const wxMock = createWxMock();
|
||||
wxMock.login.mockImplementation(({ success }) => {
|
||||
success({ code: 'wx-login-code' });
|
||||
});
|
||||
wxMock.request.mockImplementation(({ success }) => {
|
||||
success({
|
||||
statusCode: 200,
|
||||
data: {
|
||||
token: 'jwt-pending-wechat',
|
||||
bindingStatus: 'pending_bind_phone',
|
||||
},
|
||||
});
|
||||
});
|
||||
const page = loadWebViewPage(wxMock);
|
||||
|
||||
await page.onLoad({});
|
||||
|
||||
expect(wxMock.login).not.toHaveBeenCalled();
|
||||
expect(wxMock.request).not.toHaveBeenCalled();
|
||||
expect(page.data.loading).toBe(false);
|
||||
expect(page.data.phoneBindingRequired).toBe(false);
|
||||
expect(page.data.webViewUrl).toBe(
|
||||
'https://www.genarrative.world/?clientType=mini_program&clientRuntime=wechat_mini_program',
|
||||
);
|
||||
});
|
||||
|
||||
test('web-view 页面分享好友和朋友圈都回到小程序 web-view 入口', () => {
|
||||
const wxMock = createWxMock();
|
||||
const page = loadWebViewPage(wxMock);
|
||||
|
||||
expect(page.onShareAppMessage()).toEqual({
|
||||
title: '陶泥儿',
|
||||
path: '/pages/web-view/index',
|
||||
});
|
||||
expect(page.onShareTimeline()).toEqual({
|
||||
title: '陶泥儿',
|
||||
query: '',
|
||||
});
|
||||
});
|
||||
|
||||
test('默认匿名进入 web-view 仍不依赖 API_BASE_URL 配置', async () => {
|
||||
@@ -140,6 +187,51 @@ describe('mini-program web-view auth page', () => {
|
||||
);
|
||||
});
|
||||
|
||||
test('体验版自动切到 dev 子域名并透传 trial 环境', async () => {
|
||||
const wxMock = createWxMock();
|
||||
wxMock.getAccountInfoSync.mockReturnValue({
|
||||
miniProgram: { envVersion: 'trial' },
|
||||
});
|
||||
const page = loadWebViewPage(wxMock);
|
||||
|
||||
await page.onLoad({});
|
||||
|
||||
expect(page.data.webViewUrl).toBe(
|
||||
'https://dev.genarrative.world/?clientType=mini_program&clientRuntime=wechat_mini_program&miniProgramEnv=trial',
|
||||
);
|
||||
});
|
||||
|
||||
test('开发版自动切到 dev 子域名并把 develop 规整为 dev', async () => {
|
||||
const wxMock = createWxMock();
|
||||
wxMock.getAccountInfoSync.mockReturnValue({
|
||||
miniProgram: { envVersion: 'develop' },
|
||||
});
|
||||
wxMock.login.mockImplementation(({ success }) => {
|
||||
success({ code: 'wx-login-code' });
|
||||
});
|
||||
wxMock.request.mockImplementation(({ success }) => {
|
||||
success({
|
||||
statusCode: 200,
|
||||
data: {
|
||||
token: 'jwt-pending-wechat',
|
||||
bindingStatus: 'pending_bind_phone',
|
||||
},
|
||||
});
|
||||
});
|
||||
const page = loadWebViewPage(wxMock);
|
||||
|
||||
await page.onLoad({ authAction: 'login', returnTo: 'previous' });
|
||||
|
||||
expect(wxMock.request).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
url: 'https://dev.genarrative.world/api/auth/wechat/miniprogram-login',
|
||||
header: expect.objectContaining({
|
||||
'x-mini-program-env': 'dev',
|
||||
}),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test('onShow 二次检查支付结果并写回 web-view hash', () => {
|
||||
const wxMock = createWxMock();
|
||||
wxMock.getStorageSync.mockImplementation((key) =>
|
||||
|
||||
Reference in New Issue
Block a user