fix(bbyy): isolate production branding from E2E defaults

This commit is contained in:
134 2026-08-20 22:12:33 +08:00
parent 1d84b1b1c0
commit d1582f33e8
11 changed files with 55 additions and 38 deletions

View File

@ -2182,7 +2182,7 @@ export function AdminSettingsClient() {
usageTimeEnabled: false, usageTimeEnabled: false,
usageTimeStart: "08:00", usageTimeStart: "08:00",
usageTimeEnd: "20:00", usageTimeEnd: "20:00",
usageTimeMessage: "由壹点累了也是需要休息的", usageTimeMessage: "BuYi 累了也是需要休息的",
defaultTheme: "system", defaultTheme: "system",
bannerEnabled: true, bannerEnabled: true,
bannerText: "限时特惠:升级会员最高立享 45% OFF!", bannerText: "限时特惠:升级会员最高立享 45% OFF!",
@ -2224,7 +2224,7 @@ export function AdminSettingsClient() {
agentWorkflowDefaultModelId: null, agentWorkflowDefaultModelId: null,
canvasDetailDefaultModelId: null, canvasDetailDefaultModelId: null,
canvasDetailAgentModelId: null, canvasDetailAgentModelId: null,
lovartComposerPrefix: "让「由壹点AI」", lovartComposerPrefix: "让「𝗕𝘂𝗬𝗶」",
lovartComposerPreviewTexts: [ lovartComposerPreviewTexts: [
"打造引人注目的社交媒体视觉", "打造引人注目的社交媒体视觉",
"帮我把这张产品图做成高级电商海报", "帮我把这张产品图做成高级电商海报",
@ -2240,8 +2240,8 @@ export function AdminSettingsClient() {
lovartPromoText: lovartPromoText:
"现在升级,立享 Kling 3.0 与 Nano Banana Pro,最高 5 折优惠", "现在升级,立享 Kling 3.0 与 Nano Banana Pro,最高 5 折优惠",
lovartPromoActionText: "立即升级", lovartPromoActionText: "立即升级",
lovartHeroTitle: "由壹点AI 让设计更简单", lovartHeroTitle: "𝗕𝘂𝗬𝗶 让设计触手可及",
lovartHeroSubtitle: "懂你的设计代理,帮你搞定一切", lovartHeroSubtitle: "下达指令,即刻呈现",
surpriseCategories: ["全部", "精选"], surpriseCategories: ["全部", "精选"],
membershipConfig: defaultMembershipConfig, membershipConfig: defaultMembershipConfig,
membershipUserOverrides: defaultMembershipUserOverrides, membershipUserOverrides: defaultMembershipUserOverrides,
@ -2302,7 +2302,7 @@ export function AdminSettingsClient() {
usageTimeStart: siteSettingsData.usageTimeStart || "08:00", usageTimeStart: siteSettingsData.usageTimeStart || "08:00",
usageTimeEnd: siteSettingsData.usageTimeEnd || "20:00", usageTimeEnd: siteSettingsData.usageTimeEnd || "20:00",
usageTimeMessage: usageTimeMessage:
siteSettingsData.usageTimeMessage || "由壹点累了也是需要休息的", siteSettingsData.usageTimeMessage || "BuYi 累了也是需要休息的",
defaultTheme: siteSettingsData.defaultTheme || "system", defaultTheme: siteSettingsData.defaultTheme || "system",
bannerEnabled: siteSettingsData.bannerEnabled ?? true, bannerEnabled: siteSettingsData.bannerEnabled ?? true,
bannerText: bannerText:
@ -2398,7 +2398,7 @@ export function AdminSettingsClient() {
(siteSettingsData as any).canvasDetailAgentModelId || null, (siteSettingsData as any).canvasDetailAgentModelId || null,
lovartComposerPrefix: lovartComposerPrefix:
String((siteSettingsData as any).lovartComposerPrefix || "").trim() || String((siteSettingsData as any).lovartComposerPrefix || "").trim() ||
"让「由壹点AI」", "让「𝗕𝘂𝗬𝗶」",
lovartComposerPreviewTexts: Array.isArray( lovartComposerPreviewTexts: Array.isArray(
siteSettingsData.lovartComposerPreviewTexts siteSettingsData.lovartComposerPreviewTexts
) )
@ -2500,9 +2500,9 @@ export function AdminSettingsClient() {
lovartPromoActionText: lovartPromoActionText:
siteSettingsData.lovartPromoActionText || "立即升级", siteSettingsData.lovartPromoActionText || "立即升级",
lovartHeroTitle: lovartHeroTitle:
siteSettingsData.lovartHeroTitle || "由壹点AI 让设计更简单", siteSettingsData.lovartHeroTitle || "𝗕𝘂𝗬𝗶 让设计触手可及",
lovartHeroSubtitle: lovartHeroSubtitle:
siteSettingsData.lovartHeroSubtitle || "懂你的设计代理,帮你搞定一切", siteSettingsData.lovartHeroSubtitle || "下达指令,即刻呈现",
surpriseCategories: Array.isArray(siteSettingsData.surpriseCategories) surpriseCategories: Array.isArray(siteSettingsData.surpriseCategories)
? siteSettingsData.surpriseCategories ? siteSettingsData.surpriseCategories
.map((item: any) => String(item).trim()) .map((item: any) => String(item).trim())
@ -10524,7 +10524,7 @@ export function AdminSettingsClient() {
lovartComposerPrefix: e.target.value.slice(0, 40), lovartComposerPrefix: e.target.value.slice(0, 40),
}) })
} }
placeholder="让「由壹点AI」" placeholder="让「𝗕𝘂𝗬𝗶」"
value={siteSettings.lovartComposerPrefix} value={siteSettings.lovartComposerPrefix}
/> />
<div className="text-muted-foreground text-xs"> <div className="text-muted-foreground text-xs">
@ -10726,7 +10726,7 @@ export function AdminSettingsClient() {
lovartHeroTitle: e.target.value, lovartHeroTitle: e.target.value,
}) })
} }
placeholder="由壹点AI 让设计更简单" placeholder="𝗕𝘂𝗬𝗶 让设计触手可及"
value={siteSettings.lovartHeroTitle} value={siteSettings.lovartHeroTitle}
/> />
</div> </div>
@ -10740,7 +10740,7 @@ export function AdminSettingsClient() {
lovartHeroSubtitle: e.target.value, lovartHeroSubtitle: e.target.value,
}) })
} }
placeholder="懂你的设计代理,帮你搞定一切" placeholder="下达指令,即刻呈现"
value={siteSettings.lovartHeroSubtitle} value={siteSettings.lovartHeroSubtitle}
/> />
</div> </div>

