Rework proto parsing to use javascript objects, add nested and object message support

Objects are preferred to classes as they're easier to clone and serialise/deserialise
This commit is contained in:
2024-06-26 21:51:43 +09:30
parent d484f75540
commit da8861cde2
3 changed files with 191 additions and 62 deletions

View File

@@ -1,17 +1,12 @@
import { TestBed } from '@angular/core/testing';
import { provideExperimentalZonelessChangeDetection } from '@angular/core';
import {
Type,
provideExperimentalZonelessChangeDetection,
} from '@angular/core';
import {
BooleanMessage,
ListMessage,
MapMessage,
MessageConfiguration,
NumericMessage,
MessageTypeEnum,
ObjectMessage,
ProtoMessage,
StringMessage,
} from './model/proto-message.model';
import { ProtoDefinitionService } from './proto-definition.service';
@@ -19,15 +14,25 @@ let testProto = `
syntax="proto3";
message Test {
string hello = 1;
int32 hello2 = 2;
int64 hello3 = 3;
float hello4 = 4;
double hello5 = 5;
bool hello6 = 6;
repeated string hello7 = 7;
map<string, string> hello8 = 8;
message NestedMessage {
string nested = 1;
}
string hello = 1;
int32 hello2 = 2;
int64 hello3 = 3;
float hello4 = 4;
double hello5 = 5;
bool hello6 = 6;
repeated string hello7 = 7;
map<string, string> hello8 = 8;
ReferenceMessage hello9 = 9;
NestedMessage hello10 = 10;
}
message ReferenceMessage {
string test = 1;
}
`;
describe('TestService', () => {
@@ -42,34 +47,54 @@ describe('TestService', () => {
it('should convert parse protobuf correctly', async () => {
const testMessages = await service.parseProtoDefinition(testProto);
const converted = testMessages[0];
const converted = testMessages[1];
expect(converted.name).toBe('Test');
expect(converted.values.length).toBe(8);
checkNameAndType(converted, 'hello', StringMessage);
checkNameAndType(converted, 'hello2', NumericMessage);
checkNameAndType(converted, 'hello3', NumericMessage);
checkNameAndType(converted, 'hello4', NumericMessage);
checkNameAndType(converted, 'hello5', NumericMessage);
checkNameAndType(converted, 'hello6', BooleanMessage);
checkNameAndType(converted, 'hello7', ListMessage);
checkNameAndType(converted, 'hello8', MapMessage);
expect(converted.values.length).toBe(10);
checkNameAndType(converted, 'hello', MessageTypeEnum.String);
checkNameAndType(converted, 'hello2', MessageTypeEnum.Numeric);
checkNameAndType(converted, 'hello3', MessageTypeEnum.Numeric);
checkNameAndType(converted, 'hello4', MessageTypeEnum.Numeric);
checkNameAndType(converted, 'hello5', MessageTypeEnum.Numeric);
checkNameAndType(converted, 'hello6', MessageTypeEnum.Boolean);
checkNameAndType(converted, 'hello7', MessageTypeEnum.List);
checkNameAndType(converted, 'hello8', MessageTypeEnum.Map);
checkNameAndType(converted, 'hello9', MessageTypeEnum.Object);
checkNameAndType(converted, 'hello10', MessageTypeEnum.Object);
const listMessage = converted.values[6].configuration as ListMessage;
expect(listMessage.subConfiguration).toBeInstanceOf(StringMessage);
expect(listMessage.subConfiguration.type).toBe(MessageTypeEnum.String);
const mapMessage = converted.values[7].configuration as MapMessage;
expect(mapMessage.keyConfiguration).toBeInstanceOf(StringMessage);
expect(mapMessage.valueConfiguration).toBeInstanceOf(StringMessage);
expect(mapMessage.keyConfiguration.type).toBe(MessageTypeEnum.String);
expect(mapMessage.valueConfiguration.type).toBe(MessageTypeEnum.String);
const referenceMessage = converted.values[8].configuration as ObjectMessage;
expect(referenceMessage.messageDefinition.values.length).toBe(1);
expect(referenceMessage.messageDefinition.name).toBe('ReferenceMessage');
const nestedReferenceMessage = referenceMessage.messageDefinition.values[0];
expect(nestedReferenceMessage.configuration.type).toBe(
MessageTypeEnum.String
);
expect(nestedReferenceMessage.name).toBe('test');
const nestedMessage = converted.values[9].configuration as ObjectMessage;
expect(nestedMessage.messageDefinition.values.length).toBe(1);
expect(nestedMessage.messageDefinition.name).toBe('NestedMessage');
const nestedNestedMessage = nestedMessage.messageDefinition.values[0];
expect(nestedNestedMessage.configuration.type).toBe(MessageTypeEnum.String);
expect(nestedNestedMessage.name).toBe('nested');
// TODO: Enum type
});
});
const checkNameAndType = (
converted: ProtoMessage,
name: string,
type: Type<MessageConfiguration>
type: MessageTypeEnum
) => {
const field = converted.values.find((value) => value.name === name);
expect(field?.configuration).toBeInstanceOf(type);
expect(field?.configuration.type).toBe(type);
};