-
Notifications
You must be signed in to change notification settings - Fork 1k
feat[react-gen2]: support for variant containers #3828
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a7416ca
966ff90
6359fa9
2ca5359
b17d1f4
c40d989
9623628
bcfae30
fead5df
0f3820f
3d107ca
7e74e7d
27fcb28
bbed638
c876a01
97aa51c
1d80e11
1e859dd
6af09aa
e4dbd8d
00e347c
c12fdee
af3dc67
248b481
6778086
7f2a51e
ae6e032
62c4857
2f2ba53
da82b19
1419e94
fe32d67
84608cb
ca536d4
c19849f
c96ba14
0afe591
ea38c22
6ae66e5
ce06409
5df82bf
163a330
1975d8a
e468dd0
14e3aa9
e4042f3
f72cd45
a1e44ea
bbeb527
f2a8a74
f608250
90620c7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--- | ||
'@builder.io/sdk-solid': patch | ||
--- | ||
|
||
Feat: exports `setClientUserAttributes` helper that can be used to set and update Builder's user attributes cookie. This cookie is used by Builder's Personalization Containers to decide which variant to render. | ||
|
||
Usage example: | ||
|
||
```ts | ||
import { setClientUserAttributes } from '@builder.io/sdk-solid'; | ||
|
||
setClientUserAttributes({ | ||
device: 'tablet', | ||
}); | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--- | ||
'@builder.io/sdk-svelte': patch | ||
--- | ||
|
||
Feat: exports `setClientUserAttributes` helper that can be used to set and update Builder's user attributes cookie. This cookie is used by Builder's Personalization Containers to decide which variant to render. | ||
|
||
Usage example: | ||
|
||
```ts | ||
import { setClientUserAttributes } from '@builder.io/sdk-svelte'; | ||
|
||
setClientUserAttributes({ | ||
device: 'tablet', | ||
}); | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--- | ||
'@builder.io/sdk-vue': patch | ||
--- | ||
|
||
Feat: exports `setClientUserAttributes` helper that can be used to set and update Builder's user attributes cookie. This cookie is used by Builder's Personalization Containers to decide which variant to render. | ||
|
||
Usage example: | ||
|
||
```ts | ||
import { setClientUserAttributes } from '@builder.io/sdk-vue'; | ||
|
||
setClientUserAttributes({ | ||
device: 'tablet', | ||
}); | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--- | ||
'@builder.io/sdk-angular': patch | ||
--- | ||
|
||
Feat: exports `setClientUserAttributes` helper that can be used to set and update Builder's user attributes cookie. This cookie is used by Builder's Personalization Containers to decide which variant to render. | ||
|
||
Usage example: | ||
|
||
```ts | ||
import { setClientUserAttributes } from '@builder.io/sdk-angular'; | ||
|
||
setClientUserAttributes({ | ||
device: 'tablet', | ||
}); | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--- | ||
'@builder.io/sdk-react-native': patch | ||
--- | ||
|
||
Feat: exports `setClientUserAttributes` helper that can be used to set and update Builder's user attributes cookie. This cookie is used by Builder's Personalization Containers to decide which variant to render. | ||
|
||
Usage example: | ||
|
||
```ts | ||
import { setClientUserAttributes } from '@builder.io/sdk-react-native'; | ||
|
||
setClientUserAttributes({ | ||
device: 'tablet', | ||
}); | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--- | ||
'@builder.io/sdk-qwik': patch | ||
--- | ||
|
||
Feat: exports `setClientUserAttributes` helper that can be used to set and update Builder's user attributes cookie. This cookie is used by Builder's Personalization Containers to decide which variant to render. | ||
|
||
Usage example: | ||
|
||
```ts | ||
import { setClientUserAttributes } from '@builder.io/sdk-qwik'; | ||
|
||
setClientUserAttributes({ | ||
device: 'tablet', | ||
}); | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--- | ||
'@builder.io/sdk-react': patch | ||
--- | ||
|
||
Feat: exports `setClientUserAttributes` helper that can be used to set and update Builder's user attributes cookie. This cookie is used by Builder's Personalization Containers to decide which variant to render. | ||
|
||
Usage example: | ||
|
||
```ts | ||
import { setClientUserAttributes } from '@builder.io/sdk-react'; | ||
|
||
setClientUserAttributes({ | ||
device: 'tablet', | ||
}); | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--- | ||
'@builder.io/sdk-react-nextjs': patch | ||
--- | ||
|
||
Feat: exports `setClientUserAttributes` helper that can be used to set and update Builder's user attributes cookie. This cookie is used by Builder's Personalization Containers to decide which variant to render. | ||
|
||
Usage example: | ||
|
||
```ts | ||
import { setClientUserAttributes } from '@builder.io/sdk-react-nextjs'; | ||
|
||
setClientUserAttributes({ | ||
device: 'tablet', | ||
}); | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@builder.io/react': patch | ||
--- | ||
|
||
Fix: hydration mismatch error and reactivity of Personalization Containers when `userAttributes` cookie value is updated. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@builder.io/sdk-react': patch | ||
--- | ||
|
||
Feat: support of Variant Containers or Block level personalization |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,15 @@ | ||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
const path = require('path'); | ||
|
||
/** @type {import('next').NextConfig} */ | ||
const nextConfig = { | ||
experimental: { | ||
externalDir: true, | ||
}, | ||
webpack: config => { | ||
config.resolve.alias['react'] = path.resolve(__dirname, './node_modules/react'); | ||
return config; | ||
}, | ||
}; | ||
|
||
module.exports = nextConfig; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
import type { Browser } from '@playwright/test'; | ||
import { expect } from '@playwright/test'; | ||
import { excludeGen2, test } from '../helpers/index.js'; | ||
import { excludeGen2, isSSRFramework, test } from '../helpers/index.js'; | ||
import { launchEmbedderAndWaitForSdk } from '../helpers/visual-editor.js'; | ||
const SELECTOR = 'div[builder-content-id]'; | ||
|
||
const createContextWithCookies = async ({ | ||
|
@@ -35,19 +36,17 @@ const initializeUserAttributes = async ( | |
page: _page, | ||
baseURL, | ||
browser, | ||
sdk, | ||
packageName, | ||
sdk, | ||
}: Pick< | ||
Parameters<Parameters<typeof test>[2]>[0], | ||
'page' | 'baseURL' | 'browser' | 'packageName' | 'sdk' | ||
>, | ||
{ userAttributes }: { userAttributes: Record<string, string> } | ||
) => { | ||
// gen1-next likely have a config issue with SSR | ||
test.skip(packageName === 'gen1-next14-pages'); | ||
// gen1-remix started failing on this test for an unknown reason. | ||
test.skip(packageName === 'gen1-remix'); | ||
test.skip(excludeGen2(sdk)); | ||
test.skip(excludeGen2(sdk) && sdk !== 'react'); | ||
|
||
if (!baseURL) throw new Error('Missing baseURL'); | ||
|
||
|
@@ -162,4 +161,89 @@ test.describe('Personalization Container', () => { | |
}); | ||
} | ||
}); | ||
|
||
test('setClientUserAttributes and builder.setUserAttributes sets cookie and renders variant after the first render', async ({ | ||
page, | ||
packageName, | ||
}) => { | ||
// here we are checking specifically for winning variant content by setting the user attributes | ||
test.skip(!['react-sdk-next-15-app', 'gen1-next15-app'].includes(packageName)); | ||
await page.goto('/variant-containers'); | ||
|
||
// content 1 | ||
await expect(page.getByText('My tablet content')).toBeVisible(); | ||
await expect(page.getByText('My mobile content updated')).not.toBeVisible(); | ||
await expect(page.getByText('My default content')).not.toBeVisible(); | ||
|
||
// content 2 - this has no targeting set, so the first variant should be the winning variant | ||
await expect(page.getByText('Tablet content 2')).toBeVisible(); | ||
}); | ||
|
||
test('only default variants are ssred on the server', async ({ browser, packageName, sdk }) => { | ||
test.skip(!isSSRFramework(packageName)); | ||
test.skip(!['react', 'oldReact'].includes(sdk)); | ||
// Cannot read properties of null (reading 'useContext') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @samijaber we should create a ticket to move away from remix v1 for gen1 tests and use v2 that we already have in snippets. This will help us alias a single react and fix these tests repo: https://github.com/sidmohanty11/builder-remix-gen1-example There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah @sidmohanty11 , I actually spent a bunch of time doing this locally but hit some cascading issues that caused most (interactivity-related?) tests to fail for remix v2, so i ended up putting a pin in it for now. But would be good to sort it out |
||
test.skip(packageName === 'gen1-remix'); | ||
|
||
const context = await browser.newContext({ | ||
javaScriptEnabled: false, | ||
}); | ||
|
||
const page = await context.newPage(); | ||
|
||
await page.goto('/variant-containers'); | ||
|
||
await expect(page.getByText('My default content')).toBeVisible(); | ||
await expect(page.getByText('Default content 2')).toBeVisible(); | ||
}); | ||
|
||
test('root style attribute is correctly set', async ({ page, sdk, packageName }) => { | ||
test.skip(!['react', 'oldReact'].includes(sdk)); | ||
// Cannot read properties of null (reading 'useContext') | ||
test.skip(packageName === 'gen1-remix'); | ||
|
||
await page.goto('/variant-containers'); | ||
|
||
const secondPersonalizationContainer = page | ||
.locator('.builder-personalization-container') | ||
.nth(1); | ||
await expect(secondPersonalizationContainer).toHaveCSS('background-color', 'rgb(255, 0, 0)'); | ||
}); | ||
|
||
test.describe('visual editing', () => { | ||
test('correctly shows the variant that is being currently edited', async ({ | ||
page, | ||
sdk, | ||
basePort, | ||
packageName, | ||
}) => { | ||
test.skip(!['react', 'oldReact'].includes(sdk)); | ||
// Cannot read properties of null (reading 'useContext') | ||
test.skip(packageName === 'gen1-remix'); | ||
|
||
const paths = [ | ||
'/variant-containers-with-previewing-index-0', | ||
'/variant-containers-with-previewing-index-1', | ||
'/variant-containers-with-previewing-index-undefined', | ||
]; | ||
|
||
const expectedTexts = [ | ||
'My tablet content', | ||
'My mobile content updated', | ||
'My default content', | ||
]; | ||
|
||
for (let i = 0; i < paths.length; i++) { | ||
const path = paths[i]; | ||
await launchEmbedderAndWaitForSdk({ | ||
path, | ||
page, | ||
sdk, | ||
basePort, | ||
}); | ||
|
||
await expect(page.frameLocator('iframe').getByText(expectedTexts[i])).toBeVisible(); | ||
} | ||
}); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this to resolve the weird "multiple versions of React"/"Cannot import
useContext
of undefined" bugs we've seen in certain tests?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup, while checking the error of
useRef not defined
in personalization spec I remembered we faced a similar case for useState a while back which was resolved with this