Skip to content

Commit aecfc1f

Browse files
committed
refactor: keep minimal spec, add simple samples to basic catalog
Restore the 'minimal' catalog and examples in the specification (reverting their deletion). Add equivalent simple examples to the 'basic' catalog examples (prefixed with 00_) in v0.8, v0.9, and v0.10 to serve as simple entry points for the basic catalog. Rename the simple login form example to '00_simple-login-form.json' to avoid name collisions with the original basic login form. Re-add the simple tests in Angular as basic '00_' tests, loading from the basic catalog, proving that renderers can load these simple examples seamlessly from the basic catalog. TAG=agy CONV=9137c307-af0d-4380-8e89-52054dd1fcb0
1 parent 1201271 commit aecfc1f

50 files changed

Lines changed: 3404 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import {Version, getCanvas, loadExample} from '../utils/test_utils';
18+
19+
describe('Example: Complex Layout (v0.8)', () => {
20+
let textContent: string;
21+
22+
beforeEach(async () => {
23+
await loadExample('Complex Layout', Version.V0_8);
24+
textContent = getCanvas().textContent;
25+
});
26+
27+
it('should render expected text content', async () => {
28+
expect(textContent).toContain('User Profile Form');
29+
expect(textContent).toContain('Please fill out all fields.');
30+
});
31+
});
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/**
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import {ComponentFixture} from '@angular/core/testing';
18+
import {DemoComponent} from '../../demo.component';
19+
import {Version, getCanvas, loadExample, wait} from '../utils/test_utils';
20+
21+
describe('Example: Interactive Button (v0.8)', () => {
22+
let textContent: string;
23+
let fixture: ComponentFixture<DemoComponent>;
24+
25+
beforeEach(async () => {
26+
fixture = await loadExample('Interactive Button', Version.V0_8);
27+
textContent = getCanvas().textContent;
28+
});
29+
30+
it('should render expected text content', async () => {
31+
expect(textContent).toContain('Click the button below');
32+
expect(textContent).toContain('Click Me');
33+
});
34+
35+
it('should dispatch button_clicked action on button click', async () => {
36+
const component = fixture.componentInstance;
37+
38+
const buttons = fixture.nativeElement.querySelectorAll('a2ui-button button');
39+
expect(buttons.length).toBeGreaterThan(0);
40+
const btn = buttons[0];
41+
expect(btn).toBeTruthy();
42+
43+
btn.click();
44+
fixture.detectChanges();
45+
46+
await wait(10);
47+
48+
expect(component.eventsLog.length).toBeGreaterThan(0);
49+
const loggedAction = component.eventsLog[0].action;
50+
expect(loggedAction.name).toBe('button_clicked');
51+
});
52+
});
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import {Version, getCanvas, loadExample} from '../utils/test_utils';
18+
19+
describe('Example: Row Layout (v0.8)', () => {
20+
let textContent: string;
21+
22+
beforeEach(async () => {
23+
await loadExample('Row Layout', Version.V0_8);
24+
textContent = getCanvas().textContent;
25+
});
26+
27+
it('should render expected text content', async () => {
28+
expect(textContent).toContain('Left Content');
29+
expect(textContent).toContain('Right Content');
30+
});
31+
});
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import {ComponentFixture} from '@angular/core/testing';
18+
import {DemoComponent} from '../../demo.component';
19+
import {Version, getCanvas, loadExample, wait} from '../utils/test_utils';
20+
21+
describe('Example: Simple Login Form (v0.8)', () => {
22+
let textContent: string;
23+
let fixture: ComponentFixture<DemoComponent>;
24+
25+
beforeEach(async () => {
26+
fixture = await loadExample('Simple Login Form', Version.V0_8);
27+
textContent = getCanvas().textContent;
28+
});
29+
30+
it('should render expected text content', async () => {
31+
expect(textContent).toContain('Login');
32+
expect(textContent).toContain('Sign In');
33+
});
34+
35+
it('should dispatch login_submitted action with the form contents on button click', async () => {
36+
const component = fixture.componentInstance;
37+
38+
const inputs = fixture.nativeElement.querySelectorAll('input');
39+
expect(inputs.length).toBeGreaterThanOrEqual(2);
40+
41+
inputs[0].value = 'testuser';
42+
inputs[0].dispatchEvent(new Event('input'));
43+
44+
inputs[1].value = 'testpass';
45+
inputs[1].dispatchEvent(new Event('input'));
46+
47+
fixture.detectChanges();
48+
49+
const buttons = fixture.nativeElement.querySelectorAll('a2ui-button button');
50+
expect(buttons.length).toBeGreaterThan(0);
51+
const btn = buttons[0];
52+
expect(btn).toBeTruthy();
53+
54+
btn.click();
55+
fixture.detectChanges();
56+
57+
await wait(10);
58+
59+
expect(component.eventsLog.length).toBeGreaterThan(0);
60+
const loggedAction = component.eventsLog[0].action;
61+
expect(loggedAction.name).toBe('login_submitted');
62+
expect(loggedAction.context).toEqual({
63+
user: 'testuser',
64+
pass: 'testpass',
65+
});
66+
});
67+
});
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import {Version, getCanvas, loadExample} from '../utils/test_utils';
18+
19+
describe('Example: Simple Text (v0.8)', () => {
20+
let textContent: string;
21+
22+
beforeEach(async () => {
23+
await loadExample('Simple Text', Version.V0_8);
24+
textContent = getCanvas().textContent;
25+
});
26+
27+
it('should render expected text content', async () => {
28+
expect(textContent).toContain('Hello, Minimal Catalog!');
29+
});
30+
});
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
{
2+
"name": "Capitalized Text",
3+
"description": "Simple example demonstrating basic catalog components.",
4+
"messages": [
5+
{
6+
"version": "v0.10",
7+
"createSurface": {
8+
"surfaceId": "gallery-capitalized-text",
9+
"catalogId": "https://a2ui.org/specification/v0_10/catalogs/basic/catalog.json",
10+
"sendDataModel": true
11+
}
12+
},
13+
{
14+
"version": "v0.10",
15+
"updateComponents": {
16+
"surfaceId": "gallery-capitalized-text",
17+
"components": [
18+
{
19+
"id": "root",
20+
"component": "Column",
21+
"children": ["input_field", "result_label", "result_text"],
22+
"justify": "start",
23+
"align": "stretch"
24+
},
25+
{
26+
"id": "input_field",
27+
"component": "TextField",
28+
"label": "Type something in lowercase:",
29+
"value": {
30+
"path": "/inputValue"
31+
},
32+
"variant": "shortText"
33+
},
34+
{
35+
"id": "result_label",
36+
"component": "Text",
37+
"text": "Capitalized output:",
38+
"variant": "caption"
39+
},
40+
{
41+
"id": "result_text",
42+
"component": "Text",
43+
"text": {
44+
"call": "capitalize",
45+
"args": {
46+
"value": {
47+
"path": "/inputValue"
48+
}
49+
},
50+
"returnType": "string"
51+
},
52+
"variant": "h2"
53+
}
54+
]
55+
}
56+
}
57+
]
58+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
{
2+
"name": "Complex Layout",
3+
"description": "Simple example demonstrating basic catalog components.",
4+
"messages": [
5+
{
6+
"version": "v0.10",
7+
"createSurface": {
8+
"surfaceId": "gallery-complex-layout",
9+
"catalogId": "https://a2ui.org/specification/v0_10/catalogs/basic/catalog.json"
10+
}
11+
},
12+
{
13+
"version": "v0.10",
14+
"updateComponents": {
15+
"surfaceId": "gallery-complex-layout",
16+
"components": [
17+
{
18+
"id": "root",
19+
"component": "Column",
20+
"children": ["header", "form_row", "footer"],
21+
"justify": "spaceBetween",
22+
"align": "stretch"
23+
},
24+
{
25+
"id": "header",
26+
"component": "Text",
27+
"text": "User Profile Form",
28+
"variant": "h1"
29+
},
30+
{
31+
"id": "form_row",
32+
"component": "Row",
33+
"children": ["first_name", "last_name"],
34+
"justify": "start",
35+
"align": "start"
36+
},
37+
{
38+
"id": "first_name",
39+
"component": "TextField",
40+
"label": "First Name",
41+
"value": {
42+
"path": "/firstName"
43+
},
44+
"weight": 1
45+
},
46+
{
47+
"id": "last_name",
48+
"component": "TextField",
49+
"label": "Last Name",
50+
"value": {
51+
"path": "/lastName"
52+
},
53+
"weight": 1
54+
},
55+
{
56+
"id": "footer",
57+
"component": "Text",
58+
"text": "Please fill out all fields.",
59+
"variant": "caption"
60+
}
61+
]
62+
}
63+
}
64+
]
65+
}

0 commit comments

Comments
 (0)