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
35 changes: 22 additions & 13 deletions apps/console/src/__tests__/BrowserSimulation.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ const mocks = vi.hoisted(() => {
}
return { data: [] };
}
async findOne(objectName: string, id: string) {
if (objectName === 'kitchen_sink') {
return { id, name: 'Test Sink', amount: 100 };
}
return null;
}
async getObjectSchema(name: string) {
if (name === 'kitchen_sink') {
return {
Expand Down Expand Up @@ -147,6 +153,14 @@ describe('Console Application Simulation', () => {
});

it('Scenario 4: Object Create Form (All Field Types)', async () => {
// Helper function to check if a label exists in the form
const expectLabelToExist = (label: string) => {
const escaped = label.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const regex = new RegExp(escaped, 'i');
const elements = screen.queryAllByText(regex);
expect(elements.length).toBeGreaterThan(0);
};

renderApp('/kitchen_sink');

// 1. Wait for Object View
Expand All @@ -164,10 +178,10 @@ describe('Console Application Simulation', () => {
});

// 4. Verify Field Inputs
// Wait for at least one field to appear to ensure form is loaded
// Wait for form to finish loading and first field to appear
await waitFor(() => {
expect(screen.getByText(/Text \(Name\)/i)).toBeInTheDocument();
}, { timeout: 5000 });
}, { timeout: 10000 });

const fieldLabels = [
'Text (Name)',
Expand All @@ -178,17 +192,12 @@ describe('Console Application Simulation', () => {
'Boolean (Switch)',
];

// Check each label exists
for (const label of fieldLabels) {
const escaped = label.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const regex = new RegExp(escaped, 'i');
const elements = screen.queryAllByText(regex);
if (elements.length === 0) {
console.log(`Failed to find label: ${label}`);
// console.log(document.body.innerHTML); // Too large, but useful if localized
}
expect(elements.length).toBeGreaterThan(0);
}
// Check all labels exist concurrently using Promise.all for faster execution
await Promise.all(
fieldLabels.map(label =>
waitFor(() => expectLabelToExist(label), { timeout: 5000 })
)
);

// 5. Test specific interaction (e.g. typing in name)
// Note: Shadcn/Form labels might be associated via ID, so getByLabelText is safer usually,
Expand Down
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@
"devDependencies": {
"@changesets/cli": "^2.29.8",
"@eslint/js": "^9.39.1",
"@objectstack/cli": "^0.9.0",
"@objectstack/core": "^0.9.0",
"@objectstack/driver-memory": "^0.9.0",
"@objectstack/objectql": "^0.9.0",
"@objectstack/plugin-msw": "^0.9.0",
"@objectstack/runtime": "^0.9.0",
"@objectstack/cli": "^0.9.1",
"@objectstack/core": "^0.9.1",
"@objectstack/driver-memory": "^0.9.1",
"@objectstack/objectql": "^0.9.1",
"@objectstack/plugin-msw": "^0.9.1",
"@objectstack/runtime": "^0.9.1",
Comment on lines +62 to +67
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The upgrade to @objectstack 0.9.1 is incomplete. While the root package.json and several packages were updated, the following package.json files still reference version 0.9.0 and need to be updated:

  • apps/console/package.json (lines 39-44)
  • examples/crm/package.json (lines 18-20, 24)
  • examples/kitchen-sink/package.json (lines 16, 19)
  • examples/msw-todo/package.json (lines 14-19)
  • examples/todo/package.json (lines 14-15, 18)

This inconsistency could lead to version conflicts and unexpected behavior when running these applications or examples. All @objectstack dependencies across the entire monorepo should be upgraded to 0.9.1 to ensure consistency.

Copilot uses AI. Check for mistakes.
Comment on lines +62 to +67
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to Coding Guideline Rule #2 (Documentation Driven Development), any feature implemented or refactored must update the corresponding documentation. This dependency upgrade should be documented in CHANGELOG.md under the [Unreleased] section. The CHANGELOG should note the upgrade from @objectstack 0.9.0 to 0.9.1 and any relevant changes or improvements that come with it.

Copilot generated this review using guidance from repository custom instructions.
"@storybook/addon-essentials": "^8.6.14",
"@storybook/addon-interactions": "^8.6.14",
"@storybook/addon-links": "^8.6.15",
Expand Down Expand Up @@ -117,7 +117,7 @@
},
"dependencies": {
"@hono/node-server": "^1.19.9",
"@objectstack/plugin-hono-server": "^0.9.0",
"@objectstack/plugin-hono-server": "^0.9.1",
"coverage-v8": "0.0.1-security",
"hono": "^4.11.7",
"pino": "^8.21.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
},
"dependencies": {
"@object-ui/types": "workspace:*",
"@objectstack/spec": "^0.9.0",
"@objectstack/spec": "^0.9.1",
"lodash": "^4.17.23",
"zod": "^4.3.6"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/data-objectstack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"dependencies": {
"@object-ui/core": "workspace:*",
"@object-ui/types": "workspace:*",
"@objectstack/client": "^0.9.0"
"@objectstack/client": "^0.9.1"
},
"devDependencies": {
"tsup": "^8.0.1",
Expand Down
11 changes: 7 additions & 4 deletions packages/fields/src/widgets/BooleanField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,18 @@
return <span className="text-sm">{value ? 'Yes' : 'No'}</span>;
}

// Filter out non-DOM props
const { inputType, ...domProps } = props as any;

if (widget === 'checkbox') {
return (
<div className="flex items-center space-x-2">
<Checkbox
{...props}
{...domProps}
id={id}
checked={!!value}
onCheckedChange={(checked) => onChange(!!checked)}
disabled={readonly || props.disabled}
disabled={readonly || domProps.disabled}

Check warning

Code scanning / CodeQL

Useless conditional Warning

This use of variable 'readonly' always evaluates to false.
/>
<Label htmlFor={id}>{label}</Label>
</div>
Expand All @@ -33,11 +36,11 @@
return (
<div className="flex items-center space-x-2">
<Switch
{...props}
{...domProps}
id={id}
checked={!!value}
onCheckedChange={onChange}
disabled={readonly || props.disabled}
disabled={readonly || domProps.disabled}

Check warning

Code scanning / CodeQL

Useless conditional Warning

This use of variable 'readonly' always evaluates to false.
/>
<Label htmlFor={id}>{label}</Label>
</div>
Expand Down
7 changes: 5 additions & 2 deletions packages/fields/src/widgets/DateField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@
return <span className="text-sm">{value ? new Date(value).toLocaleDateString() : '-'}</span>;
}

// Filter out non-DOM props
const { inputType, ...domProps } = props as any;

return (
<Input
{...props}
{...domProps}
type="date"
value={value || ''}
onChange={(e) => onChange(e.target.value)}
disabled={readonly || props.disabled}
disabled={readonly || domProps.disabled}

Check warning

Code scanning / CodeQL

Useless conditional Warning

This use of variable 'readonly' always evaluates to false.
/>
);
}
7 changes: 5 additions & 2 deletions packages/fields/src/widgets/DateTimeField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@
);
}

// Filter out non-DOM props
const { inputType, ...domProps } = props as any;

return (
<Input
{...props}
{...domProps}
type="datetime-local"
value={value || ''}
onChange={(e) => onChange(e.target.value)}
disabled={readonly || props.disabled}
disabled={readonly || domProps.disabled}

Check warning

Code scanning / CodeQL

Useless conditional Warning

This use of variable 'readonly' always evaluates to false.
/>
);
}
7 changes: 5 additions & 2 deletions packages/fields/src/widgets/EmailField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@
);
}

// Filter out non-DOM props
const { inputType, ...domProps } = props as any;

return (
<Input
{...props}
{...domProps}
type="email"
value={value || ''}
onChange={(e) => onChange(e.target.value)}
placeholder={config?.placeholder || 'email@example.com'}
disabled={readonly || props.disabled}
disabled={readonly || domProps.disabled}

Check warning

Code scanning / CodeQL

Useless conditional Warning

This use of variable 'readonly' always evaluates to false.
aria-invalid={!!errorMessage}
/>
);
Expand Down
7 changes: 5 additions & 2 deletions packages/fields/src/widgets/NumberField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,20 @@
const numberField = (field || (props as any).schema) as NumberFieldMetadata;
const precision = numberField?.precision;

// Filter out non-DOM props
const { inputType, ...domProps } = props as any;

return (
<Input
{...props}
{...domProps}
type="number"
value={value ?? ''}
onChange={(e) => {
const val = e.target.value;
onChange(val === '' ? (null as any) : Number(val));
}}
placeholder={numberField?.placeholder}
disabled={readonly || props.disabled}
disabled={readonly || domProps.disabled}

Check warning

Code scanning / CodeQL

Useless conditional Warning

This use of variable 'readonly' always evaluates to false.
step={precision ? Math.pow(10, -precision) : 'any'}
/>
);
Expand Down
7 changes: 5 additions & 2 deletions packages/fields/src/widgets/PasswordField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,18 @@
return <span className="text-sm">••••••••</span>;
}

// Filter out non-DOM props
const { inputType, ...domProps } = props as any;

return (
<div className="relative">
<Input
{...props}
{...domProps}
type={showPassword ? 'text' : 'password'}
value={value || ''}
onChange={(e) => onChange(e.target.value)}
placeholder={config?.placeholder}
disabled={readonly || props.disabled}
disabled={readonly || domProps.disabled}

Check warning

Code scanning / CodeQL

Useless conditional Warning

This use of variable 'readonly' always evaluates to false.
className={`pr-10 ${className || ''}`}
/>
<Button
Expand Down
7 changes: 5 additions & 2 deletions packages/fields/src/widgets/PhoneField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@
);
}

