样式修改
This commit is contained in:
@@ -12,7 +12,7 @@ import { createStyleFixture } from "./style-fixtures";
|
||||
|
||||
// Bundle the actual React provider, dialogs, header/footer and encrypted media
|
||||
// hooks. The ephemeral server and browser request policy isolate all writes,
|
||||
// destinations and analytics; no original business JS or template runtime runs.
|
||||
// and destinations; no original business JS or template runtime runs.
|
||||
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
||||
const temporary = await mkdtemp(join(tmpdir(), "huakui-native-site-")),
|
||||
bundle = join(temporary, "site.js");
|
||||
@@ -23,7 +23,6 @@ await build({
|
||||
contents: `
|
||||
import {createRoot} from 'react-dom/client';
|
||||
import {SiteProvider,useSite} from '@/components/providers/SiteProvider';
|
||||
import {TrackerProvider} from '@/components/analytics/TrackerProvider';
|
||||
import {SiteHeader} from '@/components/layout/SiteHeader';
|
||||
import {SiteFooter} from '@/components/layout/SiteFooter';
|
||||
import {SiteShell} from '@/components/layout/SiteShell';
|
||||
@@ -32,7 +31,7 @@ import {AppDownloadLink} from '@/components/catalog/Interactions';
|
||||
import {setAuthSession} from '@/lib/api';
|
||||
window.__setAuthSession=setAuthSession;
|
||||
const app=createRoot(document.getElementById('root'));function UserProbe(){const site=useSite();return <div style={{position:'absolute',top:150,left:10}}><output id='display-avatar' data-value={site.user?.avatar||''} data-name={site.user?.nickName||''} data-balance={site.user?.recharge||0} data-registered={String(!!site.user?.isRegister)}/></div>}
|
||||
function render(data){app.render(data.requestPath==='/navigation/'?<SiteShell view='nav' data={data}><SiteNavigationPage data={data}/></SiteShell>:<SiteProvider data={data}><TrackerProvider data={data}><SiteHeader data={data}/><UserProbe/><main style={{minHeight:900,paddingTop:100}}><h1>真实 React 共享组件隔离检查</h1><AppDownloadLink className="hk-app-cta__download" href={data.installGuide.fallbackURL}>点击下载</AppDownloadLink><button id="outside">页面按钮</button></main><SiteFooter data={data}/></TrackerProvider></SiteProvider>);}window.__rerender=render;render(window.__fixture);
|
||||
function render(data){app.render(data.requestPath==='/navigation/'?<SiteShell view='nav' data={data}><SiteNavigationPage data={data}/></SiteShell>:<SiteProvider data={data}><SiteHeader data={data}/><UserProbe/><main style={{minHeight:900,paddingTop:100}}><h1>真实 React 共享组件隔离检查</h1><AppDownloadLink className="hk-app-cta__download" href={data.installGuide.fallbackURL}>点击下载</AppDownloadLink><button id="outside">页面按钮</button></main><SiteFooter data={data}/></SiteProvider>);}window.__rerender=render;render(window.__fixture);
|
||||
`,
|
||||
},
|
||||
bundle: true,
|
||||
@@ -72,13 +71,6 @@ const server = createServer(async (request, response) => {
|
||||
response.end(await readFile(bundle));
|
||||
return;
|
||||
}
|
||||
if (path === "/static/common/web-sdk-v1.2.0.js") {
|
||||
response.setHeader("Content-Type", "application/javascript");
|
||||
response.end(
|
||||
"/* SDK mocked by the browser fixture before React mounts. */",
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (path.startsWith("/static/")) {
|
||||
const file = resolve(root, "public", "." + path);
|
||||
if (!file.startsWith(join(root, "public") + "/")) {
|
||||
@@ -151,7 +143,6 @@ const server = createServer(async (request, response) => {
|
||||
requestPath: path,
|
||||
pageKey: "home",
|
||||
pageName: "首页",
|
||||
trackerAppId: "isolated",
|
||||
isLoggedIn: user,
|
||||
isRegistered: false,
|
||||
userName: "隔离游客",
|
||||
@@ -203,9 +194,7 @@ const image = Buffer.from(
|
||||
key = Buffer.from("2019ysapp7527");
|
||||
for (let i = 0; i < Math.min(100, image.length); i++)
|
||||
image[i] ^= key[i % key.length];
|
||||
type EventRecord = { method: string; payload: Record<string, unknown> };
|
||||
const events: EventRecord[] = [],
|
||||
errors: string[] = [],
|
||||
const errors: string[] = [],
|
||||
missing: string[] = [],
|
||||
unexpected: string[] = [],
|
||||
destinations: string[] = [];
|
||||
@@ -214,14 +203,8 @@ let releaseImage: (() => void) | undefined,
|
||||
delayImage = false,
|
||||
imageRequested = 0;
|
||||
const configure = async (context: BrowserContext, ageAccepted = false) => {
|
||||
await context.exposeBinding(
|
||||
"__recordEvent",
|
||||
(_source, event: EventRecord) => {
|
||||
events.push(event);
|
||||
},
|
||||
);
|
||||
await context.addInitScript({
|
||||
content: `window.__ageClosed=0;document.addEventListener('eighteen:closed',function(){window.__ageClosed++});window.WebSDK={init:function(){return Promise.resolve()},getCommonFields:function(){return Promise.resolve({device_id:'isolated-device',device:'OTHER',sid:'isolated-sid'})},flush:function(){},track:new Proxy({},{get:function(_,method){return function(payload){return window.__recordEvent({method:String(method),payload:payload})}}})};try{${ageAccepted ? "localStorage.setItem('hg_age_ok','1');" : ""}if(!localStorage.getItem('__fixture_history_seeded')){localStorage.setItem('hgdj_search_history',JSON.stringify(['历史词']));localStorage.setItem('__fixture_history_seeded','1');}}catch{}`,
|
||||
content: `window.__ageClosed=0;document.addEventListener('eighteen:closed',function(){window.__ageClosed++});try{${ageAccepted ? "localStorage.setItem('hg_age_ok','1');" : ""}if(!localStorage.getItem('__fixture_history_seeded')){localStorage.setItem('hgdj_search_history',JSON.stringify(['历史词']));localStorage.setItem('__fixture_history_seeded','1');}}catch{}`,
|
||||
});
|
||||
await context.route("**/*", async (route) => {
|
||||
const request = route.request(),
|
||||
@@ -302,7 +285,6 @@ const configure = async (context: BrowserContext, ageAccepted = false) => {
|
||||
};
|
||||
const ready = async (page: Page) => {
|
||||
await page.waitForSelector(".hk-site-header");
|
||||
await page.waitForFunction(() => !!window.__trackerCommonFields);
|
||||
};
|
||||
const footerQR = async (page: Page, value: string, previous = "") => {
|
||||
await page.waitForFunction(({ value, previous }) => {
|
||||
@@ -413,17 +395,8 @@ try {
|
||||
await stack.keyboard.press("Escape");
|
||||
await stack.waitForSelector("[data-dialog-ad]", { state: "detached" });
|
||||
await expectOverflow(stack, "");
|
||||
await stack.waitForTimeout(50);
|
||||
assert.equal(
|
||||
events.filter(
|
||||
(event) =>
|
||||
event.method === "adImpression" && event.payload.ad_id === "stack-1",
|
||||
).length,
|
||||
1,
|
||||
);
|
||||
await stacked.close();
|
||||
imageRequested = 0;
|
||||
events.length = 0;
|
||||
// Age gate cannot be bypassed by Escape. Ads wait for actual XOR decode + image
|
||||
// load, resume their queue on another page, and stay dismissed in this session.
|
||||
const context = await browser.newContext({
|
||||
@@ -459,7 +432,6 @@ try {
|
||||
await page.waitForTimeout(150);
|
||||
assert.equal(imageRequested, 1);
|
||||
assert.equal(await page.locator("[data-dialog-ad]").isVisible(), false);
|
||||
assert.equal(events.filter((e) => e.method === "adImpression").length, 0);
|
||||
assert.equal(
|
||||
await page.evaluate(() => localStorage.getItem("hg_age_ok")),
|
||||
"1",
|
||||
@@ -515,16 +487,6 @@ try {
|
||||
await page.evaluate(() => sessionStorage.getItem("dialogAdDismissed")),
|
||||
"2|1|2",
|
||||
);
|
||||
assert.equal(
|
||||
events.filter((e) => e.method === "adImpression" && e.payload.ad_id === "1")
|
||||
.length,
|
||||
1,
|
||||
);
|
||||
assert.equal(
|
||||
events.filter((e) => e.method === "adClick" && e.payload.ad_id === "1")
|
||||
.length,
|
||||
1,
|
||||
);
|
||||
await page.goto(origin + "/?ads=1&bad=1");
|
||||
await ready(page);
|
||||
await page.locator("[data-dialog-ad].hk-is-open").waitFor();
|
||||
@@ -532,12 +494,6 @@ try {
|
||||
await page.locator("[data-dialog-ad-id]").getAttribute("data-dialog-ad-id"),
|
||||
"2",
|
||||
);
|
||||
assert.equal(
|
||||
events.some(
|
||||
(e) => e.method === "adImpression" && e.payload.ad_id === "bad",
|
||||
),
|
||||
false,
|
||||
);
|
||||
await page.keyboard.press("Escape");
|
||||
// Actual HeaderSearch hooks, keyboard navigation and history; no account entry remains.
|
||||
await page.goto(origin + "/?user=1");
|
||||
@@ -1053,15 +1009,8 @@ try {
|
||||
assert.ok(destinations.includes("/mock/android.apk"));
|
||||
assert.ok(destinations.includes("/mock/fallback"));
|
||||
assert.ok(destinations.includes("/mock/launch"));
|
||||
assert.ok(
|
||||
events.some(
|
||||
(event) =>
|
||||
event.method === "navigation" &&
|
||||
event.payload.navigation_key === "header_download",
|
||||
),
|
||||
);
|
||||
console.log(
|
||||
"Native React site smoke passed: age gate/focus lock, encrypted advertisement readiness/failure/queue/cross-page session, footer QR pixels/size/URL/official fallback/empty configuration/restoration, HeaderSearch/history/keyboard/encoded URLs, configured desktop hover/focus/toggle/Escape/outside-click and mobile expandable navigation/canonical/external/download links, no login/user-menu/account entries, PC download and configured/fallback iOS/Android tabs/actions/deep links, drawer/footer/main entries, scroll/focus restoration and analytics. All APIs and outbound destinations isolated.",
|
||||
"Native React site smoke passed: age gate/focus lock, encrypted advertisement readiness/failure/queue/cross-page session, footer QR pixels/size/URL/official fallback/empty configuration/restoration, HeaderSearch/history/keyboard/encoded URLs, configured desktop hover/focus/toggle/Escape/outside-click and mobile expandable navigation/canonical/external/download links, no login/user-menu/account entries, PC download and configured/fallback iOS/Android tabs/actions/deep links, drawer/footer/main entries, scroll/focus restoration. All APIs and outbound destinations isolated.",
|
||||
);
|
||||
} finally {
|
||||
releaseImage?.();
|
||||
|
||||
Reference in New Issue
Block a user