|
|
|
/*
|
|
|
|
* Copyright 2025 coze-dev Authors
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
import * as t from '../src/proto';
|
|
|
|
|
|
|
|
describe('ferry-parser', () => {
|
|
|
|
describe('proto field', () => {
|
|
|
|
it('should convert message field extensions', () => {
|
|
|
|
const idl = `
|
|
|
|
syntax = "proto3";
|
|
|
|
enum Numbers {
|
|
|
|
ONE = 1;
|
|
|
|
}
|
|
|
|
message Foo {
|
|
|
|
string k1 = 1 [(api.position) = "query"];
|
|
|
|
string k2 = 2 [(api.position) = 'body'];
|
|
|
|
string k3 = 3 [(api.position) = 'path'];
|
|
|
|
string k4 = 4 [(api.position) = 'header'];
|
|
|
|
string k5 = 5 [(api.position) = 'entire_body'];
|
|
|
|
string k6 = 6 [(api.position) = 'raw_body', (aapi.position) = 'raw_body'];
|
|
|
|
string k7 = 7 [(api.position) = 'status_code', (api.positionn) = 'raw_body'];
|
|
|
|
string k10 = 10 [(api.key) = 'key10'];
|
|
|
|
string k11 = 11 [(api.key) = 'k11'];
|
|
|
|
bytes k12 = 12 [(api.web_type) = 'File'];
|
|
|
|
int32 k21 = 21 [(api.query) = 'k21'];
|
|
|
|
int32 k22 = 22 [(api.body) = 'k22'];
|
|
|
|
int32 k23 = 23 [(api.path) = 'k23'];
|
|
|
|
int32 k24 = 24 [(api.header) = 'k24'];
|
|
|
|
int32 k25 = 25 [(api.entire_body) = 'key25'];
|
|
|
|
int32 k26 = 26 [(api.raw_body) = 'key_26'];
|
|
|
|
int32 k27 = 27 [(api.status_code) = 'key-27'];
|
|
|
|
int32 k31 = 31 [(api.query) = 'key31', (api.web_type) = 'number', (api.position) = ''];
|
|
|
|
int32 k32 = 32 [(api.position) = 'body', (api.key)='key32', (api.value_type) = 'any'];
|
|
|
|
int32 k33 = 33 [(api.method) = 'POST', (api.position) = 'QUERY'];
|
|
|
|
int32 k34 = 34 ;
|
|
|
|
Numbers k35 = 35 [(api.position) = 'path'];
|
|
|
|
}
|
|
|
|
`;
|
|
|
|
|
|
|
|
const expected = [
|
|
|
|
{ position: 'query' },
|
|
|
|
{ position: 'body' },
|
|
|
|
{ position: 'path' },
|
|
|
|
{ position: 'header' },
|
|
|
|
{ position: 'entire_body' },
|
|
|
|
{ position: 'raw_body' },
|
|
|
|
{ position: 'status_code' },
|
|
|
|
{ key: 'key10' },
|
|
|
|
{},
|
|
|
|
{ web_type: 'File' },
|
|
|
|
{ position: 'query' },
|
|
|
|
{ position: 'body' },
|
|
|
|
{ position: 'path' },
|
|
|
|
{ position: 'header' },
|
|
|
|
{ position: 'entire_body', key: 'key25' },
|
|
|
|
{ position: 'raw_body', key: 'key_26' },
|
|
|
|
{ position: 'status_code', key: 'key-27' },
|
|
|
|
{ position: 'query', key: 'key31', web_type: 'number' },
|
|
|
|
{ position: 'body', key: 'key32', value_type: 'any' },
|
|
|
|
{},
|
|
|
|
undefined,
|
|
|
|
{ position: 'path' },
|
|
|
|
];
|
|
|
|
|
|
|
|
const document = t.parse(idl);
|
|
|
|
const Foo = (document.root.nested || {}).Foo as t.MessageDefinition;
|
|
|
|
const extensionConfigs = Object.values(Foo.fields).map(
|
|
|
|
field => field.extensionConfig,
|
|
|
|
);
|
|
|
|
return expect(extensionConfigs).to.eql(expected);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should convert message field extensions using old rules', () => {
|
|
|
|
const idl = `
|
|
|
|
syntax = "proto3";
|
|
|
|
message Foo {
|
|
|
|
int32 k1 = 1 [(api_req).query = 'k1'];
|
|
|
|
int32 k2 = 2 [(api_req).body = 'k2'];
|
|
|
|
int32 k3 = 3 [(api_req).path = 'k3'];
|
|
|
|
int32 k4 = 4 [(api_req).header = 'k4'];
|
|
|
|
int32 k6 = 5 [(api_req).raw_body = 'key5'];
|
|
|
|
int32 k5 = 6 [(api_resp).header = 'key6'];
|
|
|
|
int32 k7 = 7 [(api_resp).http_code = 'key7'];
|
|
|
|
string k8 = 8 [(api_resp).body = 'k8'];
|
|
|
|
}
|
|
|
|
`;
|
|
|
|
|
|
|
|
const expected = [
|
|
|
|
{ position: 'query' },
|
|
|
|
{ position: 'body' },
|
|
|
|
{ position: 'path' },
|
|
|
|
{ position: 'header' },
|
|
|
|
{ position: 'raw_body', key: 'key5' },
|
|
|
|
{ position: 'header', key: 'key6' },
|
|
|
|
{},
|
|
|
|
{ position: 'body' },
|
|
|
|
];
|
|
|
|
|
|
|
|
const document = t.parse(idl);
|
|
|
|
const Foo = (document.root.nested || {}).Foo as t.MessageDefinition;
|
|
|
|
const extensionConfigs = Object.values(Foo.fields).map(
|
|
|
|
field => field.extensionConfig,
|
|
|
|
);
|
|
|
|
return expect(extensionConfigs).to.eql(expected);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should throw an error when using invalid type for a path parameter', () => {
|
|
|
|
const idl = `
|
|
|
|
syntax = "proto3";
|
|
|
|
message Foo {
|
|
|
|
bool k1 = 1 [(api.position) = "path"];
|
|
|
|
}
|
|
|
|
`;
|
|
|
|
|
|
|
|
try {
|
|
|
|
t.parse(idl);
|
|
|
|
} catch (err) {
|
|
|
|
const { message } = err;
|
|
|
|
const expected =
|
|
|
|
"the type of path parameter 'k1' in 'Foo' should be string or integer";
|
|
|
|
return expect(message).to.equal(expected);
|
|
|
|
}
|
|
|
|
|
|
|
|
return expect(true).to.equal(false);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|