Skip to content

Commit

Permalink
Zigbee2mqtt: New setup wizard & connection to external MQTT brokers (#…
Browse files Browse the repository at this point in the history
…1872)

Co-authored-by: atrovato <[email protected]>
  • Loading branch information
Pierre-Gilles and atrovato authored May 3, 2024
1 parent 6f0bc73 commit c28b59e
Show file tree
Hide file tree
Showing 77 changed files with 2,996 additions and 1,410 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
describe('Zigbee2Mqtt setup wizard local mode from scratch', () => {
before(() => {
cy.login();

const serverUrl = Cypress.env('serverUrl');
cy.intercept(
{
method: 'GET',
url: `${serverUrl}/api/v1/service/zigbee2mqtt/status`
},
{
fixture: 'integration/routes/integration/zigbee2mqtt/status_ready_to_setup.json'
}
);
cy.intercept(
{
method: 'GET',
url: `${serverUrl}/api/v1/service/zigbee2mqtt/setup`
},
{
body: {}
}
);
cy.visit('/dashboard/integration/device/zigbee2mqtt/setup');
});

it('Check list', () => {
cy.get('[data-cy=z2m-setup-wizard]')
.should('exist')
.within(() => {
cy.get('button').should('be.length', 2);
});

cy.get('[data-cy=z2m-setup-local-panel]')
.should('exist')
.within(() => {
cy.get('button').should('not.be.disabled');
cy.get('.requirement').should('be.length', 3);
});

cy.get('[data-cy=z2m-toggle-status]').should('exist');
cy.get('[data-cy=z2m-running-status]').should('exist');
});

it('Select local mode', () => {
const serverUrl = Cypress.env('serverUrl');
cy.intercept(
{
method: 'GET',
url: `${serverUrl}/api/v1/service/usb/port`
},
{
fixture: 'integration/routes/integration/usb/get_available_usb_ports.json'
}
).as('usbPorts');

cy.get('[data-cy=z2m-setup-local-panel]').within(() => {
cy.get('button').click();
});
cy.wait('@usbPorts');

// Setup panel should be hidden
cy.get('[data-cy=z2m-setup-local-panel]').should('not.exist');
// Save panel should be hidden
cy.get('[data-cy=z2m-setup-save]').should('exist');
cy.get('[data-cy=z2m-setup-reset]').should('exist');

// Save button is disabled
cy.get('[data-cy=z2m-setup-save]').should('be.disabled');

// Start typing on USB port and abort
cy.get('[data-cy=z2m-setup-local-usb-field]')
.children()
.type('invalid value{esc}');
// Save button is still disabled
cy.get('[data-cy=z2m-setup-save]').should('be.disabled');

// Start typing on USB port and confirm
cy.get('[data-cy=z2m-setup-local-usb-field]')
.children()
.click()
.type('{downArrow}{enter}');

// Save button is still enabled
cy.get('[data-cy=z2m-setup-save]').should('not.be.disabled');

// Select a dongle name
cy.get('[data-cy=z2m-setup-local-dongle-field]')
.children()
.click()
.type('{downArrow}{enter}');
});

it('Check confirm configuration', () => {
cy.get('[data-cy=z2m-setup-save]')
.should('exist')
.should('not.be.disabled');
cy.get('[data-cy=z2m-setup-reset]')
.should('exist')
.should('not.be.disabled');
});

it('Save configuration with error', () => {
// Check no error panel
cy.get('[data-cy=z2m-setup-save-error]').should('not.exist');

// Re-fill form
cy.get('[data-cy=z2m-setup-local-usb-field]')
.children()
.click()
.type('{downArrow}{enter}');

// Enter TCP port
cy.get('[data-cy=z2m-setup-local-tcp-field]').type('12345');

const serverUrl = Cypress.env('serverUrl');
cy.intercept(
{
method: 'POST',
url: `${serverUrl}/api/v1/service/zigbee2mqtt/setup`
},
{
statusCode: 400
}
).as('setup');

cy.get('[data-cy=z2m-setup-save]').click();

cy.wait('@setup')
.its('request.body')
.should('deep.eq', {
ZIGBEE2MQTT_DRIVER_PATH: '/dev/ttyUSB0',
ZIGBEE_DONGLE_NAME: "CircuitSetup's CC2652P2 USB Coordinator",
Z2M_TCP_PORT: '12345',
Z2M_MQTT_MODE: 'local'
});

// Check error panel
cy.get('[data-cy=z2m-setup-save-error]').should('exist');
});

it('Save configuration with success', () => {
// Check error panel
cy.get('[data-cy=z2m-setup-save-error]').should('exist');

// Select a dongle name
cy.get('[data-cy=z2m-setup-local-dongle-field]')
.children()
.click()
.type('{downArrow}{enter}');

// Enter TCP port
cy.get('[data-cy=z2m-setup-local-tcp-field]').clear();

const serverUrl = Cypress.env('serverUrl');
cy.intercept(
{
method: 'POST',
url: `${serverUrl}/api/v1/service/zigbee2mqtt/setup`
},
{
statusCode: 200,
body: {
ZIGBEE2MQTT_DRIVER_PATH: '/dev/ttyUSB0',
ZIGBEE_DONGLE_NAME: "CircuitSetup's CC2652P2 USB Coordinator",
Z2M_TCP_PORT: '12000'
}
}
).as('setup');

cy.get('[data-cy=z2m-setup-save]').click();

cy.wait('@setup')
.its('request.body')
.should('deep.eq', {
ZIGBEE2MQTT_DRIVER_PATH: '/dev/ttyUSB0',
ZIGBEE_DONGLE_NAME: "CircuitSetup's CC2652P2 USB Coordinator",
Z2M_TCP_PORT: null,
Z2M_MQTT_MODE: 'local'
});

// Check error panel
cy.get('[data-cy=z2m-setup-save-error]').should('not.exist');

// Check summary
cy.get('[data-cy=z2m-setup-local-usb-summary]').should('have.text', '/dev/ttyUSB0');
cy.get('[data-cy=z2m-setup-local-dongle-summary]').should('have.text', "CircuitSetup's CC2652P2 USB Coordinator");
cy.get('[data-cy=z2m-setup-local-tcp-summary]').should('have.text', '12000');

cy.sendWebSocket({
type: 'zigbee2mqtt.status-change',
payload: {
usbConfigured: true,
mqttExist: true,
mqttRunning: true,
zigbee2mqttExist: true,
zigbee2mqttRunning: true,
gladysConnected: true,
zigbee2mqttConnected: true,
z2mEnabled: true,
dockerBased: true,
networkModeValid: true
}
});
});

it('Reset configuration', () => {
cy.get('[data-cy=z2m-setup-save]').should('not.exist');
cy.get('[data-cy=z2m-setup-local-summary]')
.should('exist')
.within(() => {
cy.get('button')
.contains('integration.zigbee2mqtt.setup.changeButtonLabel')
.click();
});
cy.get('[data-cy=z2m-setup-reset]').click();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
describe('Zigbee2Mqtt setup wizard remote mode from scratch', () => {
before(() => {
cy.login();

const serverUrl = Cypress.env('serverUrl');
cy.intercept(
{
method: 'GET',
url: `${serverUrl}/api/v1/service/zigbee2mqtt/status`
},
{
fixture: 'integration/routes/integration/zigbee2mqtt/status_not_ready_to_setup.json'
}
);
cy.intercept(
{
method: 'GET',
url: `${serverUrl}/api/v1/service/zigbee2mqtt/setup`
},
{
body: {}
}
);
cy.visit('/dashboard/integration/device/zigbee2mqtt/setup');
});

it('Check list', () => {
cy.get('[data-cy=z2m-setup-wizard]')
.should('exist')
.within(() => {
cy.get('button').should('be.length', 2);
});

cy.get('[data-cy=z2m-setup-remote-panel]')
.should('exist')
.within(() => {
cy.get('button').should('not.be.disabled');
cy.get('.requirement').should('be.length', 2);
});

cy.get('[data-cy=z2m-toggle-status]').should('exist');
cy.get('[data-cy=z2m-running-status]').should('exist');
});

it('Select remote mode', () => {
cy.get('[data-cy=z2m-setup-remote-panel]').within(() => {
cy.get('button').click();
});
});

it('Save configuration with error', () => {
// Check no error panel
cy.get('[data-cy=z2m-setup-save-error]').should('not.exist');

const serverUrl = Cypress.env('serverUrl');
cy.intercept(
{
method: 'POST',
url: `${serverUrl}/api/v1/service/zigbee2mqtt/setup`
},
{
statusCode: 400
}
).as('setup');

cy.get('[data-cy=z2m-setup-save]').click();

cy.wait('@setup')
.its('request.body')
.should('deep.eq', {
Z2M_MQTT_MODE: 'external'
});

// Check error panel
cy.get('[data-cy=z2m-setup-save-error]').should('exist');
});

it('Save configuration with success', () => {
// Check error panel
cy.get('[data-cy=z2m-setup-save-error]').should('exist');

cy.get('[data-cy=z2m-setup-remote-broker-url-field]').type('mqtt://localhost');
cy.get('[data-cy=z2m-setup-remote-broker-username-field]').type('admin');
cy.get('[data-cy=z2m-setup-remote-broker-password-field]').type('test');

const serverUrl = Cypress.env('serverUrl');
cy.intercept(
{
method: 'POST',
url: `${serverUrl}/api/v1/service/zigbee2mqtt/setup`
},
{
statusCode: 200,
body: {
Z2M_MQTT_MODE: 'external',
Z2M_MQTT_URL: 'mqtt://localhost',
GLADYS_MQTT_USERNAME: 'admin',
GLADYS_MQTT_PASSWORD: 'test'
}
}
).as('setup');

cy.get('[data-cy=z2m-setup-save]').click();

cy.wait('@setup')
.its('request.body')
.should('deep.eq', {
Z2M_MQTT_MODE: 'external',
Z2M_MQTT_URL: 'mqtt://localhost',
GLADYS_MQTT_USERNAME: 'admin',
GLADYS_MQTT_PASSWORD: 'test'
});

// Check error panel
cy.get('[data-cy=z2m-setup-save-error]').should('not.exist');

// Check summary
cy.get('[data-cy=z2m-setup-remote-mqtt-mode-summary]').i18n(
'integration.zigbee2mqtt.setup.modes.remote.external.modeLabel'
);

cy.sendWebSocket({
type: 'zigbee2mqtt.status-change',
payload: {
usbConfigured: false,
mqttExist: true,
mqttRunning: true,
zigbee2mqttExist: false,
zigbee2mqttRunning: false,
gladysConnected: true,
zigbee2mqttConnected: false,
z2mEnabled: true,
dockerBased: false,
networkModeValid: false
}
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"comPath": "/dev/ttyUSB0",
"comVID": "0658",
"comName": "0200"
},
{
"comPath": "/dev/ttyUSB1",
"comVID": "0478",
"comName": "0910"
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"usbConfigured": false,
"mqttExist": false,
"mqttRunning": false,
"zigbee2mqttExist": false,
"zigbee2mqttRunning": false,
"gladysConnected": false,
"zigbee2mqttConnected": false,
"z2mEnabled": false,
"dockerBased": false,
"networkModeValid": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"usbConfigured": false,
"mqttExist": false,
"mqttRunning": false,
"zigbee2mqttExist": false,
"zigbee2mqttRunning": false,
"gladysConnected": false,
"zigbee2mqttConnected": false,
"z2mEnabled": false,
"dockerBased": true,
"networkModeValid": true
}
Loading

0 comments on commit c28b59e

Please sign in to comment.