View File

@ -399,7 +399,7 @@ function normalizeLovartComposerPreviewTexts(value: unknown): string[] {
function normalizeLovartComposerPrefix(value: unknown): string { function normalizeLovartComposerPrefix(value: unknown): string {
const normalized = String(value || "").trim(); const normalized = String(value || "").trim();
if (!normalized) { if (!normalized) {
return "让「由壹点AI」"; return "让「𝗕𝘂𝗬𝗶」";
} }
return normalized.slice(0, 40); return normalized.slice(0, 40);
} }
@ -573,7 +573,7 @@ const PUBLIC_SITE_SETTINGS_SCOPES = new Set<string>([
]); ]);
const HOME_SITE_SETTINGS_FALLBACK: Record<string, unknown> = { const HOME_SITE_SETTINGS_FALLBACK: Record<string, unknown> = {
siteName: "AI Chatbot", siteName: "𝗕𝘂𝗬𝗶",
siteLogo: null, siteLogo: null,
siteLogoDark: null, siteLogoDark: null,
favicon: null, favicon: null,
@ -583,11 +583,11 @@ const HOME_SITE_SETTINGS_FALLBACK: Record<string, unknown> = {
bannerText: "限时特惠:升级会员最高立享 45% OFF!", bannerText: "限时特惠:升级会员最高立享 45% OFF!",
bannerLink: null, bannerLink: null,
bannerActionText: "立即查看", bannerActionText: "立即查看",
lovartHeroTitle: "由壹点AI 让设计更简单", lovartHeroTitle: "𝗕𝘂𝗬𝗶 让设计触手可及",
lovartHeroSubtitle: "懂你的设计代理,帮你搞定一切", lovartHeroSubtitle: "下达指令,即刻呈现",
surpriseCategories: ["全部", "精选"], surpriseCategories: ["全部", "精选"],
canvasDefaultModelId: null, canvasDefaultModelId: null,
lovartComposerPrefix: "让「由壹点AI」", lovartComposerPrefix: "让「𝗕𝘂𝗬𝗶」",
lovartComposerPreviewTexts: [], lovartComposerPreviewTexts: [],
lovartPromptTagVisibility: {}, lovartPromptTagVisibility: {},
contactConfig: normalizeContactConfig(undefined), contactConfig: normalizeContactConfig(undefined),
@ -664,7 +664,7 @@ async function readScopedSiteSettings(keys: string[]) {
function createBrandingSettings(settings: Record<string, unknown> | undefined) { function createBrandingSettings(settings: Record<string, unknown> | undefined) {
return { return {
siteName: String(settings?.siteName || "AI Chatbot"), siteName: String(settings?.siteName || "𝗕𝘂𝗬𝗶"),
siteLogo: settings?.siteLogo || null, siteLogo: settings?.siteLogo || null,
siteLogoDark: settings?.siteLogoDark || null, siteLogoDark: settings?.siteLogoDark || null,
favicon: settings?.favicon || null, favicon: settings?.favicon || null,
@ -822,7 +822,7 @@ async function getScopedPublicSiteSettings(
usageTimeStart: typedSettings?.usageTimeStart || "08:00", usageTimeStart: typedSettings?.usageTimeStart || "08:00",
usageTimeEnd: typedSettings?.usageTimeEnd || "20:00", usageTimeEnd: typedSettings?.usageTimeEnd || "20:00",
usageTimeMessage: usageTimeMessage:
typedSettings?.usageTimeMessage || "由壹点累了也是需要休息的", typedSettings?.usageTimeMessage || "BuYi 累了也是需要休息的",
}); });
} }
@ -953,9 +953,9 @@ async function getScopedPublicSiteSettings(
typedSettings?.lovartPromoText || typedSettings?.lovartPromoText ||
"现在升级,立享 Kling 3.0 与 Nano Banana Pro,最高 5 折优惠", "现在升级,立享 Kling 3.0 与 Nano Banana Pro,最高 5 折优惠",
lovartPromoActionText: typedSettings?.lovartPromoActionText || "立即升级", lovartPromoActionText: typedSettings?.lovartPromoActionText || "立即升级",
lovartHeroTitle: typedSettings?.lovartHeroTitle || "由壹点AI 让设计更简单", lovartHeroTitle: typedSettings?.lovartHeroTitle || "𝗕𝘂𝗬𝗶 让设计触手可及",
lovartHeroSubtitle: lovartHeroSubtitle:
typedSettings?.lovartHeroSubtitle || "懂你的设计代理,帮你搞定一切", typedSettings?.lovartHeroSubtitle || "下达指令,即刻呈现",
surpriseCategories: normalizeSurpriseCategories( surpriseCategories: normalizeSurpriseCategories(
valueByKey.get(HOME_SURPRISE_CATEGORIES_KEY) valueByKey.get(HOME_SURPRISE_CATEGORIES_KEY)
), ),
@ -1476,7 +1476,7 @@ export async function GET(request: NextRequest) {
usageTimeEnabled: false, usageTimeEnabled: false,
usageTimeStart: "08:00", usageTimeStart: "08:00",
usageTimeEnd: "20:00", usageTimeEnd: "20:00",
usageTimeMessage: "由壹点累了也是需要休息的", usageTimeMessage: "BuYi 累了也是需要休息的",
bannerEnabled: true, bannerEnabled: true,
bannerText: "限时特惠:升级会员最高立享 45% OFF!", bannerText: "限时特惠:升级会员最高立享 45% OFF!",
bannerLink: null, bannerLink: null,
@ -1525,8 +1525,8 @@ export async function GET(request: NextRequest) {
canvasDetailAgentModelId: null, canvasDetailAgentModelId: null,
lovartPromoText: "现在升级,立享 Kling 3.0 与 Nano Banana Pro,最高 5 折优惠", lovartPromoText: "现在升级,立享 Kling 3.0 与 Nano Banana Pro,最高 5 折优惠",
lovartPromoActionText: "立即升级", lovartPromoActionText: "立即升级",
lovartHeroTitle: "由壹点AI 让设计更简单", lovartHeroTitle: "𝗕𝘂𝗬𝗶 让设计触手可及",
lovartHeroSubtitle: "懂你的设计代理,帮你搞定一切", lovartHeroSubtitle: "下达指令,即刻呈现",
surpriseCategories, surpriseCategories,
aiDetailGenerationEnabled, aiDetailGenerationEnabled,
lovartComposerPrefix, lovartComposerPrefix,
@ -1546,8 +1546,8 @@ export async function GET(request: NextRequest) {
baseSettings.lovartPromoText || baseSettings.lovartPromoText ||
"现在升级,立享 Kling 3.0 与 Nano Banana Pro,最高 5 折优惠", "现在升级,立享 Kling 3.0 与 Nano Banana Pro,最高 5 折优惠",
lovartPromoActionText: baseSettings.lovartPromoActionText || "立即升级", lovartPromoActionText: baseSettings.lovartPromoActionText || "立即升级",
lovartHeroTitle: baseSettings.lovartHeroTitle || "由壹点AI 让设计更简单", lovartHeroTitle: baseSettings.lovartHeroTitle || "𝗕𝘂𝗬𝗶 让设计触手可及",
lovartHeroSubtitle: baseSettings.lovartHeroSubtitle || "懂你的设计代理,帮你搞定一切", lovartHeroSubtitle: baseSettings.lovartHeroSubtitle || "下达指令,即刻呈现",
notification, notification,
surpriseCategories, surpriseCategories,
aiDetailGenerationEnabled, aiDetailGenerationEnabled,
@ -3119,7 +3119,7 @@ export async function PUT(request: NextRequest) {
usageTimeEnabled: siteSettingsPayload.usageTimeEnabled ?? false, usageTimeEnabled: siteSettingsPayload.usageTimeEnabled ?? false,
usageTimeStart: siteSettingsPayload.usageTimeStart ?? "08:00", usageTimeStart: siteSettingsPayload.usageTimeStart ?? "08:00",
usageTimeEnd: siteSettingsPayload.usageTimeEnd ?? "20:00", usageTimeEnd: siteSettingsPayload.usageTimeEnd ?? "20:00",
usageTimeMessage: siteSettingsPayload.usageTimeMessage ?? "由壹点累了也是需要休息的", usageTimeMessage: siteSettingsPayload.usageTimeMessage ?? "BuYi 累了也是需要休息的",
bannerEnabled: siteSettingsPayload.bannerEnabled ?? true, bannerEnabled: siteSettingsPayload.bannerEnabled ?? true,
bannerText: siteSettingsPayload.bannerText ?? "限时特惠:升级会员最高立享 45% OFF!", bannerText: siteSettingsPayload.bannerText ?? "限时特惠:升级会员最高立享 45% OFF!",
bannerLink: siteSettingsPayload.bannerLink, bannerLink: siteSettingsPayload.bannerLink,
@ -3144,8 +3144,8 @@ export async function PUT(request: NextRequest) {
siteSettingsPayload.lovartPromoText ?? siteSettingsPayload.lovartPromoText ??
"现在升级,立享 Kling 3.0 与 Nano Banana Pro,最高 5 折优惠", "现在升级,立享 Kling 3.0 与 Nano Banana Pro,最高 5 折优惠",
lovartPromoActionText: siteSettingsPayload.lovartPromoActionText ?? "立即升级", lovartPromoActionText: siteSettingsPayload.lovartPromoActionText ?? "立即升级",
lovartHeroTitle: siteSettingsPayload.lovartHeroTitle ?? "由壹点AI 让设计更简单", lovartHeroTitle: siteSettingsPayload.lovartHeroTitle ?? "𝗕𝘂𝗬𝗶 让设计触手可及",
lovartHeroSubtitle: siteSettingsPayload.lovartHeroSubtitle ?? "懂你的设计代理,帮你搞定一切", lovartHeroSubtitle: siteSettingsPayload.lovartHeroSubtitle ?? "下达指令,即刻呈现",
updatedBy: session.user.id, updatedBy: session.user.id,
}) })
.returning(); .returning();

View File

@ -1334,7 +1334,7 @@ type VideoStoryboardStreamData =
// 建议卡片数据 - 已移除 // 建议卡片数据 - 已移除
const SUGGESTIONS: { title: string; desc: string; image: string }[] = []; const SUGGESTIONS: { title: string; desc: string; image: string }[] = [];
const CANVAS_COMPOSER_PREFIX_DEFAULT = "让「由壹点AI」"; const CANVAS_COMPOSER_PREFIX_DEFAULT = "让「𝗕𝘂𝗬𝗶」";
const CANVAS_COMPOSER_PREVIEW_TEXTS_DEFAULT = [ const CANVAS_COMPOSER_PREVIEW_TEXTS_DEFAULT = [
"打造引人注目的社交媒体视觉", "打造引人注目的社交媒体视觉",
"帮我把这张产品图做成高级电商海报", "帮我把这张产品图做成高级电商海报",

View File

@ -345,7 +345,7 @@ type LovartPromptTagKey = (typeof PROMPT_TAGS)[number]["key"];
type LovartPromptTagVisibility = Record<LovartPromptTagKey, boolean>; type LovartPromptTagVisibility = Record<LovartPromptTagKey, boolean>;
const FEATURED_PAGE_SIZE = 24; const FEATURED_PAGE_SIZE = 24;
const COMPOSER_PREFIX_DEFAULT = "让「由壹点AI」"; const COMPOSER_PREFIX_DEFAULT = "让「𝗕𝘂𝗬𝗶」";
function SidebarSvgIcon({ function SidebarSvgIcon({
iconUrl, iconUrl,

View File

@ -101,7 +101,7 @@ export type LovartPromptTagVisibility = Record<LovartPromptTagKey, boolean>;
export const MASONRY_HEIGHTS = [420, 290, 340, 470, 300, 360, 430, 320]; export const MASONRY_HEIGHTS = [420, 290, 340, 470, 300, 360, 430, 320];
export const FEATURED_PAGE_SIZE = 24; export const FEATURED_PAGE_SIZE = 24;
export const COMPOSER_PREFIX_DEFAULT = "让「由壹点AI」"; export const COMPOSER_PREFIX_DEFAULT = "让「𝗕𝘂𝗬𝗶」";
export function normalizeComposerPreviewTail(text: string, fixedPrefix: string) { export function normalizeComposerPreviewTail(text: string, fixedPrefix: string) {
const trimmed = text.trim(); const trimmed = text.trim();

View File

@ -29,7 +29,7 @@ export function BrandTopBar({
showBrand = true, showBrand = true,
siteName, siteName,
}: BrandTopBarProps) { }: BrandTopBarProps) {
const resolvedSiteName = String(siteName || "").trim() || "由壹点AI"; const resolvedSiteName = String(siteName || "").trim() || "𝗕𝘂𝗬𝗶";
const positionClass = const positionClass =
position === "fixed" position === "fixed"
? "fixed left-0 top-0 z-40 w-full" ? "fixed left-0 top-0 z-40 w-full"

View File

@ -1118,7 +1118,7 @@ export function StyleProWorkspace({
persistedState?.sourceImageUrl, persistedState?.sourceImageUrl,
]); ]);
const siteName = brandingData?.siteName || "由壹点AI"; const siteName = brandingData?.siteName || "𝗕𝘂𝗬𝗶";
const logo = brandingData?.siteLogoDark || brandingData?.siteLogo || ""; const logo = brandingData?.siteLogoDark || brandingData?.siteLogo || "";
const selectedOptionLabels = useMemo(() => { const selectedOptionLabels = useMemo(() => {

View File

@ -4725,8 +4725,8 @@ export async function getSiteSettings() {
canvasDetailAgentModelId: null, canvasDetailAgentModelId: null,
lovartPromoText: "现在升级,立享 Kling 3.0 与 Nano Banana Pro,最高 5 折优惠", lovartPromoText: "现在升级,立享 Kling 3.0 与 Nano Banana Pro,最高 5 折优惠",
lovartPromoActionText: "立即升级", lovartPromoActionText: "立即升级",
lovartHeroTitle: "由壹点AI 让设计更简单", lovartHeroTitle: "𝗕𝘂𝗬𝗶 让设计触手可及",
lovartHeroSubtitle: "懂你的设计代理,帮你搞定一切", lovartHeroSubtitle: "下达指令,即刻呈现",
}; };
try { try {
const [settings, videoCanvasEnabledSetting, videoCanvasSidebarEnabledSetting] = const [settings, videoCanvasEnabledSetting, videoCanvasSidebarEnabledSetting] =

View File

@ -475,7 +475,7 @@ export const siteSettings = pgTable("SiteSettings", {
usageTimeEnabled: boolean("usageTimeEnabled").notNull().default(false), // 是否启用时间限制 usageTimeEnabled: boolean("usageTimeEnabled").notNull().default(false), // 是否启用时间限制
usageTimeStart: varchar("usageTimeStart", { length: 5 }).default("08:00"), // 开始时间(HH:mm) usageTimeStart: varchar("usageTimeStart", { length: 5 }).default("08:00"), // 开始时间(HH:mm)
usageTimeEnd: varchar("usageTimeEnd", { length: 5 }).default("20:00"), // 结束时间(HH:mm) usageTimeEnd: varchar("usageTimeEnd", { length: 5 }).default("20:00"), // 结束时间(HH:mm)
usageTimeMessage: text("usageTimeMessage").default("由壹点累了也是需要休息的"), // 超时提示词 usageTimeMessage: text("usageTimeMessage").default("BuYi 累了也是需要休息的"), // 超时提示词
// 广告横幅设置 // 广告横幅设置
bannerEnabled: boolean("bannerEnabled").notNull().default(true), // 是否显示广告横幅 bannerEnabled: boolean("bannerEnabled").notNull().default(true), // 是否显示广告横幅
bannerText: text("bannerText").default("限时特惠:升级会员最高立享 45% OFF!"), // 广告横幅文字 bannerText: text("bannerText").default("限时特惠:升级会员最高立享 45% OFF!"), // 广告横幅文字
@ -505,8 +505,8 @@ export const siteSettings = pgTable("SiteSettings", {
"现在升级,立享 Kling 3.0 与 Nano Banana Pro,最高 5 折优惠" "现在升级,立享 Kling 3.0 与 Nano Banana Pro,最高 5 折优惠"
), ),
lovartPromoActionText: varchar("lovartPromoActionText", { length: 32 }).default("立即升级"), lovartPromoActionText: varchar("lovartPromoActionText", { length: 32 }).default("立即升级"),
lovartHeroTitle: text("lovartHeroTitle").default("由壹点AI 让设计更简单"), lovartHeroTitle: text("lovartHeroTitle").default("𝗕𝘂𝗬𝗶 让设计触手可及"),
lovartHeroSubtitle: text("lovartHeroSubtitle").default("懂你的设计代理,帮你搞定一切"), lovartHeroSubtitle: text("lovartHeroSubtitle").default("下达指令,即刻呈现"),
updatedAt: timestamp("updatedAt").notNull().defaultNow(), updatedAt: timestamp("updatedAt").notNull().defaultNow(),
updatedBy: uuid("updatedBy").references(() => user.id), updatedBy: uuid("updatedBy").references(() => user.id),
}); });

View File

@ -7,6 +7,11 @@ candidate_dir="$(mktemp -d "${app_dir}/.next-candidate.XXXXXX")"
previous_dir="${app_dir}/.next-previous-$(date +%Y%m%dT%H%M%S)" previous_dir="${app_dir}/.next-previous-$(date +%Y%m%dT%H%M%S)"
build_container="ai-chatbot-build-$(date +%s)" build_container="ai-chatbot-build-$(date +%s)"
if grep -Eq '^[[:space:]]*CANVAS_E2E_LOCAL[[:space:]]*=[[:space:]]*"?true"?[[:space:]]*$' "${app_dir}/.env.local"; then
echo "Refusing production deployment while CANVAS_E2E_LOCAL=true." >&2
exit 1
fi
cleanup_candidate() { cleanup_candidate() {
if [ -d "$candidate_dir" ]; then if [ -d "$candidate_dir" ]; then
rm -rf -- "$candidate_dir" rm -rf -- "$candidate_dir"

View File

@ -41,3 +41,15 @@ test("production deploy stages the main build and retains active static chunks",
); );
expect(deployScript).toContain('curl -fsS "$MAIN_INTERNAL_URL/ping"'); expect(deployScript).toContain('curl -fsS "$MAIN_INTERNAL_URL/ping"');
}); });
test("atomic production deploy rejects the local E2E fallback switch", () => {
const deployScript = readFileSync(
resolve(process.cwd(), "scripts/deploy-production-atomic.sh"),
"utf8"
);
expect(deployScript).toContain("CANVAS_E2E_LOCAL");
expect(deployScript).toContain(
"Refusing production deployment while CANVAS_E2E_LOCAL=true."
);
});