Skip to content

Nt 3547#335

Draft
David Nalchevanidze (nalchevanidze) wants to merge 51 commits into
mainfrom
NT-3547
Draft

Nt 3547#335
David Nalchevanidze (nalchevanidze) wants to merge 51 commits into
mainfrom
NT-3547

Conversation

@nalchevanidze

Copy link
Copy Markdown
Contributor

No description provided.

…h other web SDKs

- Replace local e2e specs with shared lib/e2e-web suite (RENDERING_MODE=hybrid); move nextjs-hydration.spec.ts into e2e-web with mode guard
- Add RENDERING_MODE support (csr/ssr/hybrid) to lib/e2e-web playwright config
- Replace Tailwind with theme.css; align all components to shared testid/class contract
- Flatten sections/ into components/; delete unused HybridEntryList, NestedContentEntry
- Remove config/entries.ts barrel; import PAGES/CLICK_SCENARIOS directly from e2e-web
- Consolidate types and client into lib/contentful.ts; rename optimization-server.ts to optimization.ts; move typeGuards into lib/util.ts
- Extract APP_PERSONALIZATION_CONSENT_COOKIE to lib/config.ts; simplify proxy.ts consent logic
- Add loadPageEntries helper; remove redundant Promise.all cache-warming from page files
- Remove unused PUBLIC_CONTENTFUL_PREVIEW_TOKEN from next.config.ts; drop Tailwind devDeps and postcss.config.mjs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…Card

Merge ContentEntry, NestedContentItem, RichTextRenderer, and LiveUpdatesExampleEntry
into EntryCard (flat in components/) and inline LiveUpdatesEntry into HomePage.
Rename AnalyticsEventDisplay → TrackingLog, InteractiveControls → ControlPanel
to match CSS class names and Angular component naming.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add liveUpdates and testId props to EntryCard so the live-updates
showcase renders directly via EntryCard without a wrapper component.
Inline AutoObservedEntries and ManuallyObservedEntries into HomePage.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…mponents presentational

Move entry lookup and toIdMap into app/page.tsx and app/page-two/page.tsx.
HomePage and PageTwoPage now receive resolved entries as props and drop
useMemo, toIdMap, PAGES, and CLICK_SCENARIOS imports entirely.
Extract toIdMap to lib/util as a generic helper.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nds and hooks

- Inline HomePage and PageTwoPage into server pages; delete wrappers
- Extract TrackView, TrackViewButton as generic client components
- Extract useTick, useEventStream, useFlagSubscription, useManualViewTracking into lib/hooks.ts
- Rename PreviewPanelAttachment → PreviewPanel, DemoCtaButton → TrackViewButton
- Move page-two client logic into focused components: OptimizationSection, TrackView, TrackViewButton

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…Card, ControlPanel, TrackingLog

Applies the same structural cleanup done to nextjs-sdk_hybrid:
- Merge contentful types/client + entries config into lib/contentful.ts
- Rename InteractiveControls → ControlPanel, AnalyticsEventDisplay → TrackingLog
- Extract EntryCard (server component) with ServerOptimizedEntry; page-two now
  uses it consistently (was rendering plain text with no tracking before)
- Extract lib/hooks.ts (useTick, useEventStream), lib/util.ts (isRecord, toIdMap)
- Move APP_PERSONALIZATION_CONSENT_COOKIE from local constants to lib/config
- Consume PAGES/CLICK_SCENARIOS from e2e-web instead of local config/entries.ts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add data-ctfl-entry-id to EntryCard content div so shared selectors work
  (shared tests call getAttribute('data-ctfl-entry-id') on the content-* element)
- Delete 4 local specs now fully covered by lib/e2e-web with RENDERING_MODE=ssr:
  entry-click-tracking, entry-hover-tracking, events-consent-gating, navigation-page-events
- Keep e2e/nextjs-ssr-behavior.spec.ts (SSR-specific: first-paint attributes, no
  redundant client Experience request after consented SSR hydration)
- Add serve:e2e script; update test:e2e to delegate to lib/e2e-web; update
  test:e2e:report and test:e2e:ui to match hybrid pattern
- Simplify playwright.config.mjs (local spec only, aligned with shared config style)
- Document E2E structure in AGENTS.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ipts

Now that E2E runs via lib/e2e-web, the local playwright.config.mjs and
implementation:playwright:install* / implementation:setup:e2e scripts are
redundant. Also drop @playwright/test devDependency — the shared suite owns it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Aligns with web-sdk, web-sdk_react, and web-sdk_angular: E2E runs via
lib/e2e-web so implementation:playwright:install*, implementation:setup:e2e,
test:e2e:codegen, and @playwright/test devDependency are not needed locally.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Playwright manages server lifecycle via webServer in lib/e2e-web config,
so the manual sh -c wrapper, serve, E2E_RESULT trap, and serve:stop are
redundant. PUBLIC_APP_ENVIRONMENT=staging belongs only in serve:e2e.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Three new tests under 'variant resolution without JavaScript' using
test.use({ javaScriptEnabled: false }):
- no consent → baseline text rendered
- consent + identified profile cookie → variant text rendered server-side
- consent revoked (denied) + profile cookie → baseline text rendered

