Skip to content

Commit

Permalink
api: support invitation management
Browse files Browse the repository at this point in the history
  • Loading branch information
abn committed Nov 1, 2024
1 parent 5333787 commit c13b028
Show file tree
Hide file tree
Showing 4 changed files with 243 additions and 0 deletions.
57 changes: 57 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
HomeIncidentDetection,
HorizontalSwing,
Installation,
Invitation,
IQUnit,
Me,
MobileDevice,
Expand Down Expand Up @@ -332,6 +333,62 @@ export class Tado {
return this.apiCall(`/api/v2/homes/${home_id}/installations`);
}

/**
* Fetches the list of invitations for a specified home.
*
* @param home_id - The ID of the home for which to retrieve invitations.
* @returns A promise that resolves to an array of Invitation objects.
*/
getInvitations(home_id: number): Promise<Invitation[]> {
return this.apiCall(`/api/v2/homes/${home_id}/invitations`);
}

/**
* Retrieves an invitation based on the provided home ID and token.
*
* @param home_id - The ID of the home for which the invitation is to be retrieved.
* @param token - The unique token (invitation id) associated with the invitation.
* @returns A promise that resolves to the invitation details.
*/
getInvitation(home_id: number, token: string): Promise<Invitation> {
return this.apiCall(`/api/v2/homes/${home_id}/invitations/${token}`);
}

/**
* Creates an invitation for a specified home.
*
* @param home_id - The unique identifier of the home to which the invitation will be sent.
* @param email - The email address of the invitee.
* @returns A promise that resolves to an Invitation object.
*/
createInvitation(home_id: number, email: string): Promise<Invitation> {
return this.apiCall(`/api/v2/homes/${home_id}/invitations`, "POST", {
email: email,
});
}

/**
* Resends an invitation to a specific home.
*
* @param home_id - The ID of the home for which the invitation is to be resent.
* @param token - The token representing the invitation to be resent.
* @returns A promise that resolves once the invitation has been resent.
*/
resendInvitation(home_id: number, token: string): Promise<void> {
return this.apiCall(`/api/v2/homes/${home_id}/invitations/${token}/resend`, "POST", {});
}

/**
* Deletes an invitation associated with a home.
*
* @param home_id - The unique identifier of the home.
* @param token - The token associated with the invitation.
* @returns A promise that resolves when the invitation is successfully deleted.
*/
deleteInvitation(home_id: number, token: string): Promise<void> {
return this.apiCall(`/api/v2/homes/${home_id}/invitations/${token}`, "DELETE");
}

/**
* Fetches the list of users associated with a given home.
*
Expand Down
15 changes: 15 additions & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -932,3 +932,18 @@ export type BoilerSystemInformation = {
};
manufacturers: Manufacturer[];
};

export type Inviter = Omit<User, "homes" | "mobileDevices"> & {
enabled: boolean;
homeId: number;
type: string & "WEB_USER";
};

export type Invitation = {
token: string;
email: string;
firstSent: string; // ISO 8601 format date-time
lastSent: string; // ISO 8601 format date-time
inviter: Inviter;
home: Home;
};
96 changes: 96 additions & 0 deletions test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import heating_system_response from "./response.heatingSystem.json";
import home_response from "./response.home.json";
import incident_detection_response from "./response.incidentDetection.json";
import installations_response from "./response.installations.json";
import invitations_response from "./response.invitations.json";
import me_response from "./response.me.json";
import mobileDevice_response from "./response.mobileDevice.json";
import mobileDevice_settings_response from "./response.mobileDevice.settings.json";
Expand Down Expand Up @@ -334,6 +335,101 @@ describe("High-level API tests", () => {
.catch(done);
});

it("Should get the invitations", (done) => {
nock("https://my.tado.com")
.get("/api/v2/homes/1907/invitations")
.reply(200, invitations_response);

tado
.getInvitations(1907)
.then((response) => {
expect(typeof response).to.equal("object");
expect(response.length).to.equal(1);
expect(response[0].email).to.equal("[email protected]");

done();
})
.catch(done);
});

it("Should get a single invitation", (done) => {
const invitation_token = "12345";
const response_body = invitations_response[0];
response_body.token = invitation_token;

nock("https://my.tado.com")
.get(`/api/v2/homes/1907/invitations/${invitation_token}`)
.reply(200, response_body);

tado
.getInvitation(1907, invitation_token)
.then((response) => {
expect(typeof response).to.equal("object");
expect(response.token).to.equal(invitation_token);

done();
})
.catch(done);
});

it("Should create an invitation", (done) => {
const invitation = { email: "[email protected]" };

nock("https://my.tado.com")
.post("/api/v2/homes/1907/invitations", (body) => {
expect(body).to.deep.equal(invitation);
return true;
})
.reply(200, invitations_response[0]);

tado
.createInvitation(1907, invitation.email)
.then((response) => {
expect(typeof response).to.equal("object");
expect(response.email).to.equal(invitation.email);

done();
})
.catch(done);
});

it("Should delete an invitation", (done) => {
const invitation_token = "12345";

nock("https://my.tado.com")
.delete(`/api/v2/homes/1907/invitations/${invitation_token}`)
.reply(204);

tado
.deleteInvitation(1907, invitation_token)
.then((response) => {
expect(response).to.equal("");

done();
})
.catch(done);
});

it("Should resend an invitation", (done) => {
const invitation_token = "12345";

nock("https://my.tado.com")
.post(`/api/v2/homes/1907/invitations/${invitation_token}/resend`, (body) => {
expect(body).to.deep.equal({});
return true;
})
.reply(204);

tado
.resendInvitation(1907, invitation_token)
.then((response) => {
expect(response).to.equal("");

done();
})
.catch(done);
});

it("Should get the users", (done) => {
nock("https://my.tado.com").get("/api/v2/homes/1907/users").reply(200, users_response);

Expand Down
75 changes: 75 additions & 0 deletions test/response.invitations.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
[
{
"token": "c111de1da1d11e111e1b81b02a1a61d5",
"email": "[email protected]",
"firstSent": "2024-11-01T19:50:05.208Z",
"lastSent": "2024-11-01T19:50:05.208Z",
"inviter": {
"name": "John Doe",
"email": "[email protected]",
"username": "john_doe",
"id": "523acf000089",
"locale": "en",
"enabled": true,
"homeId": 1907,
"type": "WEB_USER"
},
"home": {
"id": 1907,
"name": "Dummy Home",
"dateTimeZone": "Europe/Amsterdam",
"dateCreated": "2021-11-15T12:27:24.825Z",
"temperatureUnit": "CELSIUS",
"partner": null,
"simpleSmartScheduleEnabled": true,
"awayRadiusInMeters": 500,
"installationCompleted": true,
"incidentDetection": {
"supported": true,
"enabled": true
},
"generation": "PRE_LINE_X",
"zonesCount": 8,
"language": "en",
"skills": ["AUTO_ASSIST"],
"christmasModeEnabled": true,
"showAutoAssistReminders": true,
"contactDetails": {
"name": "Tado User",
"email": "[email protected]",
"phone": "+3112115194351"
},
"address": {
"addressLine1": "Museumplein 6",
"addressLine2": null,
"zipCode": "1071",
"city": "Amsterdam",
"state": null,
"country": "NLD"
},
"geolocation": {
"latitude": 51.2993,
"longitude": 9.491
},
"consentGrantSkippable": true,
"enabledFeatures": [
"DARK_MODE",
"EIQ_SETTINGS_AS_WEBVIEW",
"HIDE_BOILER_REPAIR_SERVICE",
"HOME_DETAILS_AS_WEBVIEW",
"MORE_AS_WEBVIEW",
"OFFLINE_SCHEDULE_ENABLED",
"OWD_SETTINGS_AS_WEBVIEW",
"PEOPLE_AS_WEBVIEW",
"SETTINGS_OVERVIEW_AS_WEBVIEW"
],
"isAirComfortEligible": true,
"isBalanceAcEligible": false,
"isEnergyIqEligible": true,
"isHeatSourceInstalled": false,
"isHeatPumpInstalled": false,
"isBalanceHpEligible": false,
"supportsFlowTemperatureOptimization": false
}
}
]

0 comments on commit c13b028

Please sign in to comment.