[TBID:ECX-9128] fix: sync decoration preview locale path

This commit is contained in:
lukaijie
2026-07-08 14:56:25 +08:00
parent e30a074829
commit a21effc855
2 changed files with 146 additions and 2 deletions

View File

@@ -0,0 +1,114 @@
import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import path from 'node:path'
import test from 'node:test'
const root = process.cwd()
const read = (filePath) => readFileSync(path.resolve(root, filePath), 'utf8')
function loadDecorationMessenger() {
const pageTypesSource = read('src/components/sp-web-decoration/utils/pageTypes.js').replace(
/export\s+/g,
''
)
const postMessageSource = read('src/components/sp-web-decoration/utils/postMessage.js')
.replace(/import\s+\{[^}]+\}\s+from\s+'\.\/pageTypes'\n/, '')
.replace(/export\s+default\s+\{[\s\S]*$/, '')
.replace(/export\s+/g, '')
return new Function(
`${pageTypesSource}\n${postMessageSource}\nreturn { createDecorationMessenger }`
)()
}
function setupWindow(lang) {
globalThis.window = {
location: { href: 'https://admin.example.test/admin/decoration' },
localStorage: {
getItem(key) {
return key === 'lang' ? lang : null
}
},
addEventListener() {},
removeEventListener() {}
}
}
test.afterEach(() => {
delete globalThis.window
})
function previewUrlFor(lang, options = {}) {
setupWindow(lang)
const { createDecorationMessenger } = loadDecorationMessenger()
const messenger = createDecorationMessenger('https://shop.example.test/store?foo=bar')
return new URL(
messenger.getPreviewUrl({
pageType: 'home',
templateId: undefined,
...options
})
)
}
test('preview url uses /en prefix for English admin locale', () => {
const url = previewUrlFor('en')
assert.equal(url.pathname, '/en')
})
test('preview url uses /ar prefix for Arabic admin locale', () => {
const url = previewUrlFor('ar')
assert.equal(url.pathname, '/ar')
})
test('preview url keeps root path for zhcn admin locale', () => {
const url = previewUrlFor('zhcn')
assert.equal(url.pathname, '/')
})
test('preview url preserves locale prefix for custom page', () => {
const url = previewUrlFor('en', { pageType: 'custom', templateId: 'abc' })
assert.equal(url.pathname, '/en/custom/abc')
})
test('preview url preserves query params', () => {
const url = previewUrlFor('en', { pageType: 'product_list' })
assert.equal(url.pathname, '/en/collections/all')
assert.equal(url.searchParams.get('foo'), 'bar')
assert.equal(url.searchParams.get('designMode'), '1')
assert.equal(url.searchParams.get('pageType'), 'product_list')
assert.equal(url.searchParams.get('pageId'), 'product_list')
})
test('locale path does not change postMessage payloads or target origin', () => {
setupWindow('en')
const { createDecorationMessenger } = loadDecorationMessenger()
const messenger = createDecorationMessenger('https://shop.example.test/base')
const calls = []
const iframeWindow = {
postMessage(message, targetOrigin) {
calls.push({ message, targetOrigin })
}
}
const initPayload = { sections: [{ id: 'hero' }] }
const updatePayload = { selected: { sectionId: 'hero' } }
messenger.sendInit(iframeWindow, initPayload)
messenger.sendUpdate(iframeWindow, updatePayload)
assert.deepEqual(calls, [
{
message: { type: 'DECORATION_INIT', payload: initPayload },
targetOrigin: 'https://shop.example.test'
},
{
message: { type: 'DECORATION_UPDATE', payload: updatePayload },
targetOrigin: 'https://shop.example.test'
}
])
})

View File

@@ -1,5 +1,33 @@
import { normalizeDecorationPageType, resolveDecorationPreviewPath } from './pageTypes'
const ADMIN_TO_WEB_LOCALE_PREFIX = {
en: '/en',
ar: '/ar',
zhcn: '',
zhtw: ''
}
function getCurrentAdminLang() {
if (typeof window === 'undefined') return ''
try {
return String(window.localStorage?.getItem('lang') || '').toLowerCase()
} catch {
return ''
}
}
function resolveWebLocalePrefix(lang = getCurrentAdminLang()) {
return ADMIN_TO_WEB_LOCALE_PREFIX[lang] || ''
}
function joinPreviewPath(localePrefix, routePath) {
const prefix = String(localePrefix || '').replace(/\/+$/, '')
const path = String(routePath || '/')
if (!prefix) return path || '/'
const suffix = path.replace(/^\/+/, '')
return suffix ? `${prefix}/${suffix}` : prefix
}
function resolvePreviewWebsiteOrigin(websiteUrl) {
if (!websiteUrl) return ''
try {
@@ -66,7 +94,8 @@ export function createDecorationMessenger(websiteUrl) {
if (!base.pathname || base.pathname === '') {
base.pathname = '/'
}
base.pathname = resolveDecorationPreviewPath(normalizedPageType, pageId)
const routePath = resolveDecorationPreviewPath(normalizedPageType, pageId)
base.pathname = joinPreviewPath(resolveWebLocalePrefix(), routePath)
base.searchParams.set('designMode', '1')
base.searchParams.set('pageType', normalizedPageType)
base.searchParams.set('pageId', String(pageId))
@@ -78,7 +107,8 @@ export function createDecorationMessenger(websiteUrl) {
pageType: String(normalizedPageType),
pageId: String(pageId)
})
const path = resolveDecorationPreviewPath(normalizedPageType, pageId).replace(/\/$/, '')
const routePath = resolveDecorationPreviewPath(normalizedPageType, pageId)
const path = joinPreviewPath(resolveWebLocalePrefix(), routePath).replace(/\/$/, '')
return `${originOnly}${path}/?${qs.toString()}`
}
}