// Filter out non-DOM props
const { inputType, ...domProps } = props as any;

return (
<Input
{...props}
{...domProps}
type="tel"
value={value || ''}
onChange={(e) => onChange(e.target.value)}
placeholder={config?.placeholder || '(555) 123-4567'}
disabled={readonly || props.disabled}
disabled={readonly || domProps.disabled}

Check warning

Code scanning / CodeQL

Useless conditional Warning

This use of variable 'readonly' always evaluates to false.
aria-invalid={!!errorMessage}
/>
);
Expand Down
7 changes: 5 additions & 2 deletions packages/fields/src/widgets/TextAreaField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@
const rows = textareaField?.rows || 4;
const maxLength = textareaField?.max_length;

// Filter out non-DOM props
const { inputType, ...domProps } = props as any;

return (
<div className="relative">
<Textarea
{...props}
{...domProps}
value={value || ''}
onChange={(e) => onChange(e.target.value)}
placeholder={textareaField?.placeholder}
disabled={readonly || props.disabled}
disabled={readonly || domProps.disabled}

Check warning

Code scanning / CodeQL

Useless conditional Warning

This use of variable 'readonly' always evaluates to false.
rows={rows}
maxLength={maxLength}
aria-invalid={!!errorMessage}
Expand Down
11 changes: 7 additions & 4 deletions packages/fields/src/widgets/TextField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,29 @@
// Cast for rows property
const rows = (fieldData as unknown as TextareaFieldMetadata)?.rows;

// Filter out non-DOM props
const { inputType, ...domProps } = props as any;

if (rows && rows > 1) {
return (
<Textarea
{...props}
{...domProps}
value={value || ''}
onChange={(e) => onChange(e.target.value)}
placeholder={fieldData?.placeholder}
disabled={readonly || props.disabled}
disabled={readonly || domProps.disabled}

Check warning

Code scanning / CodeQL

Useless conditional Warning

This use of variable 'readonly' always evaluates to false.
/>
);
}

return (
<Input
{...props}
{...domProps}
type={fieldData?.type === 'password' ? 'password' : 'text'}
value={value || ''}
onChange={(e) => onChange(e.target.value)}
placeholder={fieldData?.placeholder}
disabled={readonly || props.disabled}
disabled={readonly || domProps.disabled}

Check warning

Code scanning / CodeQL

Useless conditional Warning

This use of variable 'readonly' always evaluates to false.
/>
);
}
7 changes: 5 additions & 2 deletions packages/fields/src/widgets/TimeField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@
return <span className="text-sm">{value || '-'}</span>;
}

