mirror of
https://github.com/Kong/insomnia
synced 2024-11-07 22:30:15 +00:00
unifies getting of workspace name in displayment (#4060)
This commit is contained in:
parent
615287ccfc
commit
e793e6f166
@ -1,19 +0,0 @@
|
||||
import * as models from '../../../models';
|
||||
import { WorkspaceScopeKeys } from '../../workspace';
|
||||
import getWorkspaceName from '../get-workspace-name';
|
||||
|
||||
describe('getWorkspaceName', () => {
|
||||
it('returns workspace name', () => {
|
||||
const w = models.workspace.init();
|
||||
const s = models.apiSpec.init();
|
||||
w.scope = WorkspaceScopeKeys.collection;
|
||||
expect(getWorkspaceName(w, s)).toBe(w.name);
|
||||
});
|
||||
|
||||
it('returns api spec name', () => {
|
||||
const w = models.workspace.init();
|
||||
const s = models.apiSpec.init();
|
||||
w.scope = WorkspaceScopeKeys.design;
|
||||
expect(getWorkspaceName(w, s)).toBe(s.fileName);
|
||||
});
|
||||
});
|
@ -1,6 +0,0 @@
|
||||
import type { ApiSpec } from '../api-spec';
|
||||
import { isDesign, Workspace } from '../workspace';
|
||||
|
||||
export default function getWorkspaceName(w: Workspace, s: ApiSpec) {
|
||||
return isDesign(w) ? s.fileName : w.name;
|
||||
}
|
@ -3,20 +3,23 @@ import type { ApiSpec } from '../api-spec';
|
||||
import * as models from '../index';
|
||||
import { isDesign, Workspace } from '../workspace';
|
||||
|
||||
export async function rename(w: Workspace, s: ApiSpec, name: string) {
|
||||
if (isDesign(w)) {
|
||||
await models.apiSpec.update(s, {
|
||||
export async function rename(workspace: Workspace, apiSpec: ApiSpec, name: string) {
|
||||
if (isDesign(workspace)) {
|
||||
await models.apiSpec.update(apiSpec, {
|
||||
fileName: name,
|
||||
});
|
||||
} else {
|
||||
await models.workspace.update(w, {
|
||||
await models.workspace.update(workspace, {
|
||||
name,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function duplicate(w: Workspace, { name, parentId }: Pick<Workspace, 'name' | 'parentId'>) {
|
||||
const newWorkspace = await db.duplicate(w, {
|
||||
export async function duplicate(
|
||||
workspace: Workspace,
|
||||
{ name, parentId }: Pick<Workspace, 'name' | 'parentId'>,
|
||||
) {
|
||||
const newWorkspace = await db.duplicate(workspace, {
|
||||
name,
|
||||
parentId,
|
||||
});
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { SvgIcon } from 'insomnia-components';
|
||||
import React, { FC, useCallback, useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { parseApiSpec } from '../../../common/api-specs';
|
||||
import { getWorkspaceLabel } from '../../../common/get-workspace-label';
|
||||
import { RENDER_PURPOSE_NO_RENDER } from '../../../common/render';
|
||||
import * as models from '../../../models';
|
||||
import type { ApiSpec } from '../../../models/api-spec';
|
||||
import getWorkspaceName from '../../../models/helpers/get-workspace-name';
|
||||
import * as workspaceOperations from '../../../models/helpers/workspace-operations';
|
||||
import { Project } from '../../../models/project';
|
||||
import type { Workspace } from '../../../models/workspace';
|
||||
@ -15,6 +15,7 @@ import type { DocumentAction } from '../../../plugins';
|
||||
import { getDocumentActions } from '../../../plugins';
|
||||
import * as pluginContexts from '../../../plugins/context';
|
||||
import { useLoadingRecord } from '../../hooks/use-loading-record';
|
||||
import { selectActiveWorkspaceName } from '../../redux/selectors';
|
||||
import { Dropdown } from '../base/dropdown/dropdown';
|
||||
import { DropdownButton } from '../base/dropdown/dropdown-button';
|
||||
import { DropdownDivider } from '../base/dropdown/dropdown-divider';
|
||||
@ -33,13 +34,15 @@ const spinner = <i className="fa fa-refresh fa-spin" />;
|
||||
|
||||
const useWorkspaceHandlers = ({ workspace, apiSpec }: Props) => {
|
||||
const handleDuplicate = useCallback(() => {
|
||||
showWorkspaceDuplicateModal({ workspace, apiSpec });
|
||||
}, [apiSpec, workspace]);
|
||||
showWorkspaceDuplicateModal({ workspace });
|
||||
}, [workspace]);
|
||||
|
||||
const activeWorkspaceName = useSelector(selectActiveWorkspaceName);
|
||||
|
||||
const handleRename = useCallback(() => {
|
||||
showPrompt({
|
||||
title: `Rename ${getWorkspaceLabel(workspace).singular}`,
|
||||
defaultValue: getWorkspaceName(workspace, apiSpec),
|
||||
defaultValue: activeWorkspaceName,
|
||||
submitName: 'Rename',
|
||||
selectText: true,
|
||||
label: 'Name',
|
||||
@ -47,13 +50,13 @@ const useWorkspaceHandlers = ({ workspace, apiSpec }: Props) => {
|
||||
await workspaceOperations.rename(workspace, apiSpec, name);
|
||||
},
|
||||
});
|
||||
}, [apiSpec, workspace]);
|
||||
}, [apiSpec, workspace, activeWorkspaceName]);
|
||||
|
||||
const handleDelete = useCallback(() => {
|
||||
const label = getWorkspaceLabel(workspace);
|
||||
showModal(AskModal, {
|
||||
title: `Delete ${label.singular}`,
|
||||
message: `Do you really want to delete "${getWorkspaceName(workspace, apiSpec)}"?`,
|
||||
message: `Do you really want to delete "${activeWorkspaceName}"?`,
|
||||
yesText: 'Yes',
|
||||
noText: 'Cancel',
|
||||
onDone: async (isYes: boolean) => {
|
||||
@ -65,7 +68,7 @@ const useWorkspaceHandlers = ({ workspace, apiSpec }: Props) => {
|
||||
await models.workspace.remove(workspace);
|
||||
},
|
||||
});
|
||||
}, [apiSpec, workspace]);
|
||||
}, [workspace, activeWorkspaceName]);
|
||||
|
||||
return { handleDelete, handleDuplicate, handleRename };
|
||||
};
|
||||
|
@ -30,9 +30,9 @@ import { SettingsModal, TAB_INDEX_EXPORT } from '../modals/settings-modal';
|
||||
import { WorkspaceSettingsModal } from '../modals/workspace-settings-modal';
|
||||
|
||||
interface Props {
|
||||
displayName: string;
|
||||
activeEnvironment: Environment | null;
|
||||
activeWorkspace: Workspace;
|
||||
activeWorkspaceName: string;
|
||||
activeApiSpec: ApiSpec;
|
||||
activeProject: Project;
|
||||
hotKeyRegistry: HotKeyRegistry;
|
||||
@ -131,7 +131,7 @@ export class WorkspaceDropdown extends PureComponent<Props, State> {
|
||||
|
||||
render() {
|
||||
const {
|
||||
displayName,
|
||||
activeWorkspaceName,
|
||||
className,
|
||||
activeWorkspace,
|
||||
isLoading,
|
||||
@ -157,9 +157,9 @@ export class WorkspaceDropdown extends PureComponent<Props, State> {
|
||||
style={{
|
||||
maxWidth: '400px',
|
||||
}}
|
||||
title={displayName}
|
||||
title={activeWorkspaceName}
|
||||
>
|
||||
{displayName}
|
||||
{activeWorkspaceName}
|
||||
</div>
|
||||
<i className="fa fa-caret-down space-left" />
|
||||
{isLoading ? <i className="fa fa-refresh fa-spin space-left" /> : null}
|
||||
|
@ -8,15 +8,13 @@ import { AUTOBIND_CFG } from '../../../common/constants';
|
||||
import { getWorkspaceLabel } from '../../../common/get-workspace-label';
|
||||
import { strings } from '../../../common/strings';
|
||||
import * as models from '../../../models';
|
||||
import { ApiSpec } from '../../../models/api-spec';
|
||||
import getWorkspaceName from '../../../models/helpers/get-workspace-name';
|
||||
import * as workspaceOperations from '../../../models/helpers/workspace-operations';
|
||||
import { isDefaultProject, isLocalProject, isRemoteProject, Project } from '../../../models/project';
|
||||
import { Workspace } from '../../../models/workspace';
|
||||
import { initializeLocalBackendProjectAndMarkForSync } from '../../../sync/vcs/initialize-backend-project';
|
||||
import { VCS } from '../../../sync/vcs/vcs';
|
||||
import { activateWorkspace } from '../../redux/modules/workspace';
|
||||
import { selectActiveProject, selectIsLoggedIn, selectProjects } from '../../redux/selectors';
|
||||
import { selectActiveProject, selectActiveWorkspaceName, selectIsLoggedIn, selectProjects } from '../../redux/selectors';
|
||||
import { Modal } from '../base/modal';
|
||||
import { ModalBody } from '../base/modal-body';
|
||||
import { ModalFooter } from '../base/modal-footer';
|
||||
@ -25,7 +23,6 @@ import { showModal } from '.';
|
||||
|
||||
interface Options {
|
||||
workspace: Workspace;
|
||||
apiSpec: ApiSpec;
|
||||
onDone?: () => void;
|
||||
}
|
||||
|
||||
@ -44,7 +41,7 @@ const ProjectOption: FC<Project> = project => (
|
||||
</option>
|
||||
);
|
||||
|
||||
const WorkspaceDuplicateModalInternalWithRef: ForwardRefRenderFunction<Modal, InnerProps> = ({ workspace, apiSpec, onDone, hide, vcs }, ref) => {
|
||||
const WorkspaceDuplicateModalInternalWithRef: ForwardRefRenderFunction<Modal, InnerProps> = ({ workspace, onDone, hide, vcs }, ref) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const projects = useSelector(selectProjects);
|
||||
@ -52,7 +49,7 @@ const WorkspaceDuplicateModalInternalWithRef: ForwardRefRenderFunction<Modal, In
|
||||
const isLoggedIn = useSelector(selectIsLoggedIn);
|
||||
|
||||
const title = `Duplicate ${getWorkspaceLabel(workspace).singular}`;
|
||||
const defaultWorkspaceName = getWorkspaceName(workspace, apiSpec);
|
||||
const activeWorkspaceName = useSelector(selectActiveWorkspaceName);
|
||||
|
||||
const {
|
||||
register,
|
||||
@ -62,7 +59,7 @@ const WorkspaceDuplicateModalInternalWithRef: ForwardRefRenderFunction<Modal, In
|
||||
errors,
|
||||
} } = useForm<FormFields>({
|
||||
defaultValues: {
|
||||
newName: defaultWorkspaceName,
|
||||
newName: activeWorkspaceName,
|
||||
projectId: activeProject._id,
|
||||
},
|
||||
});
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { autoBindMethodsForReact } from 'class-autobind-decorator';
|
||||
import React, { FC, PureComponent, ReactNode } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Tab, TabList, TabPanel, Tabs } from 'react-tabs';
|
||||
import styled from 'styled-components';
|
||||
|
||||
@ -8,10 +9,11 @@ import { getWorkspaceLabel } from '../../../common/get-workspace-label';
|
||||
import { HandleGetRenderContext, HandleRender } from '../../../common/render';
|
||||
import type { ApiSpec } from '../../../models/api-spec';
|
||||
import type { ClientCertificate } from '../../../models/client-certificate';
|
||||
import getWorkspaceName from '../../../models/helpers/get-workspace-name';
|
||||
import * as workspaceOperations from '../../../models/helpers/workspace-operations';
|
||||
import * as models from '../../../models/index';
|
||||
import type { Workspace } from '../../../models/workspace';
|
||||
import { RootState } from '../../redux/modules';
|
||||
import { selectActiveWorkspaceName } from '../../redux/selectors';
|
||||
import { DebouncedInput } from '../base/debounced-input';
|
||||
import { FileInputButton } from '../base/file-input-button';
|
||||
import { Modal } from '../base/modal';
|
||||
@ -58,7 +60,9 @@ const CertificateField: FC<{
|
||||
);
|
||||
};
|
||||
|
||||
interface Props {
|
||||
type ReduxProps = ReturnType<typeof mapStateToProps>;
|
||||
|
||||
interface Props extends ReduxProps {
|
||||
clientCertificates: ClientCertificate[];
|
||||
workspace: Workspace;
|
||||
apiSpec: ApiSpec;
|
||||
@ -87,7 +91,7 @@ interface State {
|
||||
}
|
||||
|
||||
@autoBindMethodsForReact(AUTOBIND_CFG)
|
||||
export class WorkspaceSettingsModal extends PureComponent<Props, State> {
|
||||
export class UnconnectedWorkspaceSettingsModal extends PureComponent<Props, State> {
|
||||
modal: Modal | null = null;
|
||||
|
||||
state: State = {
|
||||
@ -127,8 +131,8 @@ export class WorkspaceSettingsModal extends PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
_handleDuplicateWorkspace() {
|
||||
const { workspace, apiSpec } = this.props;
|
||||
showWorkspaceDuplicateModal({ workspace, apiSpec, onDone: this.hide });
|
||||
const { workspace } = this.props;
|
||||
showWorkspaceDuplicateModal({ workspace, onDone: this.hide });
|
||||
}
|
||||
|
||||
_handleToggleCertificateForm() {
|
||||
@ -292,7 +296,7 @@ export class WorkspaceSettingsModal extends PureComponent<Props, State> {
|
||||
const {
|
||||
clientCertificates,
|
||||
workspace,
|
||||
apiSpec,
|
||||
activeWorkspaceName,
|
||||
editorLineWrapping,
|
||||
editorFontSize,
|
||||
editorIndentSize,
|
||||
@ -333,7 +337,7 @@ export class WorkspaceSettingsModal extends PureComponent<Props, State> {
|
||||
type="text"
|
||||
delay={500}
|
||||
placeholder="Awesome API"
|
||||
defaultValue={getWorkspaceName(workspace, apiSpec)}
|
||||
defaultValue={activeWorkspaceName}
|
||||
onChange={this._handleRename}
|
||||
/>
|
||||
</label>
|
||||
@ -539,3 +543,9 @@ export class WorkspaceSettingsModal extends PureComponent<Props, State> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: RootState) => ({
|
||||
activeWorkspaceName: selectActiveWorkspaceName(state),
|
||||
});
|
||||
|
||||
export const WorkspaceSettingsModal = connect(mapStateToProps, null, null, { forwardRef: true })(UnconnectedWorkspaceSettingsModal);
|
||||
|
@ -8,7 +8,7 @@ import { getWorkspaceLabel } from '../../../common/get-workspace-label';
|
||||
import { strings } from '../../../common/strings';
|
||||
import { exportAllToFile } from '../../redux/modules/global';
|
||||
import { importClipBoard, importFile, importUri } from '../../redux/modules/import';
|
||||
import { selectActiveProjectName, selectActiveWorkspace } from '../../redux/selectors';
|
||||
import { selectActiveProjectName, selectActiveWorkspace, selectActiveWorkspaceName } from '../../redux/selectors';
|
||||
import { Dropdown } from '../base/dropdown/dropdown';
|
||||
import { DropdownButton } from '../base/dropdown/dropdown-button';
|
||||
import { DropdownDivider } from '../base/dropdown/dropdown-divider';
|
||||
@ -64,6 +64,8 @@ export const ImportExport: FC<Props> = ({ hideSettingsModal }) => {
|
||||
hideSettingsModal();
|
||||
}, [hideSettingsModal, activeWorkspace, dispatch]);
|
||||
|
||||
const activeWorkspaceName = useSelector(selectActiveWorkspaceName);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="no-margin-top">
|
||||
@ -83,7 +85,7 @@ export const ImportExport: FC<Props> = ({ hideSettingsModal }) => {
|
||||
<DropdownDivider>Choose Export Type</DropdownDivider>
|
||||
{activeWorkspace && <DropdownItem onClick={showExportRequestsModal}>
|
||||
<i className="fa fa-home" />
|
||||
Export the "{activeWorkspace.name}" {getWorkspaceLabel(activeWorkspace).singular}
|
||||
Export the "{activeWorkspaceName}" {getWorkspaceLabel(activeWorkspace).singular}
|
||||
</DropdownItem>}
|
||||
<DropdownItem onClick={handleExportAllToFile}>
|
||||
<i className="fa fa-empty" />
|
||||
|
@ -3,7 +3,7 @@ import React, { Fragment, FunctionComponent, ReactNode, useCallback } from 'reac
|
||||
|
||||
import { ACTIVITY_HOME, GlobalActivity } from '../../common/constants';
|
||||
import { strings } from '../../common/strings';
|
||||
import { isCollection, isDesign } from '../../models/workspace';
|
||||
import { isDesign } from '../../models/workspace';
|
||||
import coreLogo from '../images/insomnia-core-logo.png';
|
||||
import { ActivityToggle } from './activity-toggle';
|
||||
import SettingsButton from './buttons/settings-button';
|
||||
@ -23,6 +23,7 @@ export const WorkspacePageHeader: FunctionComponent<Props> = ({
|
||||
wrapperProps: {
|
||||
activeApiSpec,
|
||||
activeWorkspace,
|
||||
activeWorkspaceName,
|
||||
activeProject,
|
||||
activeEnvironment,
|
||||
settings,
|
||||
@ -35,18 +36,15 @@ export const WorkspacePageHeader: FunctionComponent<Props> = ({
|
||||
[activeWorkspace, handleActivityChange],
|
||||
);
|
||||
|
||||
if (!activeWorkspace || !activeApiSpec || !activity) {
|
||||
if (!activeWorkspace || !activeWorkspaceName || !activeApiSpec || !activity) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const collection = isCollection(activeWorkspace);
|
||||
const design = isDesign(activeWorkspace);
|
||||
|
||||
const workspace = (
|
||||
<WorkspaceDropdown
|
||||
displayName={collection ? activeWorkspace.name : activeApiSpec.fileName}
|
||||
activeEnvironment={activeEnvironment}
|
||||
activeWorkspace={activeWorkspace}
|
||||
activeWorkspaceName={activeWorkspaceName}
|
||||
activeApiSpec={activeApiSpec}
|
||||
activeProject={activeProject}
|
||||
hotKeyRegistry={settings.hotKeyRegistry}
|
||||
@ -69,7 +67,7 @@ export const WorkspacePageHeader: FunctionComponent<Props> = ({
|
||||
</Fragment>
|
||||
}
|
||||
gridCenter={
|
||||
design && (
|
||||
isDesign(activeWorkspace) && (
|
||||
<ActivityToggle
|
||||
activity={activity}
|
||||
handleActivityChange={handleActivityChange}
|
||||
|
@ -52,7 +52,7 @@ import { Request, updateMimeType } from '../../models/request';
|
||||
import { isRequestGroup, RequestGroup } from '../../models/request-group';
|
||||
import { RequestMeta } from '../../models/request-meta';
|
||||
import { Response } from '../../models/response';
|
||||
import { isCollection, isWorkspace } from '../../models/workspace';
|
||||
import { isWorkspace } from '../../models/workspace';
|
||||
import { WorkspaceMeta } from '../../models/workspace-meta';
|
||||
import * as network from '../../network/network';
|
||||
import * as plugins from '../../plugins';
|
||||
@ -97,6 +97,7 @@ import {
|
||||
} from '../redux/modules/global';
|
||||
import { importUri } from '../redux/modules/import';
|
||||
import {
|
||||
selectActiveApiSpec,
|
||||
selectActiveCookieJar,
|
||||
selectActiveEnvironment,
|
||||
selectActiveGitRepository,
|
||||
@ -113,6 +114,7 @@ import {
|
||||
selectActiveWorkspace,
|
||||
selectActiveWorkspaceClientCertificates,
|
||||
selectActiveWorkspaceMeta,
|
||||
selectActiveWorkspaceName,
|
||||
selectEntitiesLists,
|
||||
selectSettings,
|
||||
selectSyncItems,
|
||||
@ -1094,7 +1096,7 @@ class App extends PureComponent<AppProps, State> {
|
||||
const {
|
||||
activeWorkspace,
|
||||
activeProject,
|
||||
activeApiSpec,
|
||||
activeWorkspaceName,
|
||||
activeEnvironment,
|
||||
activeRequest,
|
||||
activity,
|
||||
@ -1103,9 +1105,9 @@ class App extends PureComponent<AppProps, State> {
|
||||
|
||||
if (activity === ACTIVITY_HOME || activity === ACTIVITY_MIGRATION) {
|
||||
title = getAppName();
|
||||
} else if (activeWorkspace && activeApiSpec) {
|
||||
} else if (activeWorkspace && activeWorkspaceName) {
|
||||
title = activeProject.name;
|
||||
title += ` - ${isCollection(activeWorkspace) ? activeWorkspace.name : activeApiSpec.fileName}`;
|
||||
title += ` - ${activeWorkspaceName}`;
|
||||
|
||||
if (activeEnvironment) {
|
||||
title += ` (${activeEnvironment.name})`;
|
||||
@ -1590,6 +1592,7 @@ function mapStateToProps(state: RootState) {
|
||||
const workspaces = selectWorkspacesForActiveProject(state);
|
||||
const activeWorkspaceMeta = selectActiveWorkspaceMeta(state);
|
||||
const activeWorkspace = selectActiveWorkspace(state);
|
||||
const activeWorkspaceName = selectActiveWorkspaceName(state);
|
||||
const activeWorkspaceClientCertificates = selectActiveWorkspaceClientCertificates(state);
|
||||
const activeGitRepository = selectActiveGitRepository(state);
|
||||
|
||||
@ -1631,7 +1634,7 @@ function mapStateToProps(state: RootState) {
|
||||
const syncItems = selectSyncItems(state);
|
||||
|
||||
// Api spec stuff
|
||||
const activeApiSpec = apiSpecs.find(s => s.parentId === activeWorkspace?._id);
|
||||
const activeApiSpec = selectActiveApiSpec(state);
|
||||
|
||||
// Test stuff
|
||||
const activeUnitTests = selectActiveUnitTests(state);
|
||||
@ -1643,6 +1646,7 @@ function mapStateToProps(state: RootState) {
|
||||
activity: activeActivity,
|
||||
activeProject,
|
||||
activeApiSpec,
|
||||
activeWorkspaceName,
|
||||
activeCookieJar,
|
||||
activeEnvironment,
|
||||
activeGitRepository,
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { globalBeforeEach } from '../../../__jest__/before-each';
|
||||
import { reduxStateForTest } from '../../../__jest__/redux-state-for-test';
|
||||
import { ACTIVITY_DEBUG } from '../../../common/constants';
|
||||
import * as models from '../../../models';
|
||||
import { DEFAULT_PROJECT_ID, Project } from '../../../models/project';
|
||||
import { selectActiveProject } from '../selectors';
|
||||
import { WorkspaceScopeKeys } from '../../../models/workspace';
|
||||
import { selectActiveApiSpec, selectActiveProject, selectActiveWorkspaceName } from '../selectors';
|
||||
|
||||
describe('selectors', () => {
|
||||
beforeEach(globalBeforeEach);
|
||||
@ -44,4 +46,98 @@ describe('selectors', () => {
|
||||
expect(project).toStrictEqual(expect.objectContaining<Partial<Project>>({ _id: DEFAULT_PROJECT_ID }));
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectActiveApiSpec', () => {
|
||||
it('will return undefined when there is not an active workspace', async () => {
|
||||
const state = await reduxStateForTest({
|
||||
activeWorkspaceId: null,
|
||||
});
|
||||
|
||||
expect(selectActiveApiSpec(state)).toBe(undefined);
|
||||
});
|
||||
|
||||
it('will return throw when there is not an active apiSpec', async () => {
|
||||
const workspace = await models.workspace.create({
|
||||
name: 'workspace.name',
|
||||
scope: WorkspaceScopeKeys.design,
|
||||
});
|
||||
|
||||
const state = await reduxStateForTest({
|
||||
activeActivity: ACTIVITY_DEBUG,
|
||||
activeWorkspaceId: workspace._id,
|
||||
});
|
||||
state.entities.apiSpecs = {};
|
||||
|
||||
const execute = () => selectActiveApiSpec(state);
|
||||
expect(execute).toThrowError(`an api spec not found for the workspace ${workspace._id} (workspace.name)`);
|
||||
});
|
||||
|
||||
it('will return the apiSpec for a given workspace', async () => {
|
||||
const workspace = await models.workspace.create({
|
||||
name: 'workspace.name',
|
||||
scope: WorkspaceScopeKeys.design,
|
||||
});
|
||||
const spec = await models.apiSpec.updateOrCreateForParentId(
|
||||
workspace._id,
|
||||
{ fileName: 'apiSpec.fileName' },
|
||||
);
|
||||
|
||||
const state = await reduxStateForTest({
|
||||
activeActivity: ACTIVITY_DEBUG,
|
||||
activeWorkspaceId: workspace._id,
|
||||
});
|
||||
|
||||
expect(selectActiveApiSpec(state)).toEqual(spec);
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectActiveWorkspaceName', () => {
|
||||
it('returns workspace name for collections', async () => {
|
||||
const workspace = await models.workspace.create({
|
||||
name: 'workspace.name',
|
||||
scope: WorkspaceScopeKeys.collection,
|
||||
});
|
||||
// even though this shouldn't technically happen, we want to make sure the selector still makes the right decision (and ignores the api spec for collections)
|
||||
await models.apiSpec.updateOrCreateForParentId(
|
||||
workspace._id,
|
||||
{ fileName: 'apiSpec.fileName' },
|
||||
);
|
||||
const state = await reduxStateForTest({
|
||||
activeActivity: ACTIVITY_DEBUG,
|
||||
activeWorkspaceId: workspace._id,
|
||||
});
|
||||
|
||||
expect(selectActiveWorkspaceName(state)).toBe('workspace.name');
|
||||
});
|
||||
|
||||
it('returns api spec name for design documents', async () => {
|
||||
const workspace = await models.workspace.create({
|
||||
name: 'workspace.name',
|
||||
scope: WorkspaceScopeKeys.design,
|
||||
});
|
||||
await models.apiSpec.updateOrCreateForParentId(
|
||||
workspace._id,
|
||||
{ fileName: 'apiSpec.fileName' },
|
||||
);
|
||||
const state = await reduxStateForTest({
|
||||
activeActivity: ACTIVITY_DEBUG,
|
||||
activeWorkspaceId: workspace._id,
|
||||
});
|
||||
|
||||
expect(selectActiveWorkspaceName(state)).toBe('apiSpec.fileName');
|
||||
});
|
||||
|
||||
it('returns undefined when there is not an active workspace', async () => {
|
||||
await models.workspace.create({
|
||||
name: 'workspace.name',
|
||||
scope: WorkspaceScopeKeys.collection,
|
||||
});
|
||||
const state = await reduxStateForTest({
|
||||
activeActivity: ACTIVITY_DEBUG,
|
||||
activeWorkspaceId: null,
|
||||
});
|
||||
|
||||
expect(selectActiveWorkspaceName(state)).toBe(undefined);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -10,6 +10,7 @@ import { DEFAULT_PROJECT_ID, isRemoteProject } from '../../models/project';
|
||||
import { isRequest, Request } from '../../models/request';
|
||||
import { isRequestGroup, RequestGroup } from '../../models/request-group';
|
||||
import { UnitTestResult } from '../../models/unit-test-result';
|
||||
import { isCollection } from '../../models/workspace';
|
||||
import { RootState } from './modules';
|
||||
|
||||
type EntitiesLists = {
|
||||
@ -100,15 +101,10 @@ export const selectAllWorkspaces = createSelector(
|
||||
entities => entities.workspaces,
|
||||
);
|
||||
|
||||
export const selectAllApiSpecs = createSelector(
|
||||
selectEntitiesLists,
|
||||
entities => entities.apiSpecs,
|
||||
);
|
||||
|
||||
export const selectWorkspacesForActiveProject = createSelector(
|
||||
selectAllWorkspaces,
|
||||
selectActiveProject,
|
||||
(workspaces, activeProject) => workspaces.filter(w => w.parentId === activeProject._id),
|
||||
(workspaces, activeProject) => workspaces.filter(workspace => workspace.parentId === activeProject._id),
|
||||
);
|
||||
|
||||
export const selectActiveWorkspace = createSelector(
|
||||
@ -118,7 +114,7 @@ export const selectActiveWorkspace = createSelector(
|
||||
(workspaces, activeWorkspaceId, activeActivity) => {
|
||||
// Only return an active workspace if we're in an activity
|
||||
if (activeActivity && isWorkspaceActivity(activeActivity)) {
|
||||
const workspace = workspaces.find(w => w._id === activeWorkspaceId);
|
||||
const workspace = workspaces.find(workspace => workspace._id === activeWorkspaceId);
|
||||
return workspace;
|
||||
}
|
||||
|
||||
@ -135,6 +131,43 @@ export const selectActiveWorkspaceMeta = createSelector(
|
||||
},
|
||||
);
|
||||
|
||||
export const selectAllApiSpecs = createSelector(
|
||||
selectEntitiesLists,
|
||||
entities => entities.apiSpecs,
|
||||
);
|
||||
|
||||
export const selectActiveApiSpec = createSelector(
|
||||
selectAllApiSpecs,
|
||||
selectActiveWorkspace,
|
||||
(apiSpecs, activeWorkspace) => {
|
||||
if (!activeWorkspace) {
|
||||
// There should never be an active api spec without an active workspace
|
||||
return undefined;
|
||||
}
|
||||
const activeSpec = apiSpecs.find(apiSpec => apiSpec.parentId === activeWorkspace._id);
|
||||
|
||||
if (!activeSpec) {
|
||||
// This case should never be reached; an api spec should always exist for a given workspace.
|
||||
throw new Error(`an api spec not found for the workspace ${activeWorkspace._id} (${activeWorkspace.name})`);
|
||||
}
|
||||
|
||||
return activeSpec;
|
||||
}
|
||||
);
|
||||
|
||||
export const selectActiveWorkspaceName = createSelector(
|
||||
selectActiveWorkspace,
|
||||
selectActiveApiSpec,
|
||||
(activeWorkspace, activeApiSpec) => {
|
||||
if (!activeWorkspace) {
|
||||
// see above, but since the selectActiveWorkspace selector really can return undefined, we need to handle it here.
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return isCollection(activeWorkspace) ? activeWorkspace.name : activeApiSpec?.fileName;
|
||||
}
|
||||
);
|
||||
|
||||
export const selectActiveEnvironment = createSelector(
|
||||
selectActiveWorkspaceMeta,
|
||||
selectEntitiesLists,
|
||||
|
Loading…
Reference in New Issue
Block a user