Profile ID and entry/variant texts sourced directly from mock fixtures
(identified-visitor.json, contentful/data/entries/). These are the only
tests that prove SSR variant resolution works without client-side hydration.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…be blocks

nextjs-ssr-behavior.spec.ts -> ssr-behavior.spec.ts
'Next.js SSR behavior' -> 'server-side tracking attributes'
'variant resolution without JavaScript' -> 'server-side variant resolution'

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Follows the same pattern as nextjs-hydration.spec.ts: lives in lib/e2e-web,
skipped unless RENDERING_MODE=ssr. Uses baseURL fixture instead of hardcoded
port. Removes the now-empty local e2e/ directory from nextjs-sdk_ssr.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
server-side variant resolution now matches the pattern of
displays-identified-user-variants and displays-unidentified-user-variants
but with javaScriptEnabled: false — proving variants are resolved server-side
before any hydration.

Uses Playwright's request fixture to POST an identify event to the mock
before loading the page, so the mock returns identified-visitor data for
that profile ID. Consent and profile cookies are set directly.

Drops the hardcoded fixture profile ID in favour of crypto.randomUUID()
per test, which avoids cross-test state leakage.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… displays specs

- Restore displays-identified-user-variants.spec.ts and
  displays-unidentified-user-variants.spec.ts (deleted in previous commit
  by lint-staged picking up unrelated staged changes)
- Add displays-variants-ssr.spec.ts: mirrors displays-variants-csr structure
  exactly but with javaScriptEnabled: false and cookies set directly instead
  of button clicks. Uses request fixture to seed identified state in the mock.
  Gated with RENDERING_MODE !== 'ssr'. ssr-behavior.spec.ts remains separate
  for SSR-specific behaviors (tracking attributes, no redundant client request).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Delete displays-unidentified-user-variants.spec.ts (duplicate of displays-variants-csr)
- Strip variant display tests from ssr-behavior.spec.ts — those now live in
  displays-variants-ssr.spec.ts
- ssr-behavior.spec.ts now contains only SSR-specific behaviors: tracking
  attributes on first paint and no redundant client Experience request

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both files tested the same thing: no redundant client Experience request
after consented SSR hydration. Merged into ssr-behavior.spec.ts, gated
on ssr || hybrid. Tracking attributes test remains ssr-only via inline
test.skip. Deletes nextjs-hydration.spec.ts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…r-only

nextjs-hydration.spec.ts was deleted without being asked. Restored.
ssr-behavior.spec.ts reverted to RENDERING_MODE=ssr gate only.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ndering-behavior

Both files had an identical 'no redundant client Experience request' test,
only differing in RENDERING_MODE gate. Merged into server-rendering-behavior.spec.ts:
- 'no redundant request' runs for both ssr and hybrid
- 'tracking attributes on first paint' runs for ssr only (inline test.skip)
- Uses baseURL fixture throughout (removes hardcoded localhost:3002 fallback)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both specs verify variant resolution — same behavior, different moment
(server before HTML vs client after hydration). Rename to make that clear.
Also update describe block labels to match.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
'Variant Resolution (SSR, JavaScript disabled)' — makes explicit that
tests run with JS off, proving variants are resolved server-side.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…-behavior

The test only checked attribute presence with no consent/profile cookies,
so data-ctfl-variant-index was always 0 (baseline). variant-resolution-ssr.spec.ts
proves actual SSR resolution more meaningfully with JS disabled.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…o tracking.spec.ts

Three files testing the same concern (event tracking) consolidated into one.
Shared beforeEach extracted into a setup() helper. No logic changed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wrap tracking specs in outer Tracking describe with Entry Click, Entry
Hover, Flag View inner suites. Rename navigation-page-events → navigation
and events-consent-gating → consent-gating for brevity.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…uite names

Move entry view consent-gating tests into tracking.spec.ts as Consent Gating
suite. Title-case all describe names across live-updates, navigation,
offline-queue-recovery, and server-rendering-behavior.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add e2e/utils.ts with shared setup, scrollThroughEntries, seedIdentifiedProfile,
RENDERING_MODE, isPreviewPanelEnabled, isRenderingMode, and onlyInModes.
Replace inline env reads and test.skip conditions across specs with imports.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…wPanel helper

Turbopack cannot process raw .ts files from node_modules, causing both
nextjs-sdk_ssr and nextjs-sdk_hybrid E2E builds to fail. Add
transpilePackages to both next.config.ts files to fix this.

Also extract onlyWithPreviewPanel() helper in utils.ts and replace the
two inline test.skip calls in live-updates.spec.ts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…x preview panel config

- Add className="entry-card" and className="rich-text" to EntryCard renders
- Add entry-card__nested-children wrapper for nested entries
- Replace PUBLIC_APP_ENVIRONMENT-based preview panel inference with
  PUBLIC_OPTIMIZATION_ENABLE_PREVIEW_PANEL to match other implementations