// Filter out non-DOM props
const { inputType, ...domProps } = props as any;

return (
<Input
{...props}
{...domProps}
type="time"
value={value || ''}
onChange={(e) => onChange(e.target.value)}
disabled={readonly || props.disabled}
disabled={readonly || domProps.disabled}

Check warning

Code scanning / CodeQL

Useless conditional Warning

This use of variable 'readonly' always evaluates to false.
/>
);
}
7 changes: 5 additions & 2 deletions packages/fields/src/widgets/UrlField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,17 @@
);
}

// Filter out non-DOM props
const { inputType, ...domProps } = props as any;

return (
<Input
{...props}
{...domProps}
type="url"
value={value || ''}
onChange={(e) => onChange(e.target.value)}
placeholder={config?.placeholder || 'https://example.com'}
disabled={readonly || props.disabled}
disabled={readonly || domProps.disabled}

Check warning

Code scanning / CodeQL

Useless conditional Warning

This use of variable 'readonly' always evaluates to false.
aria-invalid={!!errorMessage}
/>
);
Expand Down
2 changes: 1 addition & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
},
"dependencies": {
"@object-ui/core": "workspace:*",
"@objectstack/spec": "^0.9.0",
"@objectstack/spec": "^0.9.1",
"react-hook-form": "^7.71.1"
},
"peerDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/types/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
"directory": "packages/types"
},
"dependencies": {
"@objectstack/spec": "^0.9.0",
"@objectstack/spec": "^0.9.1",
"zod": "^4.3.6"
},
"devDependencies": {
Expand Down
Loading
Loading