Skip to content
Open
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
41 changes: 41 additions & 0 deletions renderers/angular/src/v0_8/data/processor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,45 @@ describe('MessageProcessor', () => {

expect(baseProcessor.clearSurfaces).toHaveBeenCalled();
});

it('should only return surfaces that are ready to render', () => {
// NOTE: This state can occur if a `surfaceUpdate` message is processed
// before a `beginRendering` message for the same surface.
const readySurfaceId = 'ready-surface-id';
const readyComponentId = 'ready-component-id';
const notReadySurfaceId = 'not-ready-surface-id';
const readySurface: WebCore.Surface = {
rootComponentId: readyComponentId,
componentTree: {
id: readyComponentId,
type: 'Text',
properties: {
text: { literalString: 'Ready to render' },
}
},
dataModel: new Map(),
components: new Map(),
styles: {},
};
const notReadySurface: WebCore.Surface = {
rootComponentId: null,
componentTree: null,
dataModel: new Map(),
components: new Map(),
styles: {},
};
// Add both surfaces to the base processor's surfaces map
const baseProcessor = (service as any).baseProcessor;
const surfaces = new Map<string, WebCore.Surface>([
[readySurfaceId, readySurface],
[notReadySurfaceId, notReadySurface],
]);
baseProcessor.surfaces = surfaces;

const returnedSurfaces = service.getSurfaces();

expect(returnedSurfaces.size).toBe(1);
expect(returnedSurfaces.get(readySurfaceId)).toBe(readySurface);
expect(returnedSurfaces.get(notReadySurfaceId)).toBeUndefined();
});
});
2 changes: 1 addition & 1 deletion renderers/angular/src/v0_8/data/processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export class MessageProcessor {
}

getSurfaces(): Map<string, WebCore.Surface> {
return (this.baseProcessor as any).surfaces || new Map();
return this.baseProcessor.getSurfaces() as Map<string, WebCore.Surface>;
}

