Sitelet https://github.com/limitless-angular/limitless-angular/pull/41/files
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const presentationSmokeQuery = '*[_id == $id][0]{title}';
type PresentationSmokeWindow = Window & {
__presentationSmokeBootCount?: number;
__presentationSmokeFetchCount?: number;
__presentationSmokePerspective?: unknown;
__presentationSmokeTitle?: string;
};

Expand All @@ -54,18 +55,23 @@ const clientConfig = {
dataset,
apiVersion: '2024-02-28',
useCdn: false,
perspective: 'previewDrafts',
perspective: 'drafts',
resultSourceMap: true,
} as unknown as Required<InitializedClientConfig>;

const fakeClient = {
config: () => clientConfig,
withConfig: () => fakeClient,
fetch: async () => {
fetch: async (
_query: string,
_params?: QueryParams,
options?: { perspective?: unknown },
) => {
const smokeWindow = getPresentationSmokeWindow();
if (smokeWindow) {
smokeWindow.__presentationSmokeFetchCount =
(smokeWindow.__presentationSmokeFetchCount ?? 0) + 1;
smokeWindow.__presentationSmokePerspective = options?.perspective;
}

return {
Expand Down
2 changes: 1 addition & 1 deletion apps/analog-sanity-blog-example/src/sanity/lib/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function getClient(preview?: { token: string }): SanityClient {
token: preview.token,
useCdn: false,
ignoreBrowserTokenWarning: true,
perspective: 'previewDrafts',
perspective: 'drafts',
});
}
return client;
Expand Down
4 changes: 2 additions & 2 deletions apps/sanity-presentation-e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ This starts the Analog example app with dummy Sanity env values, then uses a fak

- open `/presentation-smoke` inside an iframe
- complete the legacy `sanity/channels` handshake
- assert `@limitless-angular/sanity/preview-kit` posts `preview-kit/documents`
- assert `@limitless-angular/sanity/preview-kit` connects as a `loaders` node and honors Presentation perspective messages
- assert live preview refreshes Angular data without reloading the iframe
- assert `@limitless-angular/sanity/visual-editing` connects to the host
- assert the editable title renders the expected `data-sanity` marker
Expand Down Expand Up @@ -69,7 +69,7 @@ The real-project smoke asserts that:

- Studio Presentation opens the Angular `/presentation-smoke` preview frame
- the preview route renders data loaded by the app's real Sanity client
- `@limitless-angular/sanity/preview-kit` announces the real document in use to Studio
- `@limitless-angular/sanity/preview-kit` connects to Studio as a loader
- `@limitless-angular/sanity/visual-editing` connects to Studio and exposes an editable `data-sanity` marker
- when `SANITY_E2E_WRITE_TOKEN` is set, a real Sanity mutation updates the Angular live preview without reloading the iframe, then restores the title; that token must have document update permission for the configured project and dataset

Expand Down
75 changes: 54 additions & 21 deletions apps/sanity-presentation-e2e/tests/fake-presentation-host.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ type ProtocolMessage = {
type PresentationSmokeFrameState = {
__presentationSmokeBootCount?: number;
__presentationSmokeFetchCount?: number;
__presentationSmokePerspective?: unknown;
__presentationSmokeTitle?: string;
};

Expand All @@ -72,7 +73,7 @@ async function installFakePresentationHost(page: Page): Promise<void> {
<script>
window.__presentationMessages = [];
const iframe = document.getElementById('preview');
const targets = ['preview-kit', 'visual-editing', 'overlays'];
const targets = ['loaders', 'visual-editing', 'overlays'];
const connections = new Map();

function send(message) {
Expand Down Expand Up @@ -102,6 +103,23 @@ async function installFakePresentationHost(page: Page): Promise<void> {
window.__handshakeInterval = setInterval(handshakeAll, 500);
}

window.__sendLoaderPerspective = function (perspective) {
const connectionId = connections.get('loaders') || 'fake-loaders';
connections.set('loaders', connectionId);
send({
domain: 'sanity/channels',
type: 'loader/perspective',
from: 'presentation',
to: 'loaders',
connectionId,
data: {
projectId: '${expectedProjectId}',
dataset: '${expectedDataset}',
perspective
}
});
};

window.addEventListener('message', (event) => {
const data = event.data || {};
if (data && data.domain === 'sanity/channels') {
Expand Down Expand Up @@ -202,6 +220,8 @@ async function getFrameState(
return {
__presentationSmokeBootCount: smokeWindow.__presentationSmokeBootCount,
__presentationSmokeFetchCount: smokeWindow.__presentationSmokeFetchCount,
__presentationSmokePerspective:
smokeWindow.__presentationSmokePerspective,
__presentationSmokeTitle: smokeWindow.__presentationSmokeTitle,
};
});
Expand All @@ -219,38 +239,51 @@ async function expectEditableTitleMarker(title: Locator): Promise<void> {
await expect(title).toHaveAttribute('data-sanity', expectedDataSanity);
}

test('Angular preview announces live documents when embedded by Presentation', async ({
function isLoaderConnectionMessage(message: ProtocolMessage): boolean {
return message.type === 'handshake/syn-ack' && message.from === 'loaders';
}

async function sendLoaderPerspective(
page: Page,
perspective: string,
): Promise<void> {
await page.evaluate((nextPerspective) => {
(
window as unknown as {
__sendLoaderPerspective?: (perspective: string) => void;
}
).__sendLoaderPerspective?.(nextPerspective);
}, perspective);
}

test('Angular preview connects loaders and honors Presentation perspective', async ({
page,
}) => {
await installFakePresentationHost(page);

const previewFrame = await getPreviewFrame(page);
const frame = page.frameLocator('#preview');
const title = frame.getByTestId('presentation-smoke-title');

await expect(frame.getByTestId('presentation-smoke-kicker')).toBeVisible();
await waitForMessage(
page,
(message) => message.type === 'preview-kit/documents',
);
await waitForMessage(page, isLoaderConnectionMessage);

await expect(title).toContainText(liveTitle);
await expectEditableTitleMarker(title);
await expect
.poll(
async () =>
(await getFrameState(previewFrame)).__presentationSmokePerspective,
)
.toBe('drafts');

const documentsMessage = (await getPresentationMessages(page)).find(
(message) => message.type === 'preview-kit/documents',
);

expect(documentsMessage).toMatchObject({
from: 'preview-kit',
to: 'presentation',
type: 'preview-kit/documents',
});
expect(documentsMessage?.data).toMatchObject({
dataset: expectedDataset,
documents: [{ _id: 'presentation-smoke-post' }],
perspective: 'previewDrafts',
projectId: expectedProjectId,
});
await sendLoaderPerspective(page, 'published');
await expect
.poll(
async () =>
(await getFrameState(previewFrame)).__presentationSmokePerspective,
)
.toBe('published');
});

test('live preview refreshes Angular data without reloading the preview', async ({
Expand Down
52 changes: 4 additions & 48 deletions apps/sanity-presentation-e2e/tests/real-studio.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,6 @@ type ProtocolMessage = {
type?: string;
};

type DocumentsMessageData = {
dataset?: string;
documents?: Array<{ _id?: string }>;
perspective?: string;
projectId?: string;
};

type PresentationSmokeFrameState = {
__presentationSmokeBootCount?: number;
};
Expand Down Expand Up @@ -348,8 +341,8 @@ function extendTimeoutForPreviewFrame(
}
}

function isPreviewKitDocumentsMessage(message: ProtocolMessage): boolean {
return message.type === 'preview-kit/documents';
function isLoaderConnectionMessage(message: ProtocolMessage): boolean {
return message.type === 'handshake/syn-ack' && message.from === 'loaders';
}

function isVisualEditingConnectionMessage(message: ProtocolMessage): boolean {
Expand All @@ -359,12 +352,6 @@ function isVisualEditingConnectionMessage(message: ProtocolMessage): boolean {
);
}

function getDocumentsMessageData(
message: ProtocolMessage | undefined,
): DocumentsMessageData {
return (message?.data ?? {}) as DocumentsMessageData;
}

function parseDataSanity(value: string): Record<string, string> {
return Object.fromEntries(
value.split(';').map((part) => {
Expand Down Expand Up @@ -392,7 +379,7 @@ function createMutationClient(token: string): SanityClient {
apiVersion: process.env['SANITY_E2E_API_VERSION'] || '2024-02-28',
token,
useCdn: false,
perspective: 'previewDrafts',
perspective: 'drafts',
});
}

Expand Down Expand Up @@ -433,39 +420,8 @@ test('Sanity Studio Presentation opens the Angular preview frame', async ({
await expect(title).toHaveAttribute('data-sanity', expectedDataSanity);
}

await waitForMessage(page, isPreviewKitDocumentsMessage);
await waitForMessage(page, isLoaderConnectionMessage);
await waitForMessage(page, isVisualEditingConnectionMessage);

const dataSanity = parseDataSanity(
(await title.getAttribute('data-sanity')) ?? '',
);
const documentsMessage = (await getPresentationMessages(page)).find(
isPreviewKitDocumentsMessage,
);
const documentsData = getDocumentsMessageData(documentsMessage);

expect(documentsMessage).toMatchObject({
from: 'preview-kit',
to: 'presentation',
type: 'preview-kit/documents',
});
expect(documentsData).toMatchObject({
dataset: expectedPreviewDataset,
perspective: 'previewDrafts',
projectId: expectedPreviewProjectId,
});

if (studioMode === 'real-project') {
expect(documentsData.documents ?? []).toEqual(
expect.arrayContaining([
expect.objectContaining({ _id: dataSanity['id'] }),
]),
);
} else {
expect(documentsData.documents).toEqual([
expect.objectContaining({ _id: documentId }),
]);
}
});

test('real Sanity mutations update Angular live preview without reloading', async ({
Expand Down
2 changes: 1 addition & 1 deletion packages/sanity/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const getClientFactory = (preview?: { token: string }) =>
token: preview.token,
useCdn: false,
ignoreBrowserTokenWarning: true,
perspective: 'previewDrafts',
perspective: 'drafts',
stega: {
enabled: true,
studioUrl: 'your-studio-url',
Expand Down
2 changes: 1 addition & 1 deletion packages/sanity/image-loader/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ const getClientFactory = (preview?: { token: string }) =>
token: preview.token,
useCdn: false,
ignoreBrowserTokenWarning: true,
perspective: 'previewDrafts',
perspective: 'drafts',
stega: {
enabled: true,
studioUrl: 'your-studio-url',
Expand Down
2 changes: 2 additions & 0 deletions packages/sanity/ng-package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"entryFile": "src/index.ts"
},
"allowedNonPeerDependencies": [
"@sanity/comlink",
"@sanity/presentation-comlink",
"@vercel/stega",
"lodash-es",
"lru-cache",
Expand Down
6 changes: 4 additions & 2 deletions packages/sanity/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"@angular/router": "^18.0.0 || ^19.0.0",
"@portabletext/toolkit": "^2.0.15 || ^3.0.0 || ^4.0.0 || ^5.0.0",
"@portabletext/types": "^2.0.13 || ^3.0.0 || ^4.0.0",
"@sanity/client": "^6.21.3 || ^7.0.0",
"@sanity/client": "^6.28.0 || ^7.0.0",
"@sanity/image-url": "^1.0.2 || ^2.0.2",
"@sanity/visual-editing": "^2.7.0",
"rxjs": "^7.8.0"
Expand All @@ -44,10 +44,12 @@
}
},
"dependencies": {
"@sanity/comlink": "^3.0.1",
"@sanity/presentation-comlink": "^1.0.6",
"@vercel/stega": "0.1.2",
"lodash-es": "^4.17.21",
"lru-cache": "^11.0.0",
"mendoza": "^3.0.7",
"mendoza": "3.0.8",
"tslib": "^2.3.0"
},
"devDependencies": {
Expand Down
7 changes: 0 additions & 7 deletions packages/sanity/preview-kit-compat/README.md

This file was deleted.

3 changes: 0 additions & 3 deletions packages/sanity/preview-kit-compat/eslint.config.js

This file was deleted.

5 changes: 0 additions & 5 deletions packages/sanity/preview-kit-compat/ng-package.json

This file was deleted.

25 changes: 0 additions & 25 deletions packages/sanity/preview-kit-compat/package.json

This file was deleted.

Loading
Loading