- Remove PUBLIC_APP_ENVIRONMENT from next.config.ts and serve:e2e script
- Move "Trigger custom view event" button into ControlPanel (demoCTA prop)
  to match Angular and react-web-sdk patterns
- Rename TrackView -> CustomViewTracker, delete unused TrackViewButton
- Move "Back to Home" link into page-header before h1
- Restructure page-two to sections-grid--split matching other implementations
- Gate offline navigation tests with onlyInModes('csr') — SSR/hybrid
  require server-side navigation which fails offline

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…y components

- Move APP_LOCALE and APP_PERSONALIZATION_CONSENT_COOKIE into appConfig
- Extract setAppConsent/getAppConsent into lib/util and useConsent hook into lib/hooks
- Replace useMemo/useEffect inline patterns with useConsent() in ControlPanel
- Simplify isRichTextField using isRecord (align with Angular implementation)
- Drop displayFlagValue helper, inline String(booleanFlag ?? 'undefined')
- Extract useRichTextRenderer hook in EntryCard, remove RichText component

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…cking boolean

Replace viewTracking?: 'auto' | 'manual' with manualTracking?: boolean (default false = auto),
merge two OptimizedEntry branches into one, and add autoTracking local variable for readability.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ested lookup

Remove asCf cast by typing resolvedEntry directly, tighten ref callback to one-liner,
and simplify richText/nested variable names.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…Card

Dropped during render callback simplification in the previous refactor.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ent helpers, manualTracking

- Consolidate APP_LOCALE and APP_PERSONALIZATION_CONSENT_COOKIE into appConfig
- Add getAppConsent/setAppConsent helpers to util, remove inline cookie logic from proxy/pages
- Add useConsent hook to hooks.ts, removing the scattered useEffect from ControlPanel
- Rename viewTracking 'auto'|'manual' to manualTracking boolean on EntryCard, matching hybrid

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…Panel

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both nextjs-sdk_ssr and nextjs-sdk_hybrid delegate their tests to
lib/e2e-web, but CI was running implementation:playwright:install
(which is a no-op — neither impl has a playwright dependency) and
pointing artifact upload paths at the implementation directories.

Replace with the same lib/e2e-web install + setup:e2e steps used by
Angular and react-web-sdk, and fix artifact paths accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…up flag system

- Remove HYBRID flag; hybrid uses CSR,SSR together
- E2EFlag type narrowed to 'CSR' | 'SSR'
- Move E2E_FLAGS and APP_PORT from test:e2e scripts into each Next.js
  implementation's .env.example (and .env); playwright.config.mjs loads
  .env before reading those vars so all implementations just need
  IMPLEMENTATION=<name>
- Add nested variant resolution via resolveEntry callback in SSR EntryCard
- Skip CSR variant-resolution suite when SSR flag is set (TODO: FIXME)
- Fix server-rendering-behavior to use runIf('SSR') only

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…lution-csr

Linter moved the call inside the inner describe block; restore it to the
outer suite so both unidentified and identified sub-suites are gated.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Only the unidentified user tests fail for SSR; identified user tests
can still run with consent+profile cookies.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…e file

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…in nextjs implementations

SSR flag is intentionally omitted from both ssr and hybrid implementations because full SSR variant resolution has a known bug to be fixed later.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… resolution SSR suite

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…uite

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… hydration

OptimizationProvider no longer gates children unconditionally — the gate
now only applies when onStatesReady is set. This lets Next.js SSR produce
real HTML from server components inside the provider tree.

useOptimization returns SSR_STUB (a fully-typed noop implementation) when
sdk/isReady are not yet set, covering both server render and the brief
client window before useLayoutEffect fires. The stub lives in ssrStub.ts.

layout.tsx adds force-dynamic so useSearchParams() can run without a
Suspense boundary, and .env.example enables the SSR E2E flag now that
server-side HTML rendering works.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaced Parameters<> extraction helpers with inline async functions
so the method signatures satisfy OptimizationSdk without relying on
parameter name matching. Also typed resolveOptimizedEntry's entry
param explicitly to avoid noImplicitAny under the build tsconfig.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d signatures

Wrap stub object in makeSsrStub() with an explicit OptimizationSdk annotation
so TypeScript uses contextual typing to infer parameter types for each async
method. This avoids explicit Parameters<> extraction or unsafe type assertions
while satisfying the SDK's overloaded generic method signatures under
the strict build tsconfig.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…atures

Methods with optional payloads (page, identify, track, trackClick, trackView)
now use _param? so the stub's type matches (payload?: T) => R rather than
(_payload: T | undefined) => R, which are structurally incompatible under
TypeScript strict mode. resolveOptimizedEntry keeps _entry required.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Explicit type annotations on resolveOptimizedEntry fix the TS7006
implicit-any error (overloaded generics can't be inferred through
contextual typing when built against dist types via tsconfig.build.json).
Making identify/track/trackView/trackClick params required (no ?) fixes
TS2322 assignability errors from the optional-vs-required mismatch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant