Sync & Export support for ProtoDirectory (#3014)

This commit is contained in:
Opender Singh 2021-01-25 16:27:36 +13:00 committed by GitHub
parent 42ab4e4465
commit 1fe337dd2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 81 additions and 34 deletions

View File

@ -196,9 +196,13 @@ describe('export', () => {
parentId: w._id,
protoFileId: pf1._id,
});
const pd = await models.protoDirectory.create({
name: 'ProtoDirectory 1',
parentId: w._id,
});
const pf2 = await models.protoFile.create({
name: 'ProtoFile 2',
parentId: w._id,
parentId: pd._id,
});
const gr2 = await models.grpcRequest.create({
name: 'Grpc Request 2',
@ -248,12 +252,13 @@ describe('export', () => {
expect.objectContaining({ _id: r2._id }),
expect.objectContaining({ _id: ePub._id }),
expect.objectContaining({ _id: gr1._id }),
expect.objectContaining({ _id: pd._id }),
expect.objectContaining({ _id: pf1._id }),
expect.objectContaining({ _id: gr2._id }),
expect.objectContaining({ _id: pf2._id }),
]),
});
expect(exportWorkspacesDataJson.resources.length).toBe(12);
expect(exportWorkspacesDataJson.resources.length).toBe(13);
// Test export some requests only.
const exportRequestsJson = await importUtil.exportRequestsData([r1, gr1], false, 'json');
@ -278,8 +283,8 @@ describe('export', () => {
]),
});
expect(exportRequestsDataJSON.resources.length).toBe(9);
expect(exportRequestsDataYAML.resources.length).toBe(9);
expect(exportRequestsDataJSON.resources.length).toBe(10);
expect(exportRequestsDataYAML.resources.length).toBe(10);
// Ensure JSON and YAML are the same
expect(exportRequestsDataJSON.resources).toEqual(exportRequestsDataYAML.resources);
@ -291,10 +296,18 @@ describe('export', () => {
contents: 'openapi: "3.0.0"',
});
const jar = await models.cookieJar.getOrCreateForParentId(w._id);
const pd = await models.protoDirectory.create({
name: 'ProtoDirectory 1',
parentId: w._id,
});
const pf1 = await models.protoFile.create({
name: 'ProtoFile 1',
parentId: w._id,
});
const pf2 = await models.protoFile.create({
name: 'ProtoFile 2',
parentId: pd._id,
});
const r1 = await models.request.create({
name: 'Request 1',
parentId: w._id,
@ -315,7 +328,7 @@ describe('export', () => {
const gr2 = await models.grpcRequest.create({
name: 'Grpc Request 2',
parentId: f2._id,
protoFileId: pf1._id,
protoFileId: pf2._id,
});
const uts1 = await models.unitTestSuite.create({
name: 'Unit Test Suite One',
@ -347,7 +360,9 @@ describe('export', () => {
expect.objectContaining({ _id: w._id }),
expect.objectContaining({ _id: eBase._id }),
expect.objectContaining({ _id: jar._id }),
expect.objectContaining({ _id: pd._id }),
expect.objectContaining({ _id: pf1._id }),
expect.objectContaining({ _id: pf2._id }),
expect.objectContaining({ _id: r1._id }),
expect.objectContaining({ _id: r2._id }),
expect.objectContaining({ _id: gr1._id }),

View File

@ -1,5 +1,6 @@
import * as misc from '../misc';
import { globalBeforeEach } from '../../__jest__/before-each';
import { pluralize } from '../misc';
describe('hasAuthHeader()', () => {
beforeEach(globalBeforeEach);
@ -202,3 +203,17 @@ describe('chunkArray()', () => {
expect(chunks).toEqual([[1, 2]]);
});
});
describe('pluralize()', () => {
it('should not change pluralization', () => {
expect(pluralize('Requests')).toBe('Requests');
});
it('should end with s', () => {
expect(pluralize('Request')).toBe('Requests');
});
it('should end with ies', () => {
expect(pluralize('Directory')).toBe('Directories');
});
});

View File

@ -12,7 +12,14 @@ import fs from 'fs';
import { fnOrString, generateId } from './misc';
import YAML from 'yaml';
import { trackEvent } from './analytics';
import { isGrpcRequest, isProtoFile, isRequest, isRequestGroup } from '../models/helpers/is-model';
import {
isGrpcRequest,
isProtoDirectory,
isProtoFile,
isRequest,
isRequestGroup,
isWorkspace,
} from '../models/helpers/is-model';
const WORKSPACE_ID_KEY = '__WORKSPACE_ID__';
const BASE_ENVIRONMENT_ID_KEY = '__BASE_ENVIRONMENT_ID__';
@ -29,6 +36,7 @@ const EXPORT_TYPE_COOKIE_JAR = 'cookie_jar';
const EXPORT_TYPE_ENVIRONMENT = 'environment';
const EXPORT_TYPE_API_SPEC = 'api_spec';
const EXPORT_TYPE_PROTO_FILE = 'proto_file';
const EXPORT_TYPE_PROTO_DIRECTORY = 'proto_directory';
// If we come across an ID of this form, we will replace it with a new one
const REPLACE_ID_REGEX = /__\w+_\d+__/g;
@ -44,6 +52,7 @@ const MODELS = {
[EXPORT_TYPE_ENVIRONMENT]: models.environment,
[EXPORT_TYPE_API_SPEC]: models.apiSpec,
[EXPORT_TYPE_PROTO_FILE]: models.protoFile,
[EXPORT_TYPE_PROTO_DIRECTORY]: models.protoDirectory,
};
export type ImportResult = {
@ -236,7 +245,7 @@ export async function importRaw(
newDoc = await db.docCreate(model.type, resource);
// Mark as not seen if we created a new workspace from sync
if (newDoc.type === models.workspace.type) {
if (isWorkspace(newDoc)) {
const workspaceMeta = await models.workspaceMeta.getOrCreateByParentId(newDoc._id);
await models.workspaceMeta.update(workspaceMeta, { hasSeen: false });
}
@ -299,7 +308,7 @@ export async function exportRequestsHAR(
models.workspace.type,
models.requestGroup.type,
]);
const workspace = ancestors.find(ancestor => ancestor.type === models.workspace.type);
const workspace = ancestors.find(isWorkspace);
mapRequestIdToWorkspace[request._id] = workspace;
if (workspace == null || workspaceLookup.hasOwnProperty(workspace._id)) {
continue;
@ -376,7 +385,7 @@ export async function exportRequestsData(
}
mapTypeAndIdToDoc[key] = ancestor;
docs.push(ancestor);
if (ancestor.type === models.workspace.type) {
if (isWorkspace(ancestor)) {
workspaces.push(ancestor);
}
}
@ -391,7 +400,8 @@ export async function exportRequestsData(
d.type === models.apiSpec.type ||
d.type === models.unitTestSuite.type ||
d.type === models.unitTest.type ||
isProtoFile(d)
isProtoFile(d) ||
isProtoDirectory(d)
);
});
docs.push(...descendants);
@ -408,7 +418,8 @@ export async function exportRequestsData(
isGrpcRequest(d) ||
isRequestGroup(d) ||
isProtoFile(d) ||
d.type === models.workspace.type ||
isProtoDirectory(d) ||
isWorkspace(d) ||
d.type === models.cookieJar.type ||
d.type === models.environment.type ||
d.type === models.apiSpec.type
@ -420,7 +431,7 @@ export async function exportRequestsData(
return !(d: Object).isPrivate || includePrivateDocs;
})
.map((d: Object) => {
if (d.type === models.workspace.type) {
if (isWorkspace(d)) {
d._type = EXPORT_TYPE_WORKSPACE;
} else if (d.type === models.cookieJar.type) {
d._type = EXPORT_TYPE_COOKIE_JAR;
@ -438,6 +449,8 @@ export async function exportRequestsData(
d._type = EXPORT_TYPE_GRPC_REQUEST;
} else if (isProtoFile(d)) {
d._type = EXPORT_TYPE_PROTO_FILE;
} else if (isProtoDirectory(d)) {
d._type = EXPORT_TYPE_PROTO_DIRECTORY;
} else if (d.type === models.apiSpec.type) {
d._type = EXPORT_TYPE_API_SPEC;
}

View File

@ -377,3 +377,23 @@ export function chunkArray<T>(arr: Array<T>, chunkSize: number): Array<Array<T>>
export function setActivityAttribute(activity: GlobalActivity) {
document.body.setAttribute('data-activity', activity);
}
export function pluralize(text: string): string {
let trailer = 's';
let chop = 0;
// Things already ending with 's' stay that way
if (text.match(/s$/)) {
trailer = '';
chop = 0;
}
// Things ending in 'y' convert to ies
if (text.match(/y$/)) {
trailer = 'ies';
chop = 1;
}
// Add the trailer for pluralization
return `${text.slice(0, text.length - chop)}${trailer}`;
}

View File

@ -23,7 +23,7 @@ import * as _grpcRequest from './grpc-request';
import * as _grpcRequestMeta from './grpc-request-meta';
import * as _workspace from './workspace';
import * as _workspaceMeta from './workspace-meta';
import { generateId } from '../common/misc';
import { generateId, pluralize } from '../common/misc';
export type BaseModel = {
_id: string,
@ -130,11 +130,8 @@ export function getModelName(type: string, count: number = 1) {
return 'Unknown';
} else if (count === 1) {
return model.name;
} else if (!model.name.match(/s$/)) {
// Add an 's' if it doesn't already end in one
return `${model.name}s`;
} else {
return model.name;
return pluralize(model.name);
}
}

View File

@ -36,6 +36,7 @@ describe('NeDBPlugin', () => {
models.apiSpec.type,
models.environment.type,
models.grpcRequest.type,
models.protoDirectory.type,
models.protoFile.type,
models.request.type,
models.requestGroup.type,

View File

@ -125,6 +125,7 @@ export default class NeDBPlugin {
models.unitTest.type,
models.grpcRequest.type,
models.protoFile.type,
models.protoDirectory.type,
];
} else if (type !== null && id === null) {
const workspace = await db.get(models.workspace.type, this._workspaceId);

View File

@ -1,6 +1,7 @@
import clone from 'clone';
import * as db from '../../../common/database';
import * as models from '../../../models';
import { pluralize } from '../../../common/misc';
const ENTITY_CHANGES = 'entities/changes';
const ENTITY_INITIALIZE = 'entities/initialize';
@ -10,26 +11,10 @@ const ENTITY_INITIALIZE = 'entities/initialize';
// ~~~~~~~~ //
function getReducerName(type) {
let trailer = 's';
let chop = 0;
// Things already ending with 's' stay that way
if (type.match(/s$/)) {
trailer = '';
chop = 0;
}
// Things ending in 'y' convert to ies
if (type.match(/y$/)) {
trailer = 'ies';
chop = 1;
}
// Lowercase first letter (camel case)
const lowerFirstLetter = `${type.slice(0, 1).toLowerCase()}${type.slice(1)}`;
// Add the trailer for pluralization
return `${lowerFirstLetter.slice(0, lowerFirstLetter.length - chop)}${trailer}`;
return pluralize(lowerFirstLetter);
}
const initialState = {};