clearSurfaces() {
Expand Down
59 changes: 37 additions & 22 deletions renderers/lit/src/0.8/model.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,28 +95,36 @@ describe("A2uiMessageProcessor", () => {
});

it("should handle `surfaceUpdate` by adding components", () => {
const surfaceId = "@default";
const rootComponentId = "comp-a";
const messages = [
{
beginRendering: {
surfaceId,
root: rootComponentId,
},
},
{
surfaceUpdate: {
surfaceId: "@default",
surfaceId,
components: [
{
id: "comp-a",
id: rootComponentId,
component: {
Text: { usageHint: "body", text: { literalString: "Hi" } },
Text: { usageHint: "body", text: { literalString: "Hi" } },
},
},
],
},
},
];
processor.processMessages(messages);
const surface = processor.getSurfaces().get("@default");
const surface = processor.getSurfaces().get(surfaceId);
if (!surface) {
assert.fail("No default surface");
}
assert.strictEqual(surface!.components.size, 1);
assert.ok(surface!.components.has("comp-a"));
assert.ok(surface!.components.has(rootComponentId));
});

it("should handle `deleteSurface`", () => {
Expand Down Expand Up @@ -353,7 +361,7 @@ describe("A2uiMessageProcessor", () => {
{
id: "child",
component: {
Text: { usageHint: "body", text: { literalString: "Hello" } },
Text: { usageHint: "body", text: { literalString: "Hello" } },
},
},
],
Expand Down Expand Up @@ -444,7 +452,7 @@ describe("A2uiMessageProcessor", () => {
},
{
id: "item-template",
component: { Text: { usageHint: "body", text: { path: "/name" } } },
component: { Text: { usageHint: "body", text: { path: "/name" } } },
},
],
},
Expand Down Expand Up @@ -498,7 +506,7 @@ describe("A2uiMessageProcessor", () => {
},
{
id: "item-template",
component: { Text: { usageHint: "body", text: { path: "/name" } } },
component: { Text: { usageHint: "body", text: { path: "/name" } } },
},
],
},
Expand Down Expand Up @@ -576,7 +584,7 @@ describe("A2uiMessageProcessor", () => {
// These paths would are typical when a databinding is used.
{
id: "item-template",
component: { Text: { usageHint: "body", text: { path: "./item/name" } } },
component: { Text: { usageHint: "body", text: { path: "./item/name" } } },
},
],
},
Expand Down Expand Up @@ -634,7 +642,7 @@ describe("A2uiMessageProcessor", () => {
// These paths would are typical when a databinding is used.
{
id: "item-template",
component: { Text: { usageHint: "body", text: { path: "./name" } } },
component: { Text: { usageHint: "body", text: { path: "./name" } } },
},
],
},
Expand Down Expand Up @@ -731,7 +739,8 @@ describe("A2uiMessageProcessor", () => {
{
id: "title-heading",
component: {
Text: { usageHint: "body",
Text: {
usageHint: "body",
text: {
literalString: "Top Restaurants",
},
Expand Down Expand Up @@ -774,7 +783,8 @@ describe("A2uiMessageProcessor", () => {
id: "template-image",
weight: 1,
component: {
Image: { usageHint: "largeFeature",
Image: {
usageHint: "largeFeature",
url: {
path: "imageUrl",
},
Expand All @@ -801,7 +811,8 @@ describe("A2uiMessageProcessor", () => {
{
id: "template-name",
component: {
Text: { usageHint: "body",
Text: {
usageHint: "body",
text: {
path: "name",
},
Expand All @@ -811,7 +822,8 @@ describe("A2uiMessageProcessor", () => {
{
id: "template-rating",
component: {
Text: { usageHint: "body",
Text: {
usageHint: "body",
text: {
path: "rating",
},
Expand All @@ -821,7 +833,8 @@ describe("A2uiMessageProcessor", () => {
{
id: "template-detail",
component: {
Text: { usageHint: "body",
Text: {
usageHint: "body",
text: {
path: "detail",
},
Expand All @@ -831,7 +844,8 @@ describe("A2uiMessageProcessor", () => {
{
id: "template-link",
component: {
Text: { usageHint: "body",
Text: {
usageHint: "body",
text: {
path: "infoLink",
},
Expand Down Expand Up @@ -872,7 +886,8 @@ describe("A2uiMessageProcessor", () => {
{
id: "book-now-text",
component: {
Text: { usageHint: "body",
Text: {
usageHint: "body",
text: {
literalString: "Book Now",
},
Expand Down Expand Up @@ -1133,7 +1148,7 @@ describe("A2uiMessageProcessor", () => {
{
id: "day-title",
component: {
Text: { usageHint: "body", text: { path: "title" } },
Text: { usageHint: "body", text: { path: "title" } },
},
},
{
Expand All @@ -1151,7 +1166,7 @@ describe("A2uiMessageProcessor", () => {
},
{
id: "activity-text",
component: { Text: { usageHint: "body", text: { path: "." } } },
component: { Text: { usageHint: "body", text: { path: "." } } },
},
],
},
Expand Down Expand Up @@ -1228,7 +1243,7 @@ describe("A2uiMessageProcessor", () => {
},
},
},
{ id: "tag", component: { Text: { usageHint: "body", text: { path: "." } } } },
{ id: "tag", component: { Text: { usageHint: "body", text: { path: "." } } } },
],
},
},
Expand Down Expand Up @@ -1269,7 +1284,7 @@ describe("A2uiMessageProcessor", () => {
components: [
{
id: "comp-a",
component: { Text: { usageHint: "body", text: { path: "/name" } } },
component: { Text: { usageHint: "body", text: { path: "/name" } } },
},
],
},
Expand All @@ -1289,7 +1304,7 @@ describe("A2uiMessageProcessor", () => {
components: [
{
id: "comp-b",
component: { Text: { usageHint: "body", text: { path: "/name" } } },
component: { Text: { usageHint: "body", text: { path: "/name" } } },
},
],
},
Expand Down
24 changes: 24 additions & 0 deletions renderers/web_core/src/v0_8/data/model-processor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,30 @@ describe("A2uiMessageProcessor", () => {
assert.deepStrictEqual(root.properties.text, { literal: "Hello" });
});

it("handles surfaceUpdate without beginRendering", () => {
const surfaceId = "s1";
processor.processMessages([
{
surfaceUpdate: {
surfaceId,
components: [
{
id: "root",
component: {
Text: { text: { literal: "Hello" }, usageHint: "body" },
} as any,
},
],
},
},
]);

// Should filter out the surface, as the processor treats it as not ready
// to render without a beginRendering message
const surface = processor.getSurfaces().get(surfaceId);
assert.equal(surface, undefined);
});

it("handles dataModelUpdate", () => {
processor.processMessages([
{
Expand Down
13 changes: 12 additions & 1 deletion renderers/web_core/src/v0_8/data/model-processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,18 @@ export class A2uiMessageProcessor implements MessageProcessor {
}

getSurfaces(): ReadonlyMap<string, Surface> {
return this.surfaces;
const allSurfaces = this.surfaces;
// NOTE: If a message with a `surfaceUpdate` is processed prior to a
// `beginRendering` message, the surface is still returned, but it will
// throw an error when attempting to render it due to the missing
// `rootComponentId`.
const visibleSurfaces = new Map<string, Surface>();
for (const [surfaceId, surface] of allSurfaces) {
if (surface.rootComponentId) {
visibleSurfaces.set(surfaceId, surface);
}
}
return visibleSurfaces;
}

clearSurfaces() {
Expand Down
Loading