diff --git a/package-lock.json b/package-lock.json index cd8d0d5e4..732e07358 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1706,6 +1706,7 @@ "version": "0.2.5", "resolved": "https://registry.npmjs.org/@viamrobotics/rpc/-/rpc-0.2.5.tgz", "integrity": "sha512-kvMffJhMQGAiPc5fA7wRZaEeYw2MDtBavkv0GllBNgKaGaK/JhIUMJrZsIl1oGLP15AMiv/MLUPmQ0yWttc5eA==", + "license": "Apache-2.0", "dependencies": { "@improbable-eng/grpc-web": "^0.13.0", "google-protobuf": "^3.14.0" diff --git a/src/app/app-client.test.ts b/src/app/app-client.spec.ts similarity index 52% rename from src/app/app-client.test.ts rename to src/app/app-client.spec.ts index d987f6273..a8a10eb1d 100644 --- a/src/app/app-client.test.ts +++ b/src/app/app-client.spec.ts @@ -16,18 +16,20 @@ import { AppClient, createAuth } from './app-client'; import { Timestamp } from 'google-protobuf/google/protobuf/timestamp_pb'; import { LogEntry } from '../gen/common/v1/common_pb'; import { EventDispatcher } from '../events'; -import type { ResponseStream } from '../main'; +import type { ResponseStream, ServiceError } from '../main'; +import { Message } from 'google-protobuf'; class TestResponseStream extends EventDispatcher { - private stream: ResponseStream; + private stream: ResponseStream; - constructor(stream: ResponseStream) { + constructor(stream: ResponseStream) { super(); this.stream = stream; } override on( type: string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any handler: (message: any) => void ): ResponseStream { super.on(type, handler); @@ -165,13 +167,19 @@ describe('AppClient tests', () => { describe('getUserIDByEmail tests', () => { beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'getUserIDByEmail') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.GetUserIDByEmailRequest, _md, cb) => { - const response = new pb.GetUserIDByEmailResponse(); - response.setUserId('id'); - cb(null, response); - }); + AppServiceClient.prototype.getUserIDByEmail = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.GetUserIDByEmailRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.GetUserIDByEmailResponse(); + response.setUserId('id'); + cb(null, response); + } + ); }); it('getUserIDByEmail', async () => { @@ -182,17 +190,19 @@ describe('AppClient tests', () => { describe('createOrganization tests', () => { beforeEach(() => { - vi.spyOn( - AppServiceClient.prototype, - 'createOrganization' - ).mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.CreateOrganizationRequest, _md, cb) => { - const response = new pb.CreateOrganizationResponse(); - response.setOrganization(org); - cb(null, response); - } - ); + AppServiceClient.prototype.createOrganization = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.CreateOrganizationRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.CreateOrganizationResponse(); + response.setOrganization(org); + cb(null, response); + } + ); }); it('createOrganization', async () => { @@ -204,17 +214,19 @@ describe('AppClient tests', () => { describe('listOrganizations tests', () => { const organizations = [org]; beforeEach(() => { - vi.spyOn( - AppServiceClient.prototype, - 'listOrganizations' - ).mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.ListOrganizationsRequest, _md, cb) => { - const response = new pb.ListOrganizationsResponse(); - response.setOrganizationsList(organizations); - cb(null, response); - } - ); + AppServiceClient.prototype.listOrganizations = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.ListOrganizationsRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.ListOrganizationsResponse(); + response.setOrganizationsList(organizations); + cb(null, response); + } + ); }); it('listOrganizations', async () => { @@ -230,18 +242,20 @@ describe('AppClient tests', () => { const orgIdentities = [orgIdentity]; beforeEach(() => { - vi.spyOn( - AppServiceClient.prototype, - 'getOrganizationsWithAccessToLocation' - ).mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.GetOrganizationsWithAccessToLocationRequest, _md, cb) => { - const response = - new pb.GetOrganizationsWithAccessToLocationResponse(); - response.setOrganizationIdentitiesList(orgIdentities); - cb(null, response); - } - ); + AppServiceClient.prototype.getOrganizationsWithAccessToLocation = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.GetOrganizationsWithAccessToLocationRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = + new pb.GetOrganizationsWithAccessToLocationResponse(); + response.setOrganizationIdentitiesList(orgIdentities); + cb(null, response); + } + ); }); it('getOrganizationsWithAccessToLocation', async () => { @@ -257,17 +271,19 @@ describe('AppClient tests', () => { orgDetail.setOrgName('name'); const orgDetails = [orgDetail]; beforeEach(() => { - vi.spyOn( - AppServiceClient.prototype, - 'listOrganizationsByUser' - ).mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.ListOrganizationsByUserRequest, _md, cb) => { - const response = new pb.ListOrganizationsByUserResponse(); - response.setOrgsList(orgDetails); - cb(null, response); - } - ); + AppServiceClient.prototype.listOrganizationsByUser = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.ListOrganizationsByUserRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.ListOrganizationsByUserResponse(); + response.setOrgsList(orgDetails); + cb(null, response); + } + ); }); it('listOrganizationsByUser', async () => { @@ -278,35 +294,43 @@ describe('AppClient tests', () => { describe('getOrganization tests', () => { beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'getOrganization') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.GetOrganizationRequest, _md, cb) => { - const response = new pb.GetOrganizationResponse(); - response.setOrganization(org); - cb(null, response); - }); + AppServiceClient.prototype.getOrganization = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.GetOrganizationRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.GetOrganizationResponse(); + response.setOrganization(org); + cb(null, response); + } + ); }); it('getOrganization', async () => { const response = await subject().getOrganization('orgId'); - expect(response.organization).toEqual(org.toObject()); + expect(response).toEqual(org.toObject()); }); }); describe('getOrganizationNamespaceAvailability tests', () => { beforeEach(() => { - vi.spyOn( - AppServiceClient.prototype, - 'getOrganizationNamespaceAvailability' - ).mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (req: pb.GetOrganizationNamespaceAvailabilityRequest, _md, cb) => { - const response = - new pb.GetOrganizationNamespaceAvailabilityResponse(); - response.setAvailable(true); - cb(null, response); - } - ); + AppServiceClient.prototype.getOrganizationNamespaceAvailability = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.GetOrganizationNamespaceAvailabilityRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = + new pb.GetOrganizationNamespaceAvailabilityResponse(); + response.setAvailable(true); + cb(null, response); + } + ); }); it('getOrganizationNamespaceAvailability', async () => { @@ -318,17 +342,19 @@ describe('AppClient tests', () => { describe('updateOrganization tests', () => { beforeEach(() => { - vi.spyOn( - AppServiceClient.prototype, - 'updateOrganization' - ).mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.UpdateOrganizationRequest, _md, cb) => { - const response = new pb.UpdateOrganizationResponse(); - response.setOrganization(org); - cb(null, response); - } - ); + AppServiceClient.prototype.updateOrganization = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.UpdateOrganizationRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.UpdateOrganizationResponse(); + response.setOrganization(org); + cb(null, response); + } + ); }); it('updateOrganization', async () => { @@ -350,14 +376,19 @@ describe('AppClient tests', () => { beforeEach(() => { methodSpy = vi - .spyOn(AppServiceClient.prototype, 'deleteOrganization') + .fn() .mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.DeleteOrganizationRequest, _md, cb) => { + ( + _req: pb.DeleteOrganizationRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { const response = new pb.DeleteOrganizationResponse(); cb(null, response); } ); + // @ts-expect-error compiler is matching incorrect function signature + AppServiceClient.prototype.deleteOrganization = methodSpy; }); it('deleteOrganization', async () => { @@ -384,15 +415,17 @@ describe('AppClient tests', () => { expectedResponse.setInvitesList(invites); beforeEach(() => { - vi.spyOn( - AppServiceClient.prototype, - 'listOrganizationMembers' - ).mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.ListOrganizationMembersRequest, _md, cb) => { - cb(null, expectedResponse); - } - ); + AppServiceClient.prototype.listOrganizationMembers = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.ListOrganizationMembersRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + cb(null, expectedResponse); + } + ); }); it('listOrganizationMembers', async () => { @@ -403,17 +436,19 @@ describe('AppClient tests', () => { describe('createOrganizationInvite tests', () => { beforeEach(() => { - vi.spyOn( - AppServiceClient.prototype, - 'createOrganizationInvite' - ).mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.CreateOrganizationInviteRequest, _md, cb) => { - const response = new pb.CreateOrganizationInviteResponse(); - response.setInvite(invite); - cb(null, response); - } - ); + AppServiceClient.prototype.createOrganizationInvite = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.CreateOrganizationInviteRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.CreateOrganizationInviteResponse(); + response.setInvite(invite); + cb(null, response); + } + ); }); it('createOrganizationInvite', async () => { @@ -423,24 +458,26 @@ describe('AppClient tests', () => { [], false ); - expect(response.invite).toEqual(invite.toObject()); + expect(response).toEqual(invite.toObject()); }); }); describe('updateOrganizationInviteAuthorizations tests', () => { beforeEach(() => { - vi.spyOn( - AppServiceClient.prototype, - 'updateOrganizationInviteAuthorizations' - ).mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.UpdateOrganizationInviteAuthorizationsRequest, _md, cb) => { - const response = - new pb.UpdateOrganizationInviteAuthorizationsResponse(); - response.setInvite(invite); - cb(null, response); - } - ); + AppServiceClient.prototype.updateOrganizationInviteAuthorizations = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.UpdateOrganizationInviteAuthorizationsRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = + new pb.UpdateOrganizationInviteAuthorizationsResponse(); + response.setInvite(invite); + cb(null, response); + } + ); }); it('updateOrganizationInviteAuthorizations', async () => { @@ -450,7 +487,7 @@ describe('AppClient tests', () => { [authorization], [] ); - expect(response.invite).toEqual(invite.toObject()); + expect(response).toEqual(invite.toObject()); }); }); @@ -462,13 +499,18 @@ describe('AppClient tests', () => { beforeEach(() => { methodSpy = vi - .spyOn(AppServiceClient.prototype, 'deleteOrganizationMember') + .fn() .mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.DeleteOrganizationMemberRequest, _md, cb) => { + ( + _req: pb.DeleteOrganizationMemberRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { cb(null, new pb.DeleteOrganizationInviteResponse()); } ); + // @ts-expect-error compiler is matching incorrect function signature + AppServiceClient.prototype.deleteOrganizationMember = methodSpy; }); it('deleteOrganizationMember', async () => { @@ -489,13 +531,18 @@ describe('AppClient tests', () => { beforeEach(() => { methodSpy = vi - .spyOn(AppServiceClient.prototype, 'deleteOrganizationInvite') + .fn() .mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.DeleteOrganizationInviteRequest, _md, cb) => { + ( + _req: pb.DeleteOrganizationInviteRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { cb(null, new pb.DeleteOrganizationInviteResponse()); } ); + // @ts-expect-error compiler is matching incorrect function signature + AppServiceClient.prototype.deleteOrganizationInvite = methodSpy; }); it('deleteOrganizationInvite', async () => { @@ -510,17 +557,19 @@ describe('AppClient tests', () => { describe('resendOrganizationInvite tests', () => { beforeEach(() => { - vi.spyOn( - AppServiceClient.prototype, - 'resendOrganizationInvite' - ).mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.ResendOrganizationInviteRequest, _md, cb) => { - const response = new pb.ResendOrganizationInviteResponse(); - response.setInvite(invite); - cb(null, response); - } - ); + AppServiceClient.prototype.resendOrganizationInvite = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.ResendOrganizationInviteRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.ResendOrganizationInviteResponse(); + response.setInvite(invite); + cb(null, response); + } + ); }); it('resendOrganizationInvite', async () => { @@ -528,19 +577,25 @@ describe('AppClient tests', () => { 'orgId', 'email' ); - expect(response.invite).toEqual(invite.toObject()); + expect(response).toEqual(invite.toObject()); }); }); describe('createLocation tests', () => { beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'createLocation') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.CreateLocationRequest, _md, cb) => { - const response = new pb.CreateLocationResponse(); - response.setLocation(location); - cb(null, response); - }); + AppServiceClient.prototype.createLocation = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.CreateLocationRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.CreateLocationResponse(); + response.setLocation(location); + cb(null, response); + } + ); }); it('createLocation', async () => { @@ -549,24 +604,30 @@ describe('AppClient tests', () => { 'name', 'parent' ); - expect(response.location).toEqual(location.toObject()); + expect(response).toEqual(location.toObject()); }); }); describe('getLocation tests', () => { beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'getLocation') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.GetLocationRequest, _md, cb) => { - const response = new pb.GetLocationResponse(); - response.setLocation(location); - cb(null, response); - }); + AppServiceClient.prototype.getLocation = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.GetLocationRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.GetLocationResponse(); + response.setLocation(location); + cb(null, response); + } + ); }); it('getLocation', async () => { const response = await subject().getLocation('locId'); - expect(response.location).toEqual(location.toObject()); + expect(response).toEqual(location.toObject()); }); }); @@ -577,13 +638,19 @@ describe('AppClient tests', () => { newLocation.setParentLocationId('newParent'); beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'updateLocation') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.UpdateLocationRequest, _md, cb) => { - const response = new pb.UpdateLocationResponse(); - response.setLocation(newLocation); - cb(null, response); - }); + AppServiceClient.prototype.updateLocation = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.UpdateLocationRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.UpdateLocationResponse(); + response.setLocation(newLocation); + cb(null, response); + } + ); }); it('updateLocation', async () => { @@ -593,7 +660,7 @@ describe('AppClient tests', () => { 'newParent', 'newRegion' ); - expect(response.location).toEqual(newLocation.toObject()); + expect(response).toEqual(newLocation.toObject()); }); }); @@ -604,11 +671,18 @@ describe('AppClient tests', () => { let methodSpy: MockInstance; beforeEach(() => { methodSpy = vi - .spyOn(AppServiceClient.prototype, 'deleteLocation') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.DeleteLocationRequest, _md, cb) => { - cb(null, new pb.DeleteLocationResponse()); - }); + .fn() + .mockImplementationOnce( + ( + _req: pb.DeleteLocationRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + cb(null, new pb.DeleteLocationResponse()); + } + ); + // @ts-expect-error compiler is matching incorrect function signature + AppServiceClient.prototype.deleteLocation = methodSpy; }); it('deleteLocation', async () => { @@ -624,13 +698,19 @@ describe('AppClient tests', () => { describe('listLocations tests', () => { const locations = [location]; beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'listLocations') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.ListLocationsRequest, _md, cb) => { - const response = new pb.ListLocationsResponse(); - response.setLocationsList(locations); - cb(null, response); - }); + AppServiceClient.prototype.listLocations = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.ListLocationsRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.ListLocationsResponse(); + response.setLocationsList(locations); + cb(null, response); + } + ); }); it('listLocations', async () => { @@ -647,11 +727,18 @@ describe('AppClient tests', () => { beforeEach(() => { methodSpy = vi - .spyOn(AppServiceClient.prototype, 'shareLocation') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.ShareLocationRequest, _md, cb) => { - cb(null, new pb.ShareLocationResponse()); - }); + .fn() + .mockImplementationOnce( + ( + _req: pb.ShareLocationRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + cb(null, new pb.ShareLocationResponse()); + } + ); + // @ts-expect-error compiler is matching incorrect function signature + AppServiceClient.prototype.shareLocation = methodSpy; }); it('shareLocation', async () => { @@ -672,11 +759,18 @@ describe('AppClient tests', () => { beforeEach(() => { methodSpy = vi - .spyOn(AppServiceClient.prototype, 'unshareLocation') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.UnshareLocationRequest, _md, cb) => { - cb(null, new pb.UnshareLocationResponse()); - }); + .fn() + .mockImplementationOnce( + ( + _req: pb.UnshareLocationRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + cb(null, new pb.UnshareLocationResponse()); + } + ); + // @ts-expect-error compiler is matching incorrect function signature + AppServiceClient.prototype.unshareLocation = methodSpy; }); it('unshareLocation', async () => { @@ -691,39 +785,47 @@ describe('AppClient tests', () => { describe('locationAuth tests', () => { beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'locationAuth') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.LocationAuthRequest, _md, cb) => { - const response = new pb.LocationAuthResponse(); - response.setAuth(auth); - cb(null, response); - }); + AppServiceClient.prototype.locationAuth = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.LocationAuthRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.LocationAuthResponse(); + response.setAuth(auth); + cb(null, response); + } + ); }); it('locationAuth', async () => { const response = await subject().locationAuth('locId'); - expect(response.auth).toEqual(auth.toObject()); + expect(response).toEqual(auth.toObject()); }); }); describe('createLocationSecret tests', () => { beforeEach(() => { - vi.spyOn( - AppServiceClient.prototype, - 'createLocationSecret' - ).mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.CreateLocationSecretRequest, _md, cb) => { - const response = new pb.CreateLocationSecretResponse(); - response.setAuth(auth); - cb(null, response); - } - ); + AppServiceClient.prototype.createLocationSecret = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.CreateLocationSecretRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.CreateLocationSecretResponse(); + response.setAuth(auth); + cb(null, response); + } + ); }); it('createLocationSecret', async () => { const response = await subject().createLocationSecret('locId'); - expect(response.auth).toEqual(auth.toObject()); + expect(response).toEqual(auth.toObject()); }); }); @@ -735,13 +837,18 @@ describe('AppClient tests', () => { beforeEach(() => { methodSpy = vi - .spyOn(AppServiceClient.prototype, 'deleteLocationSecret') + .fn() .mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.DeleteLocationSecretRequest, _md, cb) => { + ( + _req: pb.DeleteLocationSecretRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { cb(null, new pb.DeleteLocationSecretResponse()); } ); + // @ts-expect-error compiler is matching incorrect function signature + AppServiceClient.prototype.deleteLocationSecret = methodSpy; }); it('deleteLocationSecret', async () => { @@ -756,18 +863,24 @@ describe('AppClient tests', () => { describe('getRobot tests', () => { beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'getRobot') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.GetRobotRequest, _md, cb) => { - const response = new pb.GetRobotResponse(); - response.setRobot(robot); - cb(null, response); - }); + AppServiceClient.prototype.getRobot = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.GetRobotRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.GetRobotResponse(); + response.setRobot(robot); + cb(null, response); + } + ); }); it('getRobot', async () => { const response = await subject().getRobot('robotId'); - expect(response.robot).toEqual(robot.toObject()); + expect(response).toEqual(robot.toObject()); }); }); @@ -775,17 +888,19 @@ describe('AppClient tests', () => { const roverRentalRobots = [roverRentalRobot]; beforeEach(() => { - vi.spyOn( - AppServiceClient.prototype, - 'getRoverRentalRobots' - ).mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.GetRoverRentalRobotsRequest, _md, cb) => { - const response = new pb.GetRoverRentalRobotsResponse(); - response.setRobotsList(roverRentalRobots); - cb(null, response); - } - ); + AppServiceClient.prototype.getRoverRentalRobots = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.GetRoverRentalRobotsRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.GetRoverRentalRobotsResponse(); + response.setRobotsList(roverRentalRobots); + cb(null, response); + } + ); }); it('getRoverRentalRobots', async () => { @@ -798,13 +913,19 @@ describe('AppClient tests', () => { const parts = [robotPart]; beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'getRobotParts') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.GetRobotPartsRequest, _md, cb) => { - const response = new pb.GetRobotPartsResponse(); - response.setPartsList(parts); - cb(null, response); - }); + AppServiceClient.prototype.getRobotParts = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.GetRobotPartsRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.GetRobotPartsResponse(); + response.setPartsList(parts); + cb(null, response); + } + ); }); it('getRobotParts', async () => { @@ -818,11 +939,17 @@ describe('AppClient tests', () => { expectedResponse.setPart(robotPart); expectedResponse.setConfigJson('isJson: true'); beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'getRobotPart') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.GetRobotPartRequest, _md, cb) => { - cb(null, expectedResponse); - }); + AppServiceClient.prototype.getRobotPart = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.GetRobotPartRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + cb(null, expectedResponse); + } + ); }); it('getRobotPart', async () => { @@ -838,11 +965,17 @@ describe('AppClient tests', () => { expectedResponse.setNextPageToken('nextPage'); beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'getRobotPartLogs') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.GetRobotPartLogsRequest, _md, cb) => { - cb(null, expectedResponse); - }); + AppServiceClient.prototype.getRobotPartLogs = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.GetRobotPartLogsRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + cb(null, expectedResponse); + } + ); }); it('getRobotPartLogs', async () => { @@ -897,17 +1030,19 @@ describe('AppClient tests', () => { const histories = [partHistory]; beforeEach(() => { - vi.spyOn( - AppServiceClient.prototype, - 'getRobotPartHistory' - ).mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.GetRobotPartHistoryRequest, _md, cb) => { - const response = new pb.GetRobotPartHistoryResponse(); - response.setHistoryList(histories); - cb(null, response); - } - ); + AppServiceClient.prototype.getRobotPartHistory = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.GetRobotPartHistoryRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.GetRobotPartHistoryResponse(); + response.setHistoryList(histories); + cb(null, response); + } + ); }); it('getRobotPartHistory', async () => { @@ -918,30 +1053,42 @@ describe('AppClient tests', () => { describe('updateRobotPart tests', () => { beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'updateRobotPart') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.UpdateRobotPartRequest, _md, cb) => { - const response = new pb.UpdateRobotPartResponse(); - response.setPart(robotPart); - cb(null, response); - }); + AppServiceClient.prototype.updateRobotPart = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.UpdateRobotPartRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.UpdateRobotPartResponse(); + response.setPart(robotPart); + cb(null, response); + } + ); }); it('updateRobotPart', async () => { const response = await subject().updateRobotPart('id', 'name', {}); - expect(response.part).toEqual(robotPart.toObject()); + expect(response).toEqual(robotPart.toObject()); }); }); describe('newRobotPart tests', () => { beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'newRobotPart') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.NewRobotPartRequest, _md, cb) => { - const response = new pb.NewRobotPartResponse(); - response.setPartId('id'); - cb(null, response); - }); + AppServiceClient.prototype.newRobotPart = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.NewRobotPartRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.NewRobotPartResponse(); + response.setPartId('id'); + cb(null, response); + } + ); }); it('newRobotPart', async () => { @@ -957,11 +1104,18 @@ describe('AppClient tests', () => { beforeEach(() => { methodSpy = vi - .spyOn(AppServiceClient.prototype, 'deleteRobotPart') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.DeleteRobotPartRequest, _md, cb) => { - cb(null, new pb.DeleteRobotPartResponse()); - }); + .fn() + .mockImplementationOnce( + ( + _req: pb.DeleteRobotPartRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + cb(null, new pb.DeleteRobotPartResponse()); + } + ); + // @ts-expect-error compiler is matching incorrect function signature + AppServiceClient.prototype.deleteRobotPart = methodSpy; }); it('deleteRobotPart', async () => { @@ -978,13 +1132,19 @@ describe('AppClient tests', () => { const apiKeys = [apiKeyWithAuths]; beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'getRobotAPIKeys') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.GetRobotAPIKeysRequest, _md, cb) => { - const response = new pb.GetRobotAPIKeysResponse(); - response.setApiKeysList(apiKeys); - cb(null, response); - }); + AppServiceClient.prototype.getRobotAPIKeys = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.GetRobotAPIKeysRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.GetRobotAPIKeysResponse(); + response.setApiKeysList(apiKeys); + cb(null, response); + } + ); }); it('getRobotAPIKeys', async () => { @@ -1000,11 +1160,18 @@ describe('AppClient tests', () => { beforeEach(() => { methodSpy = vi - .spyOn(AppServiceClient.prototype, 'markPartAsMain') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.MarkPartAsMainRequest, _md, cb) => { - cb(null, new pb.MarkPartAsMainResponse()); - }); + .fn() + .mockImplementationOnce( + ( + _req: pb.MarkPartAsMainRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + cb(null, new pb.MarkPartAsMainResponse()); + } + ); + // @ts-expect-error compiler is matching incorrect function signature + AppServiceClient.prototype.markPartAsMain = methodSpy; }); it('markPartAsMain', async () => { @@ -1024,13 +1191,18 @@ describe('AppClient tests', () => { beforeEach(() => { methodSpy = vi - .spyOn(AppServiceClient.prototype, 'markPartForRestart') + .fn() .mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.MarkPartForRestartRequest, _md, cb) => { + ( + _req: pb.MarkPartForRestartRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { cb(null, new pb.MarkPartAsMainResponse()); } ); + // @ts-expect-error compiler is matching incorrect function signature + AppServiceClient.prototype.markPartForRestart = methodSpy; }); it('markPartForRestart', async () => { @@ -1045,22 +1217,24 @@ describe('AppClient tests', () => { describe('createRobotPartSecret tests', () => { beforeEach(() => { - vi.spyOn( - AppServiceClient.prototype, - 'createRobotPartSecret' - ).mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.CreateRobotPartSecretRequest, _md, cb) => { - const response = new pb.CreateRobotPartSecretResponse(); - response.setPart(robotPart); - cb(null, response); - } - ); + AppServiceClient.prototype.createRobotPartSecret = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.CreateRobotPartSecretRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.CreateRobotPartSecretResponse(); + response.setPart(robotPart); + cb(null, response); + } + ); }); it('createRobotPartSecret', async () => { const response = await subject().createRobotPartSecret('partId'); - expect(response.part).toEqual(robotPart.toObject()); + expect(response).toEqual(robotPart.toObject()); }); }); @@ -1072,13 +1246,18 @@ describe('AppClient tests', () => { beforeEach(() => { methodSpy = vi - .spyOn(AppServiceClient.prototype, 'deleteRobotPartSecret') + .fn() .mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.DeleteRobotPartSecretRequest, _md, cb) => { + ( + _req: pb.DeleteRobotPartSecretRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { cb(null, new pb.DeleteRobotPartSecretResponse()); } ); + // @ts-expect-error compiler is matching incorrect function signature + AppServiceClient.prototype.deleteRobotPartSecret = methodSpy; }); it('deleteRobotPartSecret', async () => { @@ -1095,13 +1274,19 @@ describe('AppClient tests', () => { const robots = [robot]; beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'listRobots') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.ListRobotsRequest, _md, cb) => { - const response = new pb.ListRobotsResponse(); - response.setRobotsList(robots); - cb(null, response); - }); + AppServiceClient.prototype.listRobots = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.ListRobotsRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.ListRobotsResponse(); + response.setRobotsList(robots); + cb(null, response); + } + ); }); it('listRobots', async () => { @@ -1112,13 +1297,19 @@ describe('AppClient tests', () => { describe('newRobot tests', () => { beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'newRobot') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.NewRobotRequest, _md, cb) => { - const response = new pb.NewRobotResponse(); - response.setId('robotId'); - cb(null, response); - }); + AppServiceClient.prototype.newRobot = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.NewRobotRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.NewRobotResponse(); + response.setId('robotId'); + cb(null, response); + } + ); }); it('newRobot', async () => { @@ -1129,13 +1320,19 @@ describe('AppClient tests', () => { describe('updateRobot tests', () => { beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'updateRobot') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.UpdateRobotRequest, _md, cb) => { - const response = new pb.UpdateRobotResponse(); - response.setRobot(robot); - cb(null, response); - }); + AppServiceClient.prototype.updateRobot = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.UpdateRobotRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.UpdateRobotResponse(); + response.setRobot(robot); + cb(null, response); + } + ); }); it('updateRobot', async () => { @@ -1144,7 +1341,7 @@ describe('AppClient tests', () => { 'locationId', 'name' ); - expect(response.robot).toEqual(robot.toObject()); + expect(response).toEqual(robot.toObject()); }); }); @@ -1155,11 +1352,18 @@ describe('AppClient tests', () => { beforeEach(() => { methodSpy = vi - .spyOn(AppServiceClient.prototype, 'deleteRobot') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.DeleteRobotRequest, _md, cb) => { - cb(null, new pb.DeleteRobotResponse()); - }); + .fn() + .mockImplementationOnce( + ( + _req: pb.DeleteRobotRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + cb(null, new pb.DeleteRobotResponse()); + } + ); + // @ts-expect-error compiler is matching incorrect function signature + AppServiceClient.prototype.deleteRobot = methodSpy; }); it('deleteRobot', async () => { @@ -1176,13 +1380,19 @@ describe('AppClient tests', () => { const fragments = [fragment]; beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'listFragments') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.ListFragmentsRequest, _md, cb) => { - const response = new pb.ListFragmentsResponse(); - response.setFragmentsList(fragments); - cb(null, response); - }); + AppServiceClient.prototype.listFragments = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.ListFragmentsRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.ListFragmentsResponse(); + response.setFragmentsList(fragments); + cb(null, response); + } + ); }); it('listFragments', async () => { @@ -1193,52 +1403,70 @@ describe('AppClient tests', () => { describe('getFragment tests', () => { beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'getFragment') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.GetFragmentRequest, _md, cb) => { - const response = new pb.GetFragmentResponse(); - response.setFragment(fragment); - cb(null, response); - }); + AppServiceClient.prototype.getFragment = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.GetFragmentRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.GetFragmentResponse(); + response.setFragment(fragment); + cb(null, response); + } + ); }); it('getFragment', async () => { const response = await subject().getFragment('id'); - expect(response.fragment).toEqual(fragment.toObject()); + expect(response).toEqual(fragment.toObject()); }); }); describe('createFragment tests', () => { beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'createFragment') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.CreateFragmentRequest, _md, cb) => { - const response = new pb.CreateFragmentResponse(); - response.setFragment(fragment); - cb(null, response); - }); + AppServiceClient.prototype.createFragment = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.CreateFragmentRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.CreateFragmentResponse(); + response.setFragment(fragment); + cb(null, response); + } + ); }); it('createFragment', async () => { const response = await subject().createFragment('orgId', 'name', {}); - expect(response.fragment).toEqual(fragment.toObject()); + expect(response).toEqual(fragment.toObject()); }); }); describe('updateFragment tests', () => { beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'updateFragment') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.UpdateFragmentRequest, _md, cb) => { - const response = new pb.UpdateFragmentResponse(); - response.setFragment(fragment); - cb(null, response); - }); + AppServiceClient.prototype.updateFragment = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.UpdateFragmentRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.UpdateFragmentResponse(); + response.setFragment(fragment); + cb(null, response); + } + ); }); it('updateFragment', async () => { const response = await subject().updateFragment('id', 'name', {}); - expect(response.fragment).toEqual(fragment.toObject()); + expect(response).toEqual(fragment.toObject()); }); }); @@ -1249,11 +1477,18 @@ describe('AppClient tests', () => { beforeEach(() => { methodSpy = vi - .spyOn(AppServiceClient.prototype, 'deleteFragment') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.DeleteFragmentRequest, _md, cb) => { - cb(null, new pb.DeleteFragmentResponse()); - }); + .fn() + .mockImplementationOnce( + ( + _req: pb.DeleteFragmentRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + cb(null, new pb.DeleteFragmentResponse()); + } + ); + // @ts-expect-error compiler is matching incorrect function signature + AppServiceClient.prototype.deleteFragment = methodSpy; }); it('deleteFragment', async () => { @@ -1273,11 +1508,18 @@ describe('AppClient tests', () => { beforeEach(() => { methodSpy = vi - .spyOn(AppServiceClient.prototype, 'addRole') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.AddRoleRequest, _md, cb) => { - cb(null, new pb.AddRoleResponse()); - }); + .fn() + .mockImplementationOnce( + ( + _req: pb.AddRoleRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + cb(null, new pb.AddRoleResponse()); + } + ); + // @ts-expect-error compiler is matching incorrect function signature + AppServiceClient.prototype.addRole = methodSpy; }); it('addRole', async () => { @@ -1303,11 +1545,18 @@ describe('AppClient tests', () => { beforeEach(() => { methodSpy = vi - .spyOn(AppServiceClient.prototype, 'removeRole') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.RemoveRoleRequest, _md, cb) => { - cb(null, new pb.RemoveRoleResponse()); - }); + .fn() + .mockImplementationOnce( + ( + _req: pb.RemoveRoleRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + cb(null, new pb.RemoveRoleResponse()); + } + ); + // @ts-expect-error compiler is matching incorrect function signature + AppServiceClient.prototype.removeRole = methodSpy; }); it('removeRole', async () => { @@ -1336,11 +1585,18 @@ describe('AppClient tests', () => { beforeEach(() => { methodSpy = vi - .spyOn(AppServiceClient.prototype, 'changeRole') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.ChangeRoleRequest, _md, cb) => { - cb(null, new pb.ChangeRoleResponse()); - }); + .fn() + .mockImplementationOnce( + ( + _req: pb.ChangeRoleRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + cb(null, new pb.ChangeRoleResponse()); + } + ); + // @ts-expect-error compiler is matching incorrect function signature + AppServiceClient.prototype.changeRole = methodSpy; }); it('changeRole', async () => { @@ -1357,17 +1613,19 @@ describe('AppClient tests', () => { const authorizations = [authorization]; beforeEach(() => { - vi.spyOn( - AppServiceClient.prototype, - 'listAuthorizations' - ).mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.ListAuthorizationsRequest, _md, cb) => { - const response = new pb.ListAuthorizationsResponse(); - response.setAuthorizationsList(authorizations); - cb(null, response); - } - ); + AppServiceClient.prototype.listAuthorizations = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.ListAuthorizationsRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.ListAuthorizationsResponse(); + response.setAuthorizationsList(authorizations); + cb(null, response); + } + ); }); it('listAuthorizations', async () => { @@ -1379,13 +1637,19 @@ describe('AppClient tests', () => { describe('checkPermissions tests', () => { const permissions = [permission]; beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'checkPermissions') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.CheckPermissionsRequest, _md, cb) => { - const response = new pb.CheckPermissionsResponse(); - response.setAuthorizedPermissionsList(permissions); - cb(null, response); - }); + AppServiceClient.prototype.checkPermissions = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.CheckPermissionsRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.CheckPermissionsResponse(); + response.setAuthorizedPermissionsList(permissions); + cb(null, response); + } + ); }); it('checkPermissions', async () => { @@ -1396,18 +1660,24 @@ describe('AppClient tests', () => { describe('getRegistryItem tests', () => { beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'getRegistryItem') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.GetRegistryItemRequest, _md, cb) => { - const response = new pb.GetRegistryItemResponse(); - response.setItem(registryItem); - cb(null, response); - }); + AppServiceClient.prototype.getRegistryItem = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.GetRegistryItemRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.GetRegistryItemResponse(); + response.setItem(registryItem); + cb(null, response); + } + ); }); it('getRegistryItem', async () => { const response = await subject().getRegistryItem('itemId'); - expect(response.item).toEqual(registryItem.toObject()); + expect(response).toEqual(registryItem.toObject()); }); }); @@ -1420,13 +1690,18 @@ describe('AppClient tests', () => { beforeEach(() => { methodSpy = vi - .spyOn(AppServiceClient.prototype, 'createRegistryItem') + .fn() .mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.CreateRegistryItemRequest, _md, cb) => { + ( + _req: pb.CreateRegistryItemRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { cb(null, new pb.CreateRegistryItemResponse()); } ); + // @ts-expect-error compiler is matching incorrect function signature + AppServiceClient.prototype.createRegistryItem = methodSpy; }); it('createRegistryItem', async () => { @@ -1453,13 +1728,18 @@ describe('AppClient tests', () => { beforeEach(() => { methodSpy = vi - .spyOn(AppServiceClient.prototype, 'updateRegistryItem') + .fn() .mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.UpdateRegistryItemRequest, _md, cb) => { + ( + _req: pb.UpdateRegistryItemRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { cb(null, new pb.UpdateRegistryItemResponse()); } ); + // @ts-expect-error compiler is matching incorrect function signature + AppServiceClient.prototype.updateRegistryItem = methodSpy; }); it('updateRegistryItem', async () => { @@ -1481,17 +1761,19 @@ describe('AppClient tests', () => { const items = [registryItem]; beforeEach(() => { - vi.spyOn( - AppServiceClient.prototype, - 'listRegistryItems' - ).mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.ListRegistryItemsRequest, _md, cb) => { - const response = new pb.ListRegistryItemsResponse(); - response.setItemsList(items); - cb(null, response); - } - ); + AppServiceClient.prototype.listRegistryItems = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.ListRegistryItemsRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.ListRegistryItemsResponse(); + response.setItemsList(items); + cb(null, response); + } + ); }); it('listRegistryItems', async () => { @@ -1515,13 +1797,18 @@ describe('AppClient tests', () => { beforeEach(() => { methodSpy = vi - .spyOn(AppServiceClient.prototype, 'deleteRegistryItem') + .fn() .mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.DeleteRegistryItemRequest, _md, cb) => { + ( + _req: pb.DeleteRegistryItemRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { cb(null, new pb.DeleteRegistryItemResponse()); } ); + // @ts-expect-error compiler is matching incorrect function signature + AppServiceClient.prototype.deleteRegistryItem = methodSpy; }); it('deleteRegistryItem', async () => { @@ -1536,14 +1823,20 @@ describe('AppClient tests', () => { describe('createModule tests', () => { beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'createModule') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.CreateModuleRequest, _md, cb) => { - const response = new pb.CreateModuleResponse(); - response.setUrl('url'); - response.setModuleId('id'); - cb(null, response); - }); + AppServiceClient.prototype.createModule = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.CreateModuleRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.CreateModuleResponse(); + response.setUrl('url'); + response.setModuleId('id'); + cb(null, response); + } + ); }); it('createModule', async () => { @@ -1555,13 +1848,19 @@ describe('AppClient tests', () => { describe('updateModule tests', () => { beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'updateModule') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.UpdateModuleRequest, _md, cb) => { - const response = new pb.UpdateModuleResponse(); - response.setUrl('url'); - cb(null, response); - }); + AppServiceClient.prototype.updateModule = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.UpdateModuleRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.UpdateModuleResponse(); + response.setUrl('url'); + cb(null, response); + } + ); }); it('updateModule', async () => { @@ -1579,18 +1878,24 @@ describe('AppClient tests', () => { describe('getModule tests', () => { beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'getModule') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.GetModuleRequest, _md, cb) => { - const response = new pb.GetModuleResponse(); - response.setModule(module); - cb(null, response); - }); + AppServiceClient.prototype.getModule = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.GetModuleRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.GetModuleResponse(); + response.setModule(module); + cb(null, response); + } + ); }); it('getModule', async () => { const response = await subject().getModule('id'); - expect(response.module).toEqual(module.toObject()); + expect(response).toEqual(module.toObject()); }); }); @@ -1598,13 +1903,19 @@ describe('AppClient tests', () => { const modules = [module]; beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'listModules') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.ListModulesRequest, _md, cb) => { - const response = new pb.ListModulesResponse(); - response.setModulesList(modules); - cb(null, response); - }); + AppServiceClient.prototype.listModules = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.ListModulesRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.ListModulesResponse(); + response.setModulesList(modules); + cb(null, response); + } + ); }); it('listModules', async () => { @@ -1615,14 +1926,20 @@ describe('AppClient tests', () => { describe('createKey tests', () => { beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'createKey') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.CreateKeyRequest, _md, cb) => { - const response = new pb.CreateKeyResponse(); - response.setId('id'); - response.setKey('key'); - cb(null, response); - }); + AppServiceClient.prototype.createKey = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.CreateKeyRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.CreateKeyResponse(); + response.setId('id'); + response.setKey('key'); + cb(null, response); + } + ); }); it('createKey', async () => { @@ -1639,11 +1956,18 @@ describe('AppClient tests', () => { beforeEach(() => { methodSpy = vi - .spyOn(AppServiceClient.prototype, 'deleteKey') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.DeleteKeyRequest, _md, cb) => { - cb(null, new pb.DeleteKeyResponse()); - }); + .fn() + .mockImplementationOnce( + ( + _req: pb.DeleteKeyRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + cb(null, new pb.DeleteKeyResponse()); + } + ); + // @ts-expect-error compiler is matching incorrect function signature + AppServiceClient.prototype.deleteKey = methodSpy; }); it('deleteKey', async () => { @@ -1660,13 +1984,19 @@ describe('AppClient tests', () => { const keys = [apiKeyWithAuths]; beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'listKeys') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.ListKeysRequest, _md, cb) => { - const response = new pb.ListKeysResponse(); - response.setApiKeysList(keys); - cb(null, response); - }); + AppServiceClient.prototype.listKeys = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.ListKeysRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.ListKeysResponse(); + response.setApiKeysList(keys); + cb(null, response); + } + ); }); it('listKeys', async () => { @@ -1677,14 +2007,20 @@ describe('AppClient tests', () => { describe('rotateKey tests', () => { beforeEach(() => { - vi.spyOn(AppServiceClient.prototype, 'rotateKey') - // @ts-expect-error compiler is matching incorrect function signature - .mockImplementationOnce((_req: pb.RotateKeyRequest, _md, cb) => { - const response = new pb.RotateKeyResponse(); - response.setId('newId'); - response.setKey('eyK'); - cb(null, response); - }); + AppServiceClient.prototype.rotateKey = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.RotateKeyRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = new pb.RotateKeyResponse(); + response.setId('newId'); + response.setKey('eyK'); + cb(null, response); + } + ); }); it('rotateKey', async () => { @@ -1696,19 +2032,21 @@ describe('AppClient tests', () => { describe('createKeyFromExistingKeyAuthorizations tests', () => { beforeEach(() => { - vi.spyOn( - AppServiceClient.prototype, - 'createKeyFromExistingKeyAuthorizations' - ).mockImplementationOnce( - // @ts-expect-error compiler is matching incorrect function signature - (_req: pb.CreateKeyFromExistingKeyAuthorizationsRequest, _md, cb) => { - const response = - new pb.CreateKeyFromExistingKeyAuthorizationsResponse(); - response.setKey('key'); - response.setId('id'); - cb(null, response); - } - ); + AppServiceClient.prototype.createKeyFromExistingKeyAuthorizations = vi + .fn() + .mockImplementationOnce( + ( + _req: pb.CreateKeyFromExistingKeyAuthorizationsRequest, + _md, + cb: (_: ServiceError | null, __: Message) => void + ) => { + const response = + new pb.CreateKeyFromExistingKeyAuthorizationsResponse(); + response.setKey('key'); + response.setId('id'); + cb(null, response); + } + ); }); it('createKeyFromExistingKeyAuthorizations', async () => { diff --git a/src/app/app-client.ts b/src/app/app-client.ts index 3aebdee1a..4e1414bea 100644 --- a/src/app/app-client.ts +++ b/src/app/app-client.ts @@ -96,7 +96,7 @@ export class AppClient { * @param email The email address of the user * @returns The user's ID */ - async getUserIDByEmail(email: string) { + async getUserIDByEmail(email: string): Promise { const { service } = this; const req = new pb.GetUserIDByEmailRequest(); @@ -115,7 +115,9 @@ export class AppClient { * @param name The name of the new organization * @returns The new organization */ - async createOrganization(name: string) { + async createOrganization( + name: string + ): Promise { const { service } = this; const req = new pb.CreateOrganizationRequest(); @@ -134,7 +136,7 @@ export class AppClient { * * @returns The organization list */ - async listOrganizations() { + async listOrganizations(): Promise { const { service } = this; const req = new pb.ListOrganizationsRequest(); @@ -151,7 +153,9 @@ export class AppClient { * @param locationId The ID of the location to query * @returns The list of locations with access to the requested location */ - async getOrganizationsWithAccessToLocation(locationId: string) { + async getOrganizationsWithAccessToLocation( + locationId: string + ): Promise { const { service } = this; const req = new pb.GetOrganizationsWithAccessToLocationRequest(); req.setLocationId(locationId); @@ -169,7 +173,9 @@ export class AppClient { * @param userId The ID of the user to query * @returns The list of locations the requested user has access to */ - async listOrganizationsByUser(userId: string) { + async listOrganizationsByUser( + userId: string + ): Promise { const { service } = this; const req = new pb.ListOrganizationsByUserRequest(); req.setUserId(userId); @@ -187,7 +193,9 @@ export class AppClient { * @param orgId The ID of the organization * @returns Details about the organization, if it exists */ - async getOrganization(orgId: string) { + async getOrganization( + orgId: string + ): Promise { const { service } = this; const req = new pb.GetOrganizationRequest(); req.setOrganizationId(orgId); @@ -196,7 +204,7 @@ export class AppClient { pb.GetOrganizationRequest, pb.GetOrganizationResponse >(service.getOrganization.bind(service), req); - return response.toObject(); + return response.getOrganization()?.toObject(); } /** @@ -205,7 +213,9 @@ export class AppClient { * @param namespace The namespace to query for availability * @returns A boolean indicating whether or not the namespace is available */ - async getOrganizationNamespaceAvailability(namespace: string) { + async getOrganizationNamespaceAvailability( + namespace: string + ): Promise { const { service } = this; const req = new pb.GetOrganizationNamespaceAvailabilityRequest(); req.setPublicNamespace(namespace); @@ -233,7 +243,7 @@ export class AppClient { publicNamespace?: string, region?: string, cid?: string - ) { + ): Promise { const { service } = this; const req = new pb.UpdateOrganizationRequest(); req.setOrganizationId(orgId); @@ -280,7 +290,9 @@ export class AppClient { * @returns An object containing organization members, pending invites, and * org ID */ - async listOrganizationMembers(orgId: string) { + async listOrganizationMembers( + orgId: string + ): Promise { const { service } = this; const req = new pb.ListOrganizationMembersRequest(); req.setOrganizationId(orgId); @@ -307,7 +319,7 @@ export class AppClient { email: string, authorizations: pb.Authorization[], sendEmailInvite = true - ) { + ): Promise { const { service } = this; const req = new pb.CreateOrganizationInviteRequest(); req.setOrganizationId(orgId); @@ -319,7 +331,7 @@ export class AppClient { pb.CreateOrganizationInviteRequest, pb.CreateOrganizationInviteResponse >(service.createOrganizationInvite.bind(service), req); - return response.toObject(); + return response.getInvite()?.toObject(); } /** @@ -336,7 +348,7 @@ export class AppClient { email: string, addAuthsList: pb.Authorization[], removeAuthsList: pb.Authorization[] - ) { + ): Promise { const { service } = this; const req = new pb.UpdateOrganizationInviteAuthorizationsRequest(); req.setOrganizationId(orgId); @@ -348,7 +360,7 @@ export class AppClient { pb.UpdateOrganizationInviteAuthorizationsRequest, pb.UpdateOrganizationInviteAuthorizationsResponse >(service.updateOrganizationInviteAuthorizations.bind(service), req); - return response.toObject(); + return response.getInvite()?.toObject(); } /** @@ -394,7 +406,10 @@ export class AppClient { * @param email The email associated with the invite to resend * @returns The invite */ - async resendOrganizationInvite(orgId: string, email: string) { + async resendOrganizationInvite( + orgId: string, + email: string + ): Promise { const { service } = this; const req = new pb.ResendOrganizationInviteRequest(); req.setOrganizationId(orgId); @@ -404,7 +419,7 @@ export class AppClient { pb.ResendOrganizationInviteRequest, pb.ResendOrganizationInviteResponse >(service.resendOrganizationInvite.bind(service), req); - return response.toObject(); + return response.getInvite()?.toObject(); } /** @@ -416,7 +431,11 @@ export class AppClient { * new location under * @returns The location object */ - async createLocation(orgId: string, name: string, parentLocationId?: string) { + async createLocation( + orgId: string, + name: string, + parentLocationId?: string + ): Promise { const { service } = this; const req = new pb.CreateLocationRequest(); req.setOrganizationId(orgId); @@ -429,7 +448,7 @@ export class AppClient { pb.CreateLocationRequest, pb.CreateLocationResponse >(service.createLocation.bind(service), req); - return response.toObject(); + return response.getLocation()?.toObject(); } /** @@ -438,7 +457,7 @@ export class AppClient { * @param locId The ID of the location to query. * @returns The location object */ - async getLocation(locId: string) { + async getLocation(locId: string): Promise { const { service } = this; const req = new pb.GetLocationRequest(); req.setLocationId(locId); @@ -447,7 +466,7 @@ export class AppClient { pb.GetLocationRequest, pb.GetLocationResponse >(service.getLocation.bind(service), req); - return response.toObject(); + return response.getLocation()?.toObject(); } /** @@ -465,7 +484,7 @@ export class AppClient { name?: string, parentLocId?: string, region?: string - ) { + ): Promise { const { service } = this; const req = new pb.UpdateLocationRequest(); req.setLocationId(locId); @@ -483,7 +502,7 @@ export class AppClient { pb.UpdateLocationRequest, pb.UpdateLocationResponse >(service.updateLocation.bind(service), req); - return response.toObject(); + return response.getLocation()?.toObject(); } /** @@ -508,7 +527,7 @@ export class AppClient { * @param orgId The ID of the organization to query * @returns A list of locations under the organization */ - async listLocations(orgId: string) { + async listLocations(orgId: string): Promise { const { service } = this; const req = new pb.ListLocationsRequest(); req.setOrganizationId(orgId); @@ -562,7 +581,9 @@ export class AppClient { * @param locId The ID of the location to retrieve `LocationAuth` from. * @returns The `LocationAuth` for the requested location. */ - async locationAuth(locId: string) { + async locationAuth( + locId: string + ): Promise { const { service } = this; const req = new pb.LocationAuthRequest(); req.setLocationId(locId); @@ -571,7 +592,7 @@ export class AppClient { pb.LocationAuthRequest, pb.LocationAuthResponse >(service.locationAuth.bind(service), req); - return response.toObject(); + return response.toObject().auth; } /** @@ -580,7 +601,9 @@ export class AppClient { * @param locId The ID of the location to create a `LocationAuth` for * @returns The newly created `LocationAuth` */ - async createLocationSecret(locId: string) { + async createLocationSecret( + locId: string + ): Promise { const { service } = this; const req = new pb.CreateLocationSecretRequest(); req.setLocationId(locId); @@ -589,7 +612,7 @@ export class AppClient { pb.CreateLocationSecretRequest, pb.CreateLocationSecretResponse >(service.createLocationSecret.bind(service), req); - return response.toObject(); + return response.toObject().auth; } /** @@ -616,7 +639,7 @@ export class AppClient { * @param id The ID of the robot * @returns The `Robot` object */ - async getRobot(id: string) { + async getRobot(id: string): Promise { const { service } = this; const req = new pb.GetRobotRequest(); req.setId(id); @@ -625,7 +648,7 @@ export class AppClient { service.getRobot.bind(service), req ); - return response.toObject(); + return response.toObject().robot; } /** @@ -634,7 +657,9 @@ export class AppClient { * @param orgId The ID of the organization to query * @returns The list of `RoverRentalRobot` objects */ - async getRoverRentalRobots(orgId: string) { + async getRoverRentalRobots( + orgId: string + ): Promise { const { service } = this; const req = new pb.GetRoverRentalRobotsRequest(); req.setOrgId(orgId); @@ -652,7 +677,7 @@ export class AppClient { * @param robotId The ID of the robot to query * @returns The list of `RobotPart` objects associated with the robot */ - async getRobotParts(robotId: string) { + async getRobotParts(robotId: string): Promise { const { service } = this; const req = new pb.GetRobotPartsRequest(); req.setRobotId(robotId); @@ -670,7 +695,7 @@ export class AppClient { * @param id The ID of the requested robot part * @returns The robot part and a its json config */ - async getRobotPart(id: string) { + async getRobotPart(id: string): Promise { const { service } = this; const req = new pb.GetRobotPartRequest(); req.setId(id); @@ -700,7 +725,7 @@ export class AppClient { filter?: string, levels?: string[], pageToken = '' - ) { + ): Promise { const { service } = this; const req = new pb.GetRobotPartLogsRequest(); req.setId(id); @@ -784,7 +809,9 @@ export class AppClient { * @param id The ID of the requested robot part * @returns The list of the robot part's history */ - async getRobotPartHistory(id: string) { + async getRobotPartHistory( + id: string + ): Promise { const { service } = this; const req = new pb.GetRobotPartHistoryRequest(); req.setId(id); @@ -804,7 +831,11 @@ export class AppClient { * @param robotConfig The new config for the robot part * @returns The updated robot part */ - async updateRobotPart(id: string, name: string, robotConfig: StructType) { + async updateRobotPart( + id: string, + name: string, + robotConfig: StructType + ): Promise { const { service } = this; const req = new pb.UpdateRobotPartRequest(); req.setId(id); @@ -815,7 +846,7 @@ export class AppClient { pb.UpdateRobotPartRequest, pb.UpdateRobotPartResponse >(service.updateRobotPart.bind(service), req); - return response.toObject(); + return response.toObject().part; } /** @@ -825,7 +856,7 @@ export class AppClient { * @param partName The name for the new robot part * @returns The ID of the newly-created robot part */ - async newRobotPart(robotId: string, partName: string) { + async newRobotPart(robotId: string, partName: string): Promise { const { service } = this; const req = new pb.NewRobotPartRequest(); req.setRobotId(robotId); @@ -860,7 +891,9 @@ export class AppClient { * @param robotId The ID of the robot to get API keys for * @returns A list of the robot's API keys */ - async getRobotAPIKeys(robotId: string) { + async getRobotAPIKeys( + robotId: string + ): Promise { const { service } = this; const req = new pb.GetRobotAPIKeysRequest(); req.setRobotId(robotId); @@ -910,7 +943,9 @@ export class AppClient { * @param partId The ID of the part to create a secret for * @returns The robot part object */ - async createRobotPartSecret(partId: string) { + async createRobotPartSecret( + partId: string + ): Promise { const { service } = this; const req = new pb.CreateRobotPartSecretRequest(); req.setPartId(partId); @@ -919,7 +954,7 @@ export class AppClient { pb.CreateRobotPartSecretRequest, pb.CreateRobotPartSecretResponse >(service.createRobotPartSecret.bind(service), req); - return response.toObject(); + return response.toObject().part; } /** @@ -946,7 +981,7 @@ export class AppClient { * @param locId The ID of the location to list robots for * @returns The list of robot objects */ - async listRobots(locId: string) { + async listRobots(locId: string): Promise { const { service } = this; const req = new pb.ListRobotsRequest(); req.setLocationId(locId); @@ -965,7 +1000,7 @@ export class AppClient { * @param name The name of the new robot * @returns The new robot's ID */ - async newRobot(locId: string, name: string) { + async newRobot(locId: string, name: string): Promise { const { service } = this; const req = new pb.NewRobotRequest(); req.setName(name); @@ -986,7 +1021,11 @@ export class AppClient { * @param name The name to update the robot to * @returns The newly-modified robot object */ - async updateRobot(robotId: string, locId: string, name: string) { + async updateRobot( + robotId: string, + locId: string, + name: string + ): Promise { const { service } = this; const req = new pb.UpdateRobotRequest(); req.setId(robotId); @@ -997,7 +1036,7 @@ export class AppClient { pb.UpdateRobotRequest, pb.UpdateRobotResponse >(service.updateRobot.bind(service), req); - return response.toObject(); + return response.toObject().robot; } /** @@ -1034,7 +1073,7 @@ export class AppClient { orgId: string, publicOnly = true, fragmentVisibilities: FragmentVisibilityMap[keyof FragmentVisibilityMap][] = [] - ) { + ): Promise { const { service } = this; const req = new pb.ListFragmentsRequest(); req.setOrganizationId(orgId); @@ -1054,7 +1093,7 @@ export class AppClient { * @param id The ID of the fragment to look up * @returns The requested fragment */ - async getFragment(id: string) { + async getFragment(id: string): Promise { const { service } = this; const req = new pb.GetFragmentRequest(); req.setId(id); @@ -1063,7 +1102,7 @@ export class AppClient { pb.GetFragmentRequest, pb.GetFragmentResponse >(service.getFragment.bind(service), req); - return response.toObject(); + return response.toObject().fragment; } /** @@ -1074,7 +1113,11 @@ export class AppClient { * @param config The new fragment's config * @returns The newly created fragment */ - async createFragment(orgId: string, name: string, config: StructType) { + async createFragment( + orgId: string, + name: string, + config: StructType + ): Promise { const { service } = this; const req = new pb.CreateFragmentRequest(); req.setOrganizationId(orgId); @@ -1085,7 +1128,7 @@ export class AppClient { pb.CreateFragmentRequest, pb.CreateFragmentResponse >(service.createFragment.bind(service), req); - return response.toObject(); + return response.toObject().fragment; } /** @@ -1110,7 +1153,7 @@ export class AppClient { config: StructType, makePublic?: boolean, visibility?: keyof pb.FragmentVisibilityMap - ) { + ): Promise { const { service } = this; const req = new pb.UpdateFragmentRequest(); req.setId(id); @@ -1127,7 +1170,7 @@ export class AppClient { pb.UpdateFragmentRequest, pb.UpdateFragmentResponse >(service.updateFragment.bind(service), req); - return response.toObject(); + return response.toObject().fragment; } /** @@ -1240,8 +1283,12 @@ export class AppClient { * @param orgId The ID of the organization to list authorizations for * @param resourceIds Optional list of IDs of resources to list authorizations * for. If not provided, all resources will be included + * @returns The list of authorizations */ - async listAuthorizations(orgId: string, resourceIds?: string[]) { + async listAuthorizations( + orgId: string, + resourceIds?: string[] + ): Promise { const { service } = this; const req = new pb.ListAuthorizationsRequest(); req.setOrganizationId(orgId); @@ -1262,7 +1309,9 @@ export class AppClient { * @param permissions A list of permissions to check * @returns A filtered list of the authorized permissions */ - async checkPermissions(permissions: pb.AuthorizedPermissions[]) { + async checkPermissions( + permissions: pb.AuthorizedPermissions[] + ): Promise { const { service } = this; const req = new pb.CheckPermissionsRequest(); req.setPermissionsList(permissions); @@ -1280,7 +1329,9 @@ export class AppClient { * @param itemId The ID of the item to get * @returns The requested item */ - async getRegistryItem(itemId: string) { + async getRegistryItem( + itemId: string + ): Promise { const { service } = this; const req = new pb.GetRegistryItemRequest(); req.setItemId(itemId); @@ -1289,7 +1340,7 @@ export class AppClient { pb.GetRegistryItemRequest, pb.GetRegistryItemResponse >(service.getRegistryItem.bind(service), req); - return response.toObject(); + return response.toObject().item; } /** @@ -1367,7 +1418,7 @@ export class AppClient { statuses: (keyof pb.RegistryItemStatusMap)[], searchTerm?: string, pageToken?: string - ) { + ): Promise { const { service } = this; const req = new pb.ListRegistryItemsRequest(); req.setOrganizationId(orgId); @@ -1424,7 +1475,10 @@ export class AppClient { * @param name The name of the module * @returns The module ID and a URL to its detail page */ - async createModule(orgId: string, name: string) { + async createModule( + orgId: string, + name: string + ): Promise { const { service } = this; const req = new pb.CreateModuleRequest(); req.setOrganizationId(orgId); @@ -1455,7 +1509,7 @@ export class AppClient { description: string, models: pb.Model[], entrypoint: string - ) { + ): Promise { const { service } = this; const req = new pb.UpdateModuleRequest(); req.setModuleId(moduleId); @@ -1478,7 +1532,7 @@ export class AppClient { * @param moduleId The ID of the module * @returns The requested module */ - async getModule(moduleId: string) { + async getModule(moduleId: string): Promise { const { service } = this; const req = new pb.GetModuleRequest(); req.setModuleId(moduleId); @@ -1487,7 +1541,7 @@ export class AppClient { service.getModule.bind(service), req ); - return response.toObject(); + return response.toObject().module; } /** @@ -1496,7 +1550,7 @@ export class AppClient { * @param orgId The ID of the organization to query * @returns The organization's modules */ - async listModules(orgId: string) { + async listModules(orgId: string): Promise { const { service } = this; const req = new pb.ListModulesRequest(); req.setOrganizationId(orgId); @@ -1516,7 +1570,10 @@ export class AppClient { * present timestamp * @returns The new key and ID */ - async createKey(authorizations: pb.Authorization[], name?: string) { + async createKey( + authorizations: pb.Authorization[], + name?: string + ): Promise { const { service } = this; const req = new pb.CreateKeyRequest(); req.setAuthorizationsList(authorizations); @@ -1552,7 +1609,9 @@ export class AppClient { * @param orgId The ID of the organization to query * @returns The list of API keys */ - async listKeys(orgId: string) { + async listKeys( + orgId: string + ): Promise { const { service } = this; const req = new pb.ListKeysRequest(); req.setOrgId(orgId); @@ -1570,7 +1629,7 @@ export class AppClient { * @param id The ID of the key to rotate * @returns The updated key and ID */ - async rotateKey(id: string) { + async rotateKey(id: string): Promise { const { service } = this; const req = new pb.RotateKeyRequest(); req.setId(id); @@ -1588,7 +1647,9 @@ export class AppClient { * @param id The ID of the key to duplicate * @returns The new key and ID */ - async createKeyFromExistingKeyAuthorizations(id: string) { + async createKeyFromExistingKeyAuthorizations( + id: string + ): Promise { const { service } = this; const req = new pb.CreateKeyFromExistingKeyAuthorizationsRequest(); req.setId(id); diff --git a/src/app/data-client.ts b/src/app/data-client.ts index 52f01e8eb..eb1c3b8ed 100644 --- a/src/app/data-client.ts +++ b/src/app/data-client.ts @@ -580,7 +580,7 @@ export class DataClient { /** * Get a connection to access a MongoDB Atlas Data federation instance. * - * @param orId Organization to retrieve connection for + * @param orgId Organization to retrieve connection for * @returns Hostname of the federated database */ async getDatabaseConnection(orgId: string) { diff --git a/src/app/viam-client.spec.ts b/src/app/viam-client.spec.ts new file mode 100644 index 000000000..2dcddcc1f --- /dev/null +++ b/src/app/viam-client.spec.ts @@ -0,0 +1,253 @@ +// @vitest-environment happy-dom + +import { FakeTransportBuilder } from '@improbable-eng/grpc-web-fake-transport'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { + createViamTransportFactory, + type Credential, + type AccessToken, +} from './viam-transport'; +vi.mock('./viam-transport', async (actualImport) => { + const actual = await actualImport(); + return { + ...actual, + createViamTransportFactory: vi + .fn() + .mockReturnValue(() => new FakeTransportBuilder().build()), + }; +}); +import { createRobotClient } from '../robot/dial'; +vi.mock('../robot/dial', () => { + return { createRobotClient: vi.fn() }; +}); +import { DataClient } from './data-client'; +import { BillingClient } from './billing-client'; +import { createViamClient, type ViamClientOptions } from './viam-client'; +import { MlTrainingClient } from './ml-training-client'; +import { ProvisioningClient } from './provisioning-client'; +import { AppClient } from './app-client'; +import { Location, RobotPart, SharedSecret } from '../gen/app/v1/app_pb'; + +describe('ViamClient', () => { + let options: ViamClientOptions | undefined; + + const defaultServiceHost = 'https://app.viam.com'; + const testCredential: Credential = { + authEntity: 'test-auth-entity', + type: 'api-key', + payload: 'testApiKey', + }; + const testAccessToken: AccessToken = { + type: 'access-token', + payload: 'testAccessToken', + }; + + const subject = async () => createViamClient(options!); + + beforeEach(() => { + options = undefined; + }); + + it('create client with an api key credential', async () => { + options = { credential: testCredential }; + const client = await subject(); + expect(createViamTransportFactory).toHaveBeenCalledWith( + defaultServiceHost, + testCredential + ); + expect(client.appClient).toBeInstanceOf(AppClient); + expect(client.dataClient).toBeInstanceOf(DataClient); + expect(client.mlTrainingClient).toBeInstanceOf(MlTrainingClient); + expect(client.provisioningClient).toBeInstanceOf(ProvisioningClient); + expect(client.billingClient).toBeInstanceOf(BillingClient); + }); + + it('create client with an api key credential and a custom service host', async () => { + const serviceHost = 'https://test.service.host'; + options = { serviceHost, credential: testCredential }; + const client = await subject(); + + expect(createViamTransportFactory).toHaveBeenCalledWith( + serviceHost, + testCredential + ); + expect(client.appClient).toBeInstanceOf(AppClient); + expect(client.dataClient).toBeInstanceOf(DataClient); + expect(client.mlTrainingClient).toBeInstanceOf(MlTrainingClient); + expect(client.provisioningClient).toBeInstanceOf(ProvisioningClient); + expect(client.billingClient).toBeInstanceOf(BillingClient); + }); + + it('create client with an access token', async () => { + options = { credential: testAccessToken }; + const client = await subject(); + + expect(createViamTransportFactory).toHaveBeenCalledWith( + defaultServiceHost, + testAccessToken + ); + expect(client.appClient).toBeInstanceOf(AppClient); + expect(client.dataClient).toBeInstanceOf(DataClient); + expect(client.mlTrainingClient).toBeInstanceOf(MlTrainingClient); + expect(client.provisioningClient).toBeInstanceOf(ProvisioningClient); + expect(client.billingClient).toBeInstanceOf(BillingClient); + }); + + describe('ViamClient.connectToMachine', () => { + it('errors if neither host nor id are provided', async () => { + options = { credential: testCredential }; + const client = await subject(); + await expect(async () => + client.connectToMachine({}) + ).rejects.toThrowError('must be provided'); + }); + + it('errors if no main part found', async () => { + options = { credential: testCredential }; + const client = await subject(); + + const getRobotPartsMock = vi.fn().mockImplementation(() => []); + AppClient.prototype.getRobotParts = getRobotPartsMock; + + await expect(async () => + client.connectToMachine({ id: 'test-machine-uuid' }) + ).rejects.toThrowError('not find a main part'); + }); + + it('gets main part address', async () => { + const MAIN_PART = new RobotPart(); + MAIN_PART.setMainPart(true); + MAIN_PART.setFqdn('main.part.fqdn'); + + const robotParts = [MAIN_PART.toObject()]; + // eslint-disable-next-line no-plusplus + for (let i = 0; i < 1000; i++) { + const part = new RobotPart(); + part.setMainPart(false); + robotParts.push(part.toObject()); + } + robotParts.sort(() => Math.random() - 0.5); + + const getRobotPartsMock = vi.fn().mockImplementation(() => robotParts); + AppClient.prototype.getRobotParts = getRobotPartsMock; + + options = { credential: testCredential }; + const client = await subject(); + await client.connectToMachine({ id: 'test-machine-uuid' }); + + expect(getRobotPartsMock).toHaveBeenCalledWith('test-machine-uuid'); + expect(createRobotClient).toHaveBeenCalledWith( + expect.objectContaining({ host: MAIN_PART.getFqdn() }) + ); + }); + + it('errors if no address could be found', async () => { + options = { credential: testCredential }; + const client = await subject(); + + const MAIN_PART = new RobotPart(); + MAIN_PART.setMainPart(true); + const robotParts = [MAIN_PART.toObject()]; + const getRobotPartsMock = vi.fn().mockImplementation(() => robotParts); + AppClient.prototype.getRobotParts = getRobotPartsMock; + + await expect(async () => + client.connectToMachine({ id: 'test-machine-uuid' }) + ).rejects.toThrowError('not provided and could not be obtained'); + }); + + it('gets location secret if credential is access token -- host', async () => { + options = { credential: testAccessToken }; + const client = await subject(); + + const location = new Location().toObject(); + location.auth = { + secretsList: [ + { + id: '0', + state: SharedSecret.State.STATE_DISABLED, + secret: 'disabled secret', + }, + { + id: '1', + state: SharedSecret.State.STATE_UNSPECIFIED, + secret: 'unspecified secret', + }, + { + id: '2', + state: SharedSecret.State.STATE_ENABLED, + secret: 'enabled secret', + }, + ], + locationId: 'location', + secret: 'secret', + }; + const getLocationMock = vi.fn().mockImplementation(() => location); + AppClient.prototype.getLocation = getLocationMock; + + await client.connectToMachine({ + host: 'main-part.location.viam.cloud', + }); + expect(getLocationMock).toHaveBeenCalledWith('location'); + expect(createRobotClient).toHaveBeenCalledWith( + expect.objectContaining({ + credential: expect.objectContaining({ + type: 'robot-location-secret', + payload: 'enabled secret', + }), + }) + ); + }); + + it('gets location secret if credential is access token -- id', async () => { + options = { credential: testAccessToken }; + const client = await subject(); + + const MAIN_PART = new RobotPart(); + MAIN_PART.setMainPart(true); + MAIN_PART.setLocationId('location-id'); + MAIN_PART.setFqdn('main-part.fqdn'); + const robotParts = [MAIN_PART.toObject()]; + const getRobotPartsMock = vi.fn().mockImplementation(() => robotParts); + AppClient.prototype.getRobotParts = getRobotPartsMock; + + const location = new Location().toObject(); + location.auth = { + secretsList: [ + { + id: '0', + state: SharedSecret.State.STATE_DISABLED, + secret: 'disabled secret', + }, + { + id: '1', + state: SharedSecret.State.STATE_UNSPECIFIED, + secret: 'unspecified secret', + }, + { + id: '2', + state: SharedSecret.State.STATE_ENABLED, + secret: 'enabled secret', + }, + ], + locationId: 'location', + secret: 'secret', + }; + const getLocationMock = vi.fn().mockImplementation(() => location); + AppClient.prototype.getLocation = getLocationMock; + + await client.connectToMachine({ + id: 'machine-uuid', + }); + expect(getLocationMock).toHaveBeenCalledWith('location-id'); + expect(createRobotClient).toHaveBeenCalledWith( + expect.objectContaining({ + credential: expect.objectContaining({ + type: 'robot-location-secret', + payload: 'enabled secret', + }), + }) + ); + }); + }); +}); diff --git a/src/app/viam-client.test.ts b/src/app/viam-client.test.ts deleted file mode 100644 index 4d672861d..000000000 --- a/src/app/viam-client.test.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { FakeTransportBuilder } from '@improbable-eng/grpc-web-fake-transport'; -import { beforeEach, describe, expect, it, vi } from 'vitest'; -import { - createViamTransportFactory, - type Credential, - type AccessToken, -} from './viam-transport'; -vi.mock('./viam-transport', () => { - return { - createViamTransportFactory: vi - .fn() - .mockReturnValue(() => new FakeTransportBuilder().build()), - }; -}); -import { DataClient } from './data-client'; -import { BillingClient } from './billing-client'; -import { createViamClient, type ViamClientOptions } from './viam-client'; -import { MlTrainingClient } from './ml-training-client'; -import { ProvisioningClient } from './provisioning-client'; -import { AppClient } from './app-client'; - -describe('ViamClient', () => { - let options: ViamClientOptions | undefined; - - const defaultServiceHost = 'https://app.viam.com'; - const testCredential: Credential = { - authEntity: 'test-auth-entity', - type: 'api-key', - payload: 'testApiKey', - }; - const testAccessToken: AccessToken = { - type: 'access-token', - payload: 'testAccessToken', - }; - - const subject = async () => createViamClient(options!); - - beforeEach(() => { - options = undefined; - }); - - it('create client with an api key credential', async () => { - options = { credential: testCredential }; - const client = await subject(); - expect(createViamTransportFactory).toHaveBeenCalledWith( - defaultServiceHost, - testCredential - ); - expect(client.appClient).toBeInstanceOf(AppClient); - expect(client.dataClient).toBeInstanceOf(DataClient); - expect(client.mlTrainingClient).toBeInstanceOf(MlTrainingClient); - expect(client.provisioningClient).toBeInstanceOf(ProvisioningClient); - expect(client.billingClient).toBeInstanceOf(BillingClient); - }); - - it('create client with an api key credential and a custom service host', async () => { - const serviceHost = 'https://test.service.host'; - options = { serviceHost, credential: testCredential }; - const client = await subject(); - - expect(createViamTransportFactory).toHaveBeenCalledWith( - serviceHost, - testCredential - ); - expect(client.appClient).toBeInstanceOf(AppClient); - expect(client.dataClient).toBeInstanceOf(DataClient); - expect(client.mlTrainingClient).toBeInstanceOf(MlTrainingClient); - expect(client.provisioningClient).toBeInstanceOf(ProvisioningClient); - expect(client.billingClient).toBeInstanceOf(BillingClient); - }); - - it('create client with an access token', async () => { - options = { credential: testAccessToken }; - const client = await subject(); - - expect(createViamTransportFactory).toHaveBeenCalledWith( - defaultServiceHost, - testAccessToken - ); - expect(client.appClient).toBeInstanceOf(AppClient); - expect(client.dataClient).toBeInstanceOf(DataClient); - expect(client.mlTrainingClient).toBeInstanceOf(MlTrainingClient); - expect(client.provisioningClient).toBeInstanceOf(ProvisioningClient); - expect(client.billingClient).toBeInstanceOf(BillingClient); - }); -}); diff --git a/src/app/viam-client.ts b/src/app/viam-client.ts index b4dd584d4..a6a8d0fda 100644 --- a/src/app/viam-client.ts +++ b/src/app/viam-client.ts @@ -3,12 +3,15 @@ import { createViamTransportFactory, type Credential, type AccessToken, + isCredential, } from './viam-transport'; +import { createRobotClient } from '../robot/dial'; import { DataClient } from './data-client'; import { AppClient } from './app-client'; import { BillingClient } from './billing-client'; import { MlTrainingClient } from './ml-training-client'; import { ProvisioningClient } from './provisioning-client'; +import { SharedSecret } from '../gen/app/v1/app_pb'; export interface ViamClientOptions { serviceHost?: string; @@ -24,15 +27,21 @@ export const createViamClient = async ({ serviceHost, credential ); - const client = new ViamClient(transportFactory, serviceHost); + const client = new ViamClient(transportFactory, serviceHost, credential); client.connect(); return client; }; +interface ViamClientMachineConnectionOpts { + host?: string; + id?: string; +} + /** A gRPC client for method calls to Viam app. */ export class ViamClient { private transportFactory: grpc.TransportFactory; private serviceHost: string; + private credential: Credential | AccessToken; public dataClient: DataClient | undefined; public appClient: AppClient | undefined; @@ -40,9 +49,14 @@ export class ViamClient { public provisioningClient: ProvisioningClient | undefined; public billingClient: BillingClient | undefined; - constructor(transportFactory: grpc.TransportFactory, serviceHost: string) { + constructor( + transportFactory: grpc.TransportFactory, + serviceHost: string, + credential: Credential | AccessToken + ) { this.transportFactory = transportFactory; this.serviceHost = serviceHost; + this.credential = credential; } public connect() { @@ -56,4 +70,69 @@ export class ViamClient { ); this.billingClient = new BillingClient(this.serviceHost, grpcOptions); } + + public async connectToMachine({ + host = undefined, + id = undefined, + }: ViamClientMachineConnectionOpts) { + if (host === undefined && id === undefined) { + throw new Error('Either a machine address or ID must be provided'); + } + let address = host; + let locationId: string | undefined = undefined; + + // Get address if only ID was provided + if (id !== undefined && host === undefined) { + const parts = await this.appClient?.getRobotParts(id); + const mainPart = parts?.find((part) => part.mainPart); + if (!mainPart) { + throw new Error( + `Could not find a main part for the machine with UUID: ${id}` + ); + } + address = mainPart.fqdn; + locationId = mainPart.locationId; + } + + if (!address) { + throw new Error( + 'Host was not provided and could not be obtained from the machine ID' + ); + } + + // If credential is AccessToken, then attempt to get the robot location secret + let creds = this.credential; + if (!isCredential(creds)) { + if (locationId === undefined) { + // If we don't have a location, try to get it from the address + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const firstHalf = address.split('.viam.'); + const locationSplit = firstHalf[0]?.split('.'); + if (locationSplit !== undefined) { + locationId = locationSplit.at(-1); + } + } + if (locationId !== undefined) { + // If we found the location, then attempt to get its secret + const location = await this.appClient?.getLocation(locationId); + const secret = location?.auth?.secretsList.find( + (sec) => sec.state === SharedSecret.State.STATE_ENABLED + ); + creds = { + type: 'robot-location-secret', + payload: secret?.secret, + authEntity: address, + } as Credential; + } + } + + return createRobotClient({ + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + host: address, + credential: creds, + authEntity: (creds as Credential).authEntity, + signalingAddress: 'https://app.viam.com:443', + reconnectMaxAttempts: 1, + }); + } } diff --git a/src/app/viam-transport.ts b/src/app/viam-transport.ts index 7bb96410c..6a6c9a0b5 100644 --- a/src/app/viam-transport.ts +++ b/src/app/viam-transport.ts @@ -22,6 +22,12 @@ export interface AccessToken { payload: string; } +export const isCredential = ( + object: Credential | AccessToken +): object is Credential => { + return 'authEntity' in object; +}; + /** * Initialize an authenticated transport factory that can access protected * resources.