merge: enable guided Robot onboarding by default

This commit is contained in:
2026-08-16 18:16:11 +08:00
14 changed files with 138 additions and 37 deletions

View File

@@ -65,8 +65,41 @@ async function invoke(handler: ReturnType<typeof createAiHardwareRouteHandler>,
}
describe('AI hardware Host API route', () => {
it('returns the default-off provisioning capability before credentials or upstream access', async () => {
const { handler, fetchImpl, getAccessToken } = setup();
it('returns the default-on provisioning capability before credentials or upstream access', async () => {
const environmentName = 'NIANCODE_AI_HARDWARE_GUIDED_HOTSPOT_BINDING';
const previousValue = process.env[environmentName];
delete process.env[environmentName];
vi.resetModules();
try {
const { createAiHardwareRouteHandler: createHandlerWithoutEnv } = await import('@electron/api/routes/ai-hardware');
const fetchImpl = vi.fn<typeof fetch>().mockResolvedValue(jsonResponse(overview));
const getAccessToken = vi.fn().mockResolvedValue('secret-token');
const handler = createHandlerWithoutEnv({
fetchImpl,
getAccessToken,
apiBaseUrl: 'https://square.example',
});
const result = await invoke(
handler,
'GET',
'/api/works/ai-hardware/provisioning-capabilities',
);
expect(result.payload).toEqual({
success: true,
data: { guided_hotspot_binding: true },
});
expect(getAccessToken).not.toHaveBeenCalled();
expect(fetchImpl).not.toHaveBeenCalled();
} finally {
if (previousValue === undefined) delete process.env[environmentName];
else process.env[environmentName] = previousValue;
vi.resetModules();
}
});
it('honors an explicitly injected disabled provisioning capability', async () => {
const { handler, fetchImpl, getAccessToken } = setup(undefined, { guidedHotspotBinding: false });
const result = await invoke(
handler,
'GET',
@@ -81,6 +114,36 @@ describe('AI hardware Host API route', () => {
expect(fetchImpl).not.toHaveBeenCalled();
});
it('honors the exact environment opt-out when Main loads the route', async () => {
vi.stubEnv('NIANCODE_AI_HARDWARE_GUIDED_HOTSPOT_BINDING', '0');
vi.resetModules();
try {
const { createAiHardwareRouteHandler: createHandlerWithEnv } = await import('@electron/api/routes/ai-hardware');
const fetchImpl = vi.fn<typeof fetch>().mockResolvedValue(jsonResponse(overview));
const getAccessToken = vi.fn().mockResolvedValue('secret-token');
const handler = createHandlerWithEnv({
fetchImpl,
getAccessToken,
apiBaseUrl: 'https://square.example',
});
const result = await invoke(
handler,
'GET',
'/api/works/ai-hardware/provisioning-capabilities',
);
expect(result.payload).toEqual({
success: true,
data: { guided_hotspot_binding: false },
});
expect(getAccessToken).not.toHaveBeenCalled();
expect(fetchImpl).not.toHaveBeenCalled();
} finally {
vi.unstubAllEnvs();
vi.resetModules();
}
});
it('rejects queried, body-bearing, and wrong-method capability requests locally', async () => {
const { handler, fetchImpl, getAccessToken } = setup();
const queried = await invoke(
@@ -129,7 +192,7 @@ describe('AI hardware Host API route', () => {
it('rejects disabled, expanded, or queried portal opens before invoking native or cloud dependencies', async () => {
const openExternal = vi.fn().mockResolvedValue(undefined);
const disabled = setup(undefined, { openExternal });
const disabled = setup(undefined, { guidedHotspotBinding: false, openExternal });
const disabledResult = await invoke(
disabled.handler,
'POST',