@coffeerunhobby/mcp-ha-connect 2.2.1 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +1 -1
- package/README.md +24 -2
- package/dist/omadaClient/accessControl.d.ts +290 -0
- package/dist/omadaClient/accessControl.js +509 -0
- package/dist/omadaClient/accessControl.js.map +1 -0
- package/dist/omadaClient/client.d.ts +6 -1
- package/dist/omadaClient/client.js +12 -1
- package/dist/omadaClient/client.js.map +1 -1
- package/dist/omadaClient/diagnose.d.ts +68 -0
- package/dist/omadaClient/diagnose.js +164 -0
- package/dist/omadaClient/diagnose.js.map +1 -0
- package/dist/omadaClient/index.d.ts +9 -0
- package/dist/omadaClient/index.js +19 -0
- package/dist/omadaClient/index.js.map +1 -1
- package/dist/omadaClient/macGroups.d.ts +58 -0
- package/dist/omadaClient/macGroups.js +110 -0
- package/dist/omadaClient/macGroups.js.map +1 -0
- package/dist/omadaClient/serialize.d.ts +13 -0
- package/dist/omadaClient/serialize.js +29 -0
- package/dist/omadaClient/serialize.js.map +1 -0
- package/dist/omadaClient/timeRange.d.ts +41 -0
- package/dist/omadaClient/timeRange.js +109 -0
- package/dist/omadaClient/timeRange.js.map +1 -0
- package/dist/tools/infra/actions.d.ts +1 -1
- package/dist/tools/infra/actions.js +1 -1
- package/dist/tools/omada/accessControl.d.ts +151 -0
- package/dist/tools/omada/accessControl.js +158 -0
- package/dist/tools/omada/accessControl.js.map +1 -0
- package/dist/tools/omada/index.js +9 -0
- package/dist/tools/omada/index.js.map +1 -1
- package/dist/tools/omada/macGroups.d.ts +19 -0
- package/dist/tools/omada/macGroups.js +77 -0
- package/dist/tools/omada/macGroups.js.map +1 -0
- package/dist/tools/omada/namespace.js +16 -0
- package/dist/tools/omada/namespace.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +5 -1
- package/.codex/review-rules.md +0 -16
- package/.dockerignore +0 -8
- package/.gitattributes +0 -30
- package/.github/workflows/ci.yml +0 -193
- package/AGENTS.md +0 -389
- package/Dockerfile +0 -50
- package/docker-compose.yml +0 -23
- package/docs/CHANGELOG.md +0 -341
- package/docs/COVERAGE.md +0 -219
- package/docs/QUICK_START.md +0 -240
- package/eslint.config.js +0 -33
- package/n8n/ai-agent-safety-monitor.json +0 -355
- package/openapi.json +0 -1259
- package/scripts/check-version-sync.mjs +0 -69
- package/scripts/generate-jwt.ts +0 -121
- package/src/config.ts +0 -440
- package/src/haClient/automations.ts +0 -261
- package/src/haClient/calendars.ts +0 -94
- package/src/haClient/config.ts +0 -52
- package/src/haClient/devices.ts +0 -653
- package/src/haClient/entities.ts +0 -128
- package/src/haClient/events.ts +0 -689
- package/src/haClient/history.ts +0 -73
- package/src/haClient/index.ts +0 -336
- package/src/haClient/request.ts +0 -142
- package/src/haClient/services.ts +0 -45
- package/src/haClient/states.ts +0 -60
- package/src/haClient/updates.ts +0 -58
- package/src/haClient/wsCommand.ts +0 -44
- package/src/index.ts +0 -164
- package/src/localAI/index.ts +0 -88
- package/src/localAI/prompts.ts +0 -50
- package/src/localAI/providers/base.ts +0 -120
- package/src/localAI/providers/ollama.ts +0 -78
- package/src/localAI/providers/openai.ts +0 -86
- package/src/localAI/types.ts +0 -67
- package/src/omadaClient/auth.ts +0 -178
- package/src/omadaClient/client.ts +0 -337
- package/src/omadaClient/device.ts +0 -118
- package/src/omadaClient/index.ts +0 -310
- package/src/omadaClient/network.ts +0 -284
- package/src/omadaClient/request.ts +0 -365
- package/src/omadaClient/security.ts +0 -51
- package/src/omadaClient/site.ts +0 -344
- package/src/ownerQuestions/service.ts +0 -536
- package/src/permissions/index.ts +0 -143
- package/src/resources/index.ts +0 -213
- package/src/server/auth.ts +0 -175
- package/src/server/chatFace.ts +0 -789
- package/src/server/chatSlice.ts +0 -57
- package/src/server/common.ts +0 -170
- package/src/server/eventSubscription.ts +0 -343
- package/src/server/http.ts +0 -626
- package/src/server/instructions.ts +0 -97
- package/src/server/rateLimiter.ts +0 -227
- package/src/server/stdio.ts +0 -41
- package/src/server/stream.ts +0 -205
- package/src/tools/ai/analyzeSensors.ts +0 -33
- package/src/tools/ai/index.ts +0 -20
- package/src/tools/common.ts +0 -442
- package/src/tools/homeassistant/askOwner.ts +0 -133
- package/src/tools/homeassistant/automationControls.ts +0 -66
- package/src/tools/homeassistant/calendar.ts +0 -97
- package/src/tools/homeassistant/callService.ts +0 -25
- package/src/tools/homeassistant/controlClimate.ts +0 -68
- package/src/tools/homeassistant/controlCover.ts +0 -48
- package/src/tools/homeassistant/controlFan.ts +0 -44
- package/src/tools/homeassistant/controlLight.ts +0 -38
- package/src/tools/homeassistant/controlMediaPlayer.ts +0 -50
- package/src/tools/homeassistant/createAutomation.ts +0 -35
- package/src/tools/homeassistant/deleteAutomation.ts +0 -24
- package/src/tools/homeassistant/entityAction.ts +0 -35
- package/src/tools/homeassistant/entityGuard.ts +0 -28
- package/src/tools/homeassistant/getAllSensors.ts +0 -46
- package/src/tools/homeassistant/getAutomationTrace.ts +0 -30
- package/src/tools/homeassistant/getDomainSummary.ts +0 -29
- package/src/tools/homeassistant/getEntitiesByDomain.ts +0 -56
- package/src/tools/homeassistant/getHistory.ts +0 -24
- package/src/tools/homeassistant/getState.ts +0 -24
- package/src/tools/homeassistant/getStates.ts +0 -46
- package/src/tools/homeassistant/getVersion.ts +0 -21
- package/src/tools/homeassistant/index.ts +0 -121
- package/src/tools/homeassistant/listAutomations.ts +0 -35
- package/src/tools/homeassistant/listEntities.ts +0 -44
- package/src/tools/homeassistant/listPersons.ts +0 -46
- package/src/tools/homeassistant/sceneAndScript.ts +0 -53
- package/src/tools/homeassistant/searchEntities.ts +0 -58
- package/src/tools/homeassistant/sendNotification.ts +0 -179
- package/src/tools/homeassistant/systemTools.ts +0 -52
- package/src/tools/homeassistant/triggerAutomation.ts +0 -24
- package/src/tools/index.ts +0 -78
- package/src/tools/infra/actions.ts +0 -95
- package/src/tools/infra/index.ts +0 -138
- package/src/tools/omada/blockClient.ts +0 -28
- package/src/tools/omada/cyclePoePort.ts +0 -32
- package/src/tools/omada/deleteClient.ts +0 -27
- package/src/tools/omada/disableClientRateLimit.ts +0 -23
- package/src/tools/omada/getClient.ts +0 -14
- package/src/tools/omada/getDevice.ts +0 -14
- package/src/tools/omada/getFirewallSetting.ts +0 -14
- package/src/tools/omada/getInternetInfo.ts +0 -14
- package/src/tools/omada/getLanNetworkList.ts +0 -14
- package/src/tools/omada/getLanProfileList.ts +0 -14
- package/src/tools/omada/getPortForwardingStatus.ts +0 -26
- package/src/tools/omada/getRateLimitProfiles.ts +0 -14
- package/src/tools/omada/getSiteNtpStatus.ts +0 -14
- package/src/tools/omada/getSsidDetail.ts +0 -22
- package/src/tools/omada/getSsidList.ts +0 -21
- package/src/tools/omada/getSwitchStackDetail.ts +0 -14
- package/src/tools/omada/getThreatList.ts +0 -42
- package/src/tools/omada/getWlanGroupList.ts +0 -14
- package/src/tools/omada/graph.ts +0 -187
- package/src/tools/omada/index.ts +0 -153
- package/src/tools/omada/listBlockedClients.ts +0 -17
- package/src/tools/omada/listClients.ts +0 -14
- package/src/tools/omada/listClientsActivity.ts +0 -25
- package/src/tools/omada/listClientsPastConnections.ts +0 -44
- package/src/tools/omada/listDevices.ts +0 -14
- package/src/tools/omada/listDevicesStats.ts +0 -41
- package/src/tools/omada/listMostActiveClients.ts +0 -14
- package/src/tools/omada/listSites.ts +0 -18
- package/src/tools/omada/namespace.ts +0 -1164
- package/src/tools/omada/searchDevices.ts +0 -20
- package/src/tools/omada/setClientRateLimit.ts +0 -26
- package/src/tools/omada/setClientRateLimitProfile.ts +0 -25
- package/src/tools/omada/setSiteNtpServers.ts +0 -36
- package/src/tools/omada/setSsidEnabled.ts +0 -38
- package/src/tools/omada/unblockClient.ts +0 -26
- package/src/tools/types.ts +0 -11
- package/src/tools/utils/pagination-schema.ts +0 -27
- package/src/types/ai/index.ts +0 -11
- package/src/types/ai/types.ts +0 -67
- package/src/types/homeassistant/automations.ts +0 -43
- package/src/types/homeassistant/calendars.ts +0 -26
- package/src/types/homeassistant/config.ts +0 -14
- package/src/types/homeassistant/entities.ts +0 -14
- package/src/types/homeassistant/errors.ts +0 -33
- package/src/types/homeassistant/haConfig.ts +0 -7
- package/src/types/homeassistant/history.ts +0 -13
- package/src/types/homeassistant/index.ts +0 -46
- package/src/types/homeassistant/request.ts +0 -6
- package/src/types/homeassistant/serviceCall.ts +0 -18
- package/src/types/homeassistant/states.ts +0 -58
- package/src/types/homeassistant/updates.ts +0 -28
- package/src/types/index.ts +0 -12
- package/src/types/omada/activeClientInfo.ts +0 -17
- package/src/types/omada/clientActivity.ts +0 -32
- package/src/types/omada/clientBlockStatus.ts +0 -11
- package/src/types/omada/clientPastConnection.ts +0 -82
- package/src/types/omada/index.ts +0 -14
- package/src/types/omada/omadaApiResponse.ts +0 -5
- package/src/types/omada/omadaClientInfo.ts +0 -11
- package/src/types/omada/omadaDeviceInfo.ts +0 -11
- package/src/types/omada/omadaDeviceStats.ts +0 -31
- package/src/types/omada/omadaSiteSummary.ts +0 -5
- package/src/types/omada/oswStackDetail.ts +0 -11
- package/src/types/omada/paginatedResult.ts +0 -6
- package/src/types/omada/rateLimitProfile.ts +0 -58
- package/src/types/omada/threatInfo.ts +0 -38
- package/src/types/omada/tokenResult.ts +0 -6
- package/src/types.ts +0 -2
- package/src/utils/config-validations.ts +0 -68
- package/src/utils/jwt.ts +0 -112
- package/src/utils/logger.ts +0 -121
- package/src/utils/plainText.ts +0 -48
- package/src/utils/redact.ts +0 -59
- package/src/utils/sanitizeError.ts +0 -18
- package/src/utils/tlsDispatcher.ts +0 -69
- package/src/version.ts +0 -5
- package/tests/bdd/automation-creation.spec.ts +0 -214
- package/tests/bdd/automation-management.spec.ts +0 -267
- package/tests/bdd/calendar.spec.ts +0 -190
- package/tests/bdd/configuration.spec.ts +0 -283
- package/tests/bdd/device-control.spec.ts +0 -344
- package/tests/bdd/entity-listing.spec.ts +0 -208
- package/tests/bdd/entity-search.spec.ts +0 -183
- package/tests/bdd/history-retrieval.spec.ts +0 -195
- package/tests/bdd/notifications.spec.ts +0 -238
- package/tests/bdd/service-calls.spec.ts +0 -144
- package/tests/bdd/state-retrieval.spec.ts +0 -204
- package/tests/bench/hotpaths.bench.ts +0 -68
- package/tests/config.test.ts +0 -355
- package/tests/features/automation-creation.feature +0 -36
- package/tests/features/automation-management.feature +0 -54
- package/tests/features/calendar.feature +0 -37
- package/tests/features/configuration.feature +0 -70
- package/tests/features/device-control.feature +0 -100
- package/tests/features/entity-listing.feature +0 -51
- package/tests/features/entity-search.feature +0 -44
- package/tests/features/history-retrieval.feature +0 -38
- package/tests/features/notifications.feature +0 -37
- package/tests/features/service-calls.feature +0 -35
- package/tests/features/state-retrieval.feature +0 -37
- package/tests/fixtures/openapi-default-slice.json +0 -290
- package/tests/haClient/automationTrace.test.ts +0 -59
- package/tests/haClient/automations.test.ts +0 -149
- package/tests/haClient/config.test.ts +0 -117
- package/tests/haClient/entities.test.ts +0 -188
- package/tests/haClient/events.test.ts +0 -455
- package/tests/haClient/eventsTls.test.ts +0 -52
- package/tests/haClient/history.test.ts +0 -228
- package/tests/haClient/index.test.ts +0 -243
- package/tests/haClient/request.test.ts +0 -217
- package/tests/haClient/services.test.ts +0 -120
- package/tests/haClient/states.test.ts +0 -119
- package/tests/haClient/updates.test.ts +0 -193
- package/tests/index.test.ts +0 -160
- package/tests/integration/homeassistant.test.ts +0 -144
- package/tests/integration/omada.test.ts +0 -167
- package/tests/integration/server.test.ts +0 -151
- package/tests/localAI/index.test.ts +0 -177
- package/tests/localAI/ollama.test.ts +0 -187
- package/tests/localAI/openai.test.ts +0 -257
- package/tests/omadaClient/actions.test.ts +0 -161
- package/tests/omadaClient/clientBlocks.test.ts +0 -170
- package/tests/omadaClient/ntp.test.ts +0 -381
- package/tests/omadaClient/site.test.ts +0 -37
- package/tests/ownerQuestions/service.test.ts +0 -499
- package/tests/ownerQuestions/tools.test.ts +0 -186
- package/tests/permissions/index.test.ts +0 -217
- package/tests/resources/index.test.ts +0 -288
- package/tests/scripts/generateJwt.test.ts +0 -44
- package/tests/security/accessControl.test.ts +0 -223
- package/tests/security/authentication.test.ts +0 -117
- package/tests/security/configuration.test.ts +0 -170
- package/tests/security/cryptoTransport.test.ts +0 -172
- package/tests/security/dependencies.test.ts +0 -152
- package/tests/security/injection.test.ts +0 -117
- package/tests/security/insecureDesign.test.ts +0 -121
- package/tests/security/logging.test.ts +0 -131
- package/tests/security/resourceConsumption.test.ts +0 -142
- package/tests/server/auth.test.ts +0 -249
- package/tests/server/chatFace.test.ts +0 -320
- package/tests/server/common.test.ts +0 -84
- package/tests/server/http.test.ts +0 -561
- package/tests/server/instructions.test.ts +0 -152
- package/tests/server/memoizeJsonSchema.test.ts +0 -71
- package/tests/server/stdio.test.ts +0 -99
- package/tests/server/stream.test.ts +0 -285
- package/tests/server/toolVisibility.http.test.ts +0 -111
- package/tests/server/toolVisibility.test.ts +0 -129
- package/tests/tools/ai/analyzeSensors.test.ts +0 -227
- package/tests/tools/common.test.ts +0 -123
- package/tests/tools/homeassistant/handlers.test.ts +0 -872
- package/tests/tools/infra/invokeAction.test.ts +0 -280
- package/tests/tools/omada/graph.test.ts +0 -385
- package/tests/tools/omada/handlers.test.ts +0 -897
- package/tests/tools/omada/namespace.test.ts +0 -483
- package/tests/tools/registry.test.ts +0 -168
- package/tests/utils/config-validations.test.ts +0 -352
- package/tests/utils/jwt.test.ts +0 -115
- package/tests/utils/logger.test.ts +0 -327
- package/tests/utils/redact.test.ts +0 -105
- package/tsconfig.json +0 -24
- package/vitest.config.ts +0 -38
package/tests/config.test.ts
DELETED
|
@@ -1,355 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Configuration tests
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
6
|
-
import { loadConfig, validateConfig } from '../src/config.js';
|
|
7
|
-
import type { EnvironmentConfig } from '../src/config.js';
|
|
8
|
-
|
|
9
|
-
describe('loadConfig', () => {
|
|
10
|
-
let originalEnv: NodeJS.ProcessEnv;
|
|
11
|
-
|
|
12
|
-
beforeEach(() => {
|
|
13
|
-
originalEnv = { ...process.env };
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('should load valid configuration from environment', () => {
|
|
17
|
-
const env = {
|
|
18
|
-
HA_URL: 'http://homeassistant.10.0.0.19.nip.io:8123',
|
|
19
|
-
HA_TOKEN: 'test-token-12345',
|
|
20
|
-
HA_STRICT_SSL: 'false',
|
|
21
|
-
HA_TIMEOUT: '30000',
|
|
22
|
-
MCP_SERVER_LOG_LEVEL: 'info',
|
|
23
|
-
MCP_SERVER_LOG_FORMAT: 'plain',
|
|
24
|
-
MCP_SERVER_USE_HTTP: 'false',
|
|
25
|
-
MCP_SERVER_STATEFUL: 'false',
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const config = loadConfig(env);
|
|
29
|
-
|
|
30
|
-
expect(config.baseUrl).toBe('http://homeassistant.10.0.0.19.nip.io:8123');
|
|
31
|
-
expect(config.token).toBe('test-token-12345');
|
|
32
|
-
expect(config.strictSsl).toBe(false);
|
|
33
|
-
expect(config.timeout).toBe(30000);
|
|
34
|
-
expect(config.logLevel).toBe('info');
|
|
35
|
-
expect(config.logFormat).toBe('plain');
|
|
36
|
-
expect(config.useHttp).toBe(false);
|
|
37
|
-
expect(config.stateful).toBe(false);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('parses owner question settings (enabled by default; HA users as a trimmed list)', () => {
|
|
41
|
-
const base = { HA_URL: 'http://homeassistant.10.0.0.19.nip.io:8123', HA_TOKEN: 't' };
|
|
42
|
-
|
|
43
|
-
const defaults = loadConfig(base);
|
|
44
|
-
expect(defaults.ownerQuestionsEnabled).toBe(true);
|
|
45
|
-
expect(defaults.ownerQuestionsHaUsers).toEqual([]);
|
|
46
|
-
|
|
47
|
-
const set = loadConfig({ ...base, MCP_OWNER_QUESTIONS_ENABLED: 'false', MCP_OWNER_QUESTIONS_HA_USERS: ' a1b2 , c3d4 ,' });
|
|
48
|
-
expect(set.ownerQuestionsEnabled).toBe(false);
|
|
49
|
-
expect(set.ownerQuestionsHaUsers).toEqual(['a1b2', 'c3d4']);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('should apply default values for optional fields', () => {
|
|
53
|
-
const env = {
|
|
54
|
-
HA_URL: 'http://homeassistant.10.0.0.19.nip.io:8123',
|
|
55
|
-
HA_TOKEN: 'test-token-12345',
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const config = loadConfig(env);
|
|
59
|
-
|
|
60
|
-
expect(config.strictSsl).toBe(true); // default
|
|
61
|
-
expect(config.timeout).toBe(30000); // default
|
|
62
|
-
expect(config.logLevel).toBe('info'); // default
|
|
63
|
-
expect(config.logFormat).toBe('plain'); // default
|
|
64
|
-
expect(config.useHttp).toBe(false); // default
|
|
65
|
-
expect(config.stateful).toBe(false); // default
|
|
66
|
-
expect(config.toolRegistrationMode).toBe('eager'); // default
|
|
67
|
-
expect(config.httpEnableHealthcheck).toBe(true); // default
|
|
68
|
-
expect(config.httpAllowCors).toBe(true); // default
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
describe('toolRegistrationMode (MCP_TOOL_REGISTRATION_MODE)', () => {
|
|
72
|
-
it('defaults to "eager" when unset', () => {
|
|
73
|
-
const config = loadConfig({
|
|
74
|
-
HA_URL: 'http://homeassistant.10.0.0.19.nip.io:8123',
|
|
75
|
-
HA_TOKEN: 'test-token-12345',
|
|
76
|
-
});
|
|
77
|
-
expect(config.toolRegistrationMode).toBe('eager');
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('parses "graph"', () => {
|
|
81
|
-
const config = loadConfig({
|
|
82
|
-
HA_URL: 'http://homeassistant.10.0.0.19.nip.io:8123',
|
|
83
|
-
HA_TOKEN: 'test-token-12345',
|
|
84
|
-
MCP_TOOL_REGISTRATION_MODE: 'graph',
|
|
85
|
-
});
|
|
86
|
-
expect(config.toolRegistrationMode).toBe('graph');
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it('rejects an unknown mode', () => {
|
|
90
|
-
expect(() =>
|
|
91
|
-
loadConfig({
|
|
92
|
-
HA_URL: 'http://homeassistant.10.0.0.19.nip.io:8123',
|
|
93
|
-
HA_TOKEN: 'test-token-12345',
|
|
94
|
-
MCP_TOOL_REGISTRATION_MODE: 'lazy',
|
|
95
|
-
})
|
|
96
|
-
).toThrow('Invalid environment configuration');
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it('should remove trailing slash from baseUrl', () => {
|
|
101
|
-
const env = {
|
|
102
|
-
HA_URL: 'http://homeassistant.10.0.0.19.nip.io:8123/',
|
|
103
|
-
HA_TOKEN: 'test-token-12345',
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
const config = loadConfig(env);
|
|
107
|
-
|
|
108
|
-
expect(config.baseUrl).toBe('http://homeassistant.10.0.0.19.nip.io:8123');
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it('should allow missing HA_URL (Omada-only mode)', () => {
|
|
112
|
-
const env = {
|
|
113
|
-
HA_TOKEN: 'test-token-12345',
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
const config = loadConfig(env);
|
|
117
|
-
expect(config.baseUrl).toBeUndefined();
|
|
118
|
-
expect(config.token).toBe('test-token-12345');
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
it('should allow missing HA_TOKEN (Omada-only mode)', () => {
|
|
122
|
-
const env = {
|
|
123
|
-
HA_URL: 'http://homeassistant.10.0.0.19.nip.io:8123',
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
const config = loadConfig(env);
|
|
127
|
-
expect(config.baseUrl).toBe('http://homeassistant.10.0.0.19.nip.io:8123');
|
|
128
|
-
expect(config.token).toBeUndefined();
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
it('should throw error for invalid HA_URL', () => {
|
|
132
|
-
const env = {
|
|
133
|
-
HA_URL: 'not-a-url',
|
|
134
|
-
HA_TOKEN: 'test-token-12345',
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
expect(() => loadConfig(env)).toThrow('Invalid environment configuration');
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it('should parse HTTP configuration when USE_HTTP is true', () => {
|
|
141
|
-
const env = {
|
|
142
|
-
HA_URL: 'http://homeassistant.10.0.0.19.nip.io:8123',
|
|
143
|
-
HA_TOKEN: 'test-token-12345',
|
|
144
|
-
MCP_SERVER_USE_HTTP: 'true',
|
|
145
|
-
MCP_HTTP_PORT: '3000',
|
|
146
|
-
MCP_HTTP_BIND_ADDR: '127.0.0.1',
|
|
147
|
-
MCP_HTTP_PATH: '/mcp',
|
|
148
|
-
MCP_HTTP_ENABLE_HEALTHCHECK: 'true',
|
|
149
|
-
MCP_HTTP_HEALTHCHECK_PATH: '/health',
|
|
150
|
-
MCP_HTTP_ALLOW_CORS: 'true',
|
|
151
|
-
MCP_HTTP_ALLOWED_ORIGINS: '127.0.0.1,localhost',
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
const config = loadConfig(env);
|
|
155
|
-
|
|
156
|
-
expect(config.useHttp).toBe(true);
|
|
157
|
-
expect(config.httpPort).toBe(3000);
|
|
158
|
-
expect(config.httpBindAddr).toBe('127.0.0.1');
|
|
159
|
-
expect(config.httpPath).toBe('/mcp');
|
|
160
|
-
expect(config.httpEnableHealthcheck).toBe(true);
|
|
161
|
-
expect(config.httpHealthcheckPath).toBe('/health');
|
|
162
|
-
expect(config.httpAllowCors).toBe(true);
|
|
163
|
-
expect(config.httpAllowedOrigins).toEqual(['127.0.0.1', 'localhost']);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
it('should use default httpPath /mcp', () => {
|
|
167
|
-
const env = {
|
|
168
|
-
HA_URL: 'http://homeassistant.10.0.0.19.nip.io:8123',
|
|
169
|
-
HA_TOKEN: 'test-token-12345',
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
const config = loadConfig(env);
|
|
173
|
-
expect(config.httpPath).toBe('/mcp');
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it('should handle wildcard in allowed origins', () => {
|
|
177
|
-
const env = {
|
|
178
|
-
HA_URL: 'http://homeassistant.10.0.0.19.nip.io:8123',
|
|
179
|
-
HA_TOKEN: 'test-token-12345',
|
|
180
|
-
MCP_HTTP_ALLOWED_ORIGINS: '*',
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
const config = loadConfig(env);
|
|
184
|
-
|
|
185
|
-
// Wildcard should result in empty array to disable SDK validation
|
|
186
|
-
expect(config.httpAllowedOrigins).toEqual([]);
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
it('should parse comma-separated origins', () => {
|
|
190
|
-
const env = {
|
|
191
|
-
HA_URL: 'http://homeassistant.10.0.0.19.nip.io:8123',
|
|
192
|
-
HA_TOKEN: 'test-token-12345',
|
|
193
|
-
MCP_HTTP_ALLOWED_ORIGINS: 'http://mcpserver.10.0.0.18.nip.io:3000,http://192.168.0.10:8080,localhost',
|
|
194
|
-
};
|
|
195
|
-
|
|
196
|
-
const config = loadConfig(env);
|
|
197
|
-
|
|
198
|
-
expect(config.httpAllowedOrigins).toEqual([
|
|
199
|
-
'http://mcpserver.10.0.0.18.nip.io:3000',
|
|
200
|
-
'http://192.168.0.10:8080',
|
|
201
|
-
'localhost',
|
|
202
|
-
]);
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
it('should throw error for invalid bind address', () => {
|
|
206
|
-
const env = {
|
|
207
|
-
HA_URL: 'http://homeassistant.10.0.0.19.nip.io:8123',
|
|
208
|
-
HA_TOKEN: 'test-token-12345',
|
|
209
|
-
MCP_HTTP_BIND_ADDR: 'invalid-ip',
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
expect(() => loadConfig(env)).toThrow('MCP_HTTP_BIND_ADDR must be a valid IPv4 or IPv6 address');
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
it('should accept valid IPv4 bind address', () => {
|
|
216
|
-
const env = {
|
|
217
|
-
HA_URL: 'http://homeassistant.10.0.0.19.nip.io:8123',
|
|
218
|
-
HA_TOKEN: 'test-token-12345',
|
|
219
|
-
MCP_HTTP_BIND_ADDR: '192.168.1.100',
|
|
220
|
-
// H5: a non-loopback bind requires authentication.
|
|
221
|
-
MCP_AUTH_METHOD: 'bearer',
|
|
222
|
-
MCP_AUTH_SECRET: 'test-secret-key-32chars-minimum!',
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
const config = loadConfig(env);
|
|
226
|
-
expect(config.httpBindAddr).toBe('192.168.1.100');
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
it('should accept valid IPv6 bind address', () => {
|
|
230
|
-
const env = {
|
|
231
|
-
HA_URL: 'http://homeassistant.10.0.0.19.nip.io:8123',
|
|
232
|
-
HA_TOKEN: 'test-token-12345',
|
|
233
|
-
MCP_HTTP_BIND_ADDR: '::1',
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
const config = loadConfig(env);
|
|
237
|
-
expect(config.httpBindAddr).toBe('::1');
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
it('should parse numeric timeout', () => {
|
|
241
|
-
const env = {
|
|
242
|
-
HA_URL: 'http://homeassistant.10.0.0.19.nip.io:8123',
|
|
243
|
-
HA_TOKEN: 'test-token-12345',
|
|
244
|
-
HA_TIMEOUT: '45000',
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
const config = loadConfig(env);
|
|
248
|
-
expect(config.timeout).toBe(45000);
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
it('should support all log levels', () => {
|
|
252
|
-
const levels = ['debug', 'info', 'warn', 'error'] as const;
|
|
253
|
-
|
|
254
|
-
for (const level of levels) {
|
|
255
|
-
const env = {
|
|
256
|
-
HA_URL: 'http://homeassistant.10.0.0.19.nip.io:8123',
|
|
257
|
-
HA_TOKEN: 'test-token-12345',
|
|
258
|
-
MCP_SERVER_LOG_LEVEL: level,
|
|
259
|
-
};
|
|
260
|
-
|
|
261
|
-
const config = loadConfig(env);
|
|
262
|
-
expect(config.logLevel).toBe(level);
|
|
263
|
-
}
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
it('should support all log formats', () => {
|
|
267
|
-
const formats = ['plain', 'json', 'gcp-json'] as const;
|
|
268
|
-
|
|
269
|
-
for (const format of formats) {
|
|
270
|
-
const env = {
|
|
271
|
-
HA_URL: 'http://homeassistant.10.0.0.19.nip.io:8123',
|
|
272
|
-
HA_TOKEN: 'test-token-12345',
|
|
273
|
-
MCP_SERVER_LOG_FORMAT: format,
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
const config = loadConfig(env);
|
|
277
|
-
expect(config.logFormat).toBe(format);
|
|
278
|
-
}
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
it('should parse boolean strings correctly', () => {
|
|
283
|
-
const envTrue = {
|
|
284
|
-
HA_URL: 'http://homeassistant.10.0.0.19.nip.io:8123',
|
|
285
|
-
HA_TOKEN: 'test-token-12345',
|
|
286
|
-
HA_STRICT_SSL: 'true',
|
|
287
|
-
MCP_SERVER_USE_HTTP: 'true',
|
|
288
|
-
MCP_SERVER_STATEFUL: 'true',
|
|
289
|
-
};
|
|
290
|
-
|
|
291
|
-
const configTrue = loadConfig(envTrue);
|
|
292
|
-
expect(configTrue.strictSsl).toBe(true);
|
|
293
|
-
expect(configTrue.useHttp).toBe(true);
|
|
294
|
-
expect(configTrue.stateful).toBe(true);
|
|
295
|
-
|
|
296
|
-
const envFalse = {
|
|
297
|
-
HA_URL: 'http://homeassistant.10.0.0.19.nip.io:8123',
|
|
298
|
-
HA_TOKEN: 'test-token-12345',
|
|
299
|
-
HA_STRICT_SSL: 'false',
|
|
300
|
-
MCP_SERVER_USE_HTTP: 'false',
|
|
301
|
-
MCP_SERVER_STATEFUL: 'false',
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
const configFalse = loadConfig(envFalse);
|
|
305
|
-
expect(configFalse.strictSsl).toBe(false);
|
|
306
|
-
expect(configFalse.useHttp).toBe(false);
|
|
307
|
-
expect(configFalse.stateful).toBe(false);
|
|
308
|
-
});
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
describe('validateConfig', () => {
|
|
312
|
-
it('should validate valid configuration', () => {
|
|
313
|
-
const config: EnvironmentConfig = {
|
|
314
|
-
baseUrl: 'http://homeassistant.10.0.0.19.nip.io:8123',
|
|
315
|
-
token: 'test-token-12345',
|
|
316
|
-
strictSsl: false,
|
|
317
|
-
timeout: 30000,
|
|
318
|
-
aiProvider: 'ollama',
|
|
319
|
-
aiUrl: 'http://ollama.10.0.0.17.nip.io:11434',
|
|
320
|
-
aiModel: 'qwen3:14b',
|
|
321
|
-
aiTimeout: 60000,
|
|
322
|
-
logLevel: 'info',
|
|
323
|
-
logFormat: 'plain',
|
|
324
|
-
useHttp: false,
|
|
325
|
-
stateful: false,
|
|
326
|
-
|
|
327
|
-
httpEnableHealthcheck: true,
|
|
328
|
-
httpAllowCors: true,
|
|
329
|
-
sseEventsEnabled: true,
|
|
330
|
-
sseEventsPath: '/subscribe_events',
|
|
331
|
-
rateLimitEnabled: true,
|
|
332
|
-
rateLimitWindowMs: 60000,
|
|
333
|
-
rateLimitMaxRequests: 100,
|
|
334
|
-
authMethod: 'none',
|
|
335
|
-
};
|
|
336
|
-
|
|
337
|
-
expect(() => validateConfig(config)).not.toThrow();
|
|
338
|
-
});
|
|
339
|
-
|
|
340
|
-
it('should throw error for missing baseUrl', () => {
|
|
341
|
-
const config = {
|
|
342
|
-
token: 'test-token-12345',
|
|
343
|
-
} as EnvironmentConfig;
|
|
344
|
-
|
|
345
|
-
expect(() => validateConfig(config)).toThrow('Invalid configuration');
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
it('should throw error for missing token', () => {
|
|
349
|
-
const config = {
|
|
350
|
-
baseUrl: 'http://homeassistant.10.0.0.19.nip.io:8123',
|
|
351
|
-
} as EnvironmentConfig;
|
|
352
|
-
|
|
353
|
-
expect(() => validateConfig(config)).toThrow('Invalid configuration');
|
|
354
|
-
});
|
|
355
|
-
});
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
Feature: Automation Creation
|
|
2
|
-
As a Home Assistant user
|
|
3
|
-
I want to create automations via the MCP server
|
|
4
|
-
So that I can automate my smart home devices
|
|
5
|
-
|
|
6
|
-
Background:
|
|
7
|
-
Given a connected Home Assistant client
|
|
8
|
-
|
|
9
|
-
Scenario: Create a simple time-based automation
|
|
10
|
-
Given an automation config with alias "Morning Lights"
|
|
11
|
-
And a time trigger at "06:00:00"
|
|
12
|
-
And an action to turn on "light.bedroom"
|
|
13
|
-
When I create the automation
|
|
14
|
-
Then the automation should be created successfully
|
|
15
|
-
And the automation ID should be returned
|
|
16
|
-
|
|
17
|
-
Scenario: Create an automation with state trigger
|
|
18
|
-
Given an automation config with alias "Motion Alert"
|
|
19
|
-
And a state trigger for "binary_sensor.motion" changing to "on"
|
|
20
|
-
And an action to send notification "Motion detected!"
|
|
21
|
-
When I create the automation
|
|
22
|
-
Then the automation should be created successfully
|
|
23
|
-
|
|
24
|
-
Scenario: Reject automation without required fields
|
|
25
|
-
Given an automation config without alias
|
|
26
|
-
When I attempt to create the automation
|
|
27
|
-
Then it should fail with error "alias, trigger, and action are required"
|
|
28
|
-
|
|
29
|
-
Scenario: Create automation with multiple actions
|
|
30
|
-
Given an automation config with alias "Goodnight Routine"
|
|
31
|
-
And a time trigger at "23:00:00"
|
|
32
|
-
And an action to turn off "light.living_room"
|
|
33
|
-
And an action to turn off "light.kitchen"
|
|
34
|
-
And an action to set "climate.thermostat" to 18 degrees
|
|
35
|
-
When I create the automation
|
|
36
|
-
Then the automation should be created successfully
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
Feature: Automation Management
|
|
2
|
-
As a Home Assistant user
|
|
3
|
-
I want to manage my automations
|
|
4
|
-
So that I can control when and how my smart home responds to events
|
|
5
|
-
|
|
6
|
-
Scenario: List all automations
|
|
7
|
-
Given a Home Assistant with automations
|
|
8
|
-
When I list all automations
|
|
9
|
-
Then I should get all automation entities
|
|
10
|
-
And each automation should have id, alias, and state
|
|
11
|
-
|
|
12
|
-
Scenario: Get automation details
|
|
13
|
-
Given an automation "automation.morning_lights" exists
|
|
14
|
-
When I get the automation details
|
|
15
|
-
Then I should see the automation alias "Morning Lights"
|
|
16
|
-
And the state should be "on"
|
|
17
|
-
And the mode should be "single"
|
|
18
|
-
|
|
19
|
-
Scenario: Trigger an automation manually
|
|
20
|
-
Given an automation "automation.morning_lights" exists
|
|
21
|
-
When I trigger the automation
|
|
22
|
-
Then the automation.trigger service should be called
|
|
23
|
-
And the target should be "automation.morning_lights"
|
|
24
|
-
|
|
25
|
-
Scenario: Trigger automation with variables
|
|
26
|
-
Given an automation "automation.dynamic_scene" exists
|
|
27
|
-
When I trigger the automation with variables {"brightness": 100}
|
|
28
|
-
Then the automation.trigger service should be called
|
|
29
|
-
And the variables should be passed
|
|
30
|
-
|
|
31
|
-
Scenario: Enable a disabled automation
|
|
32
|
-
Given a disabled automation "automation.night_mode" exists
|
|
33
|
-
When I enable the automation
|
|
34
|
-
Then the automation.turn_on service should be called
|
|
35
|
-
|
|
36
|
-
Scenario: Disable an enabled automation
|
|
37
|
-
Given an enabled automation "automation.morning_lights" exists
|
|
38
|
-
When I disable the automation
|
|
39
|
-
Then the automation.turn_off service should be called
|
|
40
|
-
|
|
41
|
-
Scenario: Toggle automation state
|
|
42
|
-
Given an automation "automation.morning_lights" exists
|
|
43
|
-
When I toggle the automation
|
|
44
|
-
Then the automation.toggle service should be called
|
|
45
|
-
|
|
46
|
-
Scenario: Reload automations from configuration
|
|
47
|
-
Given a Home Assistant with automations
|
|
48
|
-
When I reload automations
|
|
49
|
-
Then the automation.reload service should be called
|
|
50
|
-
|
|
51
|
-
Scenario: Delete an automation
|
|
52
|
-
Given an automation with ID "1234567890" exists
|
|
53
|
-
When I delete the automation
|
|
54
|
-
Then a DELETE request should be made to the config API
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
Feature: Calendar Operations
|
|
2
|
-
As a Home Assistant user
|
|
3
|
-
I want to access my calendar events
|
|
4
|
-
So that I can see upcoming appointments and reminders
|
|
5
|
-
|
|
6
|
-
Scenario: List all calendars
|
|
7
|
-
Given a Home Assistant with calendar entities
|
|
8
|
-
When I list all calendars
|
|
9
|
-
Then I should see all calendar entities
|
|
10
|
-
And each calendar should have entity_id, name, and state
|
|
11
|
-
|
|
12
|
-
Scenario: Get events from a specific calendar
|
|
13
|
-
Given a calendar "calendar.family" with events
|
|
14
|
-
When I get events from "calendar.family"
|
|
15
|
-
Then I should receive calendar events
|
|
16
|
-
And each event should have summary and start date
|
|
17
|
-
|
|
18
|
-
Scenario: Get events with custom date range
|
|
19
|
-
Given a calendar "calendar.work" with events
|
|
20
|
-
When I get events from January 1 to January 31
|
|
21
|
-
Then the events should be within the date range
|
|
22
|
-
|
|
23
|
-
Scenario: Get events using days parameter
|
|
24
|
-
Given a calendar "calendar.reminders" with events
|
|
25
|
-
When I get events for the next 7 days
|
|
26
|
-
Then the end date should be 7 days from now
|
|
27
|
-
|
|
28
|
-
Scenario: Get events from all calendars
|
|
29
|
-
Given multiple calendars with events
|
|
30
|
-
When I get events without specifying a calendar
|
|
31
|
-
Then I should receive events from all calendars
|
|
32
|
-
And results should be grouped by calendar
|
|
33
|
-
|
|
34
|
-
Scenario: Get events from calendar with no events
|
|
35
|
-
Given a calendar "calendar.empty" with no events
|
|
36
|
-
When I get events from "calendar.empty"
|
|
37
|
-
Then I should receive an empty events list
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
Feature: Server Configuration
|
|
2
|
-
As an MCP server administrator
|
|
3
|
-
I want to configure the server with my Home Assistant details
|
|
4
|
-
So that I can connect to my smart home
|
|
5
|
-
|
|
6
|
-
Scenario: Load valid configuration
|
|
7
|
-
Given environment variables with HA_URL and HA_TOKEN
|
|
8
|
-
When I load the configuration
|
|
9
|
-
Then the configuration should be valid
|
|
10
|
-
And baseUrl should be set correctly
|
|
11
|
-
And token should be set correctly
|
|
12
|
-
|
|
13
|
-
Scenario: Apply default values for optional settings
|
|
14
|
-
Given only required environment variables
|
|
15
|
-
When I load the configuration
|
|
16
|
-
Then strictSsl should default to true
|
|
17
|
-
And timeout should default to 30000
|
|
18
|
-
And logLevel should default to "info"
|
|
19
|
-
And logFormat should default to "plain"
|
|
20
|
-
|
|
21
|
-
Scenario: Remove trailing slash from URL
|
|
22
|
-
Given HA_URL with trailing slash "http://ha.local:8123/"
|
|
23
|
-
When I load the configuration
|
|
24
|
-
Then baseUrl should not have a trailing slash
|
|
25
|
-
|
|
26
|
-
Scenario: Allow missing HA_URL for Omada-only mode
|
|
27
|
-
Given environment variables without HA_URL
|
|
28
|
-
When I attempt to load the configuration
|
|
29
|
-
Then it should load successfully with baseUrl undefined
|
|
30
|
-
|
|
31
|
-
Scenario: Allow missing HA_TOKEN for Omada-only mode
|
|
32
|
-
Given environment variables without HA_TOKEN
|
|
33
|
-
When I attempt to load the configuration
|
|
34
|
-
Then it should load successfully with token undefined
|
|
35
|
-
|
|
36
|
-
Scenario: Reject invalid URL format
|
|
37
|
-
Given HA_URL with invalid format "not-a-url"
|
|
38
|
-
When I attempt to load the configuration
|
|
39
|
-
Then it should throw an error about invalid configuration
|
|
40
|
-
|
|
41
|
-
Scenario: Parse HTTP server configuration
|
|
42
|
-
Given HTTP mode is enabled
|
|
43
|
-
When I load the configuration
|
|
44
|
-
Then useHttp should be true
|
|
45
|
-
And httpPort should be set
|
|
46
|
-
|
|
47
|
-
Scenario: Validate bind address format
|
|
48
|
-
Given an invalid bind address "invalid-ip"
|
|
49
|
-
When I attempt to load the configuration
|
|
50
|
-
Then it should throw an error about invalid bind address
|
|
51
|
-
|
|
52
|
-
Scenario: Accept valid IPv4 bind address
|
|
53
|
-
Given a valid IPv4 bind address "192.168.1.100"
|
|
54
|
-
When I load the configuration
|
|
55
|
-
Then httpBindAddr should be "192.168.1.100"
|
|
56
|
-
|
|
57
|
-
Scenario: Accept valid IPv6 bind address
|
|
58
|
-
Given a valid IPv6 bind address "::1"
|
|
59
|
-
When I load the configuration
|
|
60
|
-
Then httpBindAddr should be "::1"
|
|
61
|
-
|
|
62
|
-
Scenario: Handle wildcard in allowed origins
|
|
63
|
-
Given allowed origins set to "*"
|
|
64
|
-
When I load the configuration
|
|
65
|
-
Then httpAllowedOrigins should be an empty array
|
|
66
|
-
|
|
67
|
-
Scenario: Parse comma-separated allowed origins
|
|
68
|
-
Given allowed origins "http://localhost:3000,http://192.168.1.100"
|
|
69
|
-
When I load the configuration
|
|
70
|
-
Then httpAllowedOrigins should contain both origins
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
Feature: Device Control
|
|
2
|
-
As a Home Assistant user
|
|
3
|
-
I want to control my smart home devices through the MCP server
|
|
4
|
-
So that I can manage my home automation
|
|
5
|
-
|
|
6
|
-
# Light Control
|
|
7
|
-
Scenario: Turn on a light
|
|
8
|
-
Given a light entity "light.living_room" that is "off"
|
|
9
|
-
When I turn on the light
|
|
10
|
-
Then the light service "turn_on" should be called
|
|
11
|
-
And the target should be "light.living_room"
|
|
12
|
-
|
|
13
|
-
Scenario: Turn on a light with brightness
|
|
14
|
-
Given a light entity "light.bedroom"
|
|
15
|
-
When I turn on the light with brightness 75%
|
|
16
|
-
Then the light service "turn_on" should be called
|
|
17
|
-
And the service data should include brightness_pct 75
|
|
18
|
-
|
|
19
|
-
Scenario: Set light color temperature
|
|
20
|
-
Given a light entity "light.kitchen"
|
|
21
|
-
When I set the color temperature to 4000K
|
|
22
|
-
Then the light service "turn_on" should be called
|
|
23
|
-
And the service data should include color_temp_kelvin 4000
|
|
24
|
-
|
|
25
|
-
Scenario: Set light RGB color
|
|
26
|
-
Given a light entity "light.office"
|
|
27
|
-
When I set the RGB color to red (255, 0, 0)
|
|
28
|
-
Then the light service "turn_on" should be called
|
|
29
|
-
And the service data should include rgb_color [255, 0, 0]
|
|
30
|
-
|
|
31
|
-
# Climate Control
|
|
32
|
-
Scenario: Set thermostat temperature
|
|
33
|
-
Given a climate entity "climate.living_room"
|
|
34
|
-
When I set the temperature to 22 degrees
|
|
35
|
-
Then the climate service "set_temperature" should be called
|
|
36
|
-
And the service data should include temperature 22
|
|
37
|
-
|
|
38
|
-
Scenario: Set HVAC mode to heat
|
|
39
|
-
Given a climate entity "climate.bedroom"
|
|
40
|
-
When I set the HVAC mode to "heat"
|
|
41
|
-
Then the climate service "set_hvac_mode" should be called
|
|
42
|
-
And the service data should include hvac_mode "heat"
|
|
43
|
-
|
|
44
|
-
Scenario: Set climate preset mode
|
|
45
|
-
Given a climate entity "climate.office"
|
|
46
|
-
When I set the preset mode to "eco"
|
|
47
|
-
Then the climate service "set_preset_mode" should be called
|
|
48
|
-
And the service data should include preset_mode "eco"
|
|
49
|
-
|
|
50
|
-
# Media Player Control
|
|
51
|
-
Scenario: Play media player
|
|
52
|
-
Given a media player entity "media_player.living_room"
|
|
53
|
-
When I play the media player
|
|
54
|
-
Then the media_player service "media_play" should be called
|
|
55
|
-
|
|
56
|
-
Scenario: Pause media player
|
|
57
|
-
Given a media player entity "media_player.bedroom"
|
|
58
|
-
When I pause the media player
|
|
59
|
-
Then the media_player service "media_pause" should be called
|
|
60
|
-
|
|
61
|
-
Scenario: Set media player volume
|
|
62
|
-
Given a media player entity "media_player.kitchen"
|
|
63
|
-
When I set the volume to 50%
|
|
64
|
-
Then the media_player service "volume_set" should be called
|
|
65
|
-
And the service data should include volume_level 0.5
|
|
66
|
-
|
|
67
|
-
# Cover Control
|
|
68
|
-
Scenario: Open a cover
|
|
69
|
-
Given a cover entity "cover.garage_door"
|
|
70
|
-
When I open the cover
|
|
71
|
-
Then the cover service "open_cover" should be called
|
|
72
|
-
|
|
73
|
-
Scenario: Close a cover
|
|
74
|
-
Given a cover entity "cover.blinds"
|
|
75
|
-
When I close the cover
|
|
76
|
-
Then the cover service "close_cover" should be called
|
|
77
|
-
|
|
78
|
-
Scenario: Set cover position
|
|
79
|
-
Given a cover entity "cover.living_room_blinds"
|
|
80
|
-
When I set the cover position to 50%
|
|
81
|
-
Then the cover service "set_cover_position" should be called
|
|
82
|
-
And the service data should include position 50
|
|
83
|
-
|
|
84
|
-
# Fan Control
|
|
85
|
-
Scenario: Turn on a fan
|
|
86
|
-
Given a fan entity "fan.bedroom"
|
|
87
|
-
When I turn on the fan
|
|
88
|
-
Then the fan service "turn_on" should be called
|
|
89
|
-
|
|
90
|
-
Scenario: Set fan speed
|
|
91
|
-
Given a fan entity "fan.living_room"
|
|
92
|
-
When I set the fan speed to 75%
|
|
93
|
-
Then the fan service "set_percentage" should be called
|
|
94
|
-
And the service data should include percentage 75
|
|
95
|
-
|
|
96
|
-
Scenario: Toggle fan oscillation
|
|
97
|
-
Given a fan entity "fan.office"
|
|
98
|
-
When I enable oscillation
|
|
99
|
-
Then the fan service "oscillate" should be called
|
|
100
|
-
And the service data should include oscillating true
|