mirror of
https://github.com/Kong/insomnia.git
synced 2026-04-21 06:37:36 -04:00
removes insomnia designer migration code (#4404)
This commit is contained in:
committed by
GitHub
parent
48ac330d95
commit
4940348dd9
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
ACTIVITY_DEBUG,
|
||||
ACTIVITY_HOME,
|
||||
ACTIVITY_MIGRATION,
|
||||
ACTIVITY_SPEC,
|
||||
ACTIVITY_UNIT_TEST,
|
||||
FLEXIBLE_URL_REGEX,
|
||||
@@ -43,7 +42,6 @@ describe('isWorkspaceActivity', () => {
|
||||
|
||||
it('should return false', () => {
|
||||
expect(isWorkspaceActivity(ACTIVITY_HOME)).toBe(false);
|
||||
expect(isWorkspaceActivity(ACTIVITY_MIGRATION)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -53,7 +51,6 @@ describe('isValidActivity', () => {
|
||||
expect(isValidActivity(ACTIVITY_DEBUG)).toBe(true);
|
||||
expect(isValidActivity(ACTIVITY_UNIT_TEST)).toBe(true);
|
||||
expect(isValidActivity(ACTIVITY_HOME)).toBe(true);
|
||||
expect(isValidActivity(ACTIVITY_MIGRATION)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false', () => {
|
||||
|
||||
@@ -159,13 +159,11 @@ export type GlobalActivity =
|
||||
| 'spec'
|
||||
| 'debug'
|
||||
| 'unittest'
|
||||
| 'home'
|
||||
| 'migration';
|
||||
| 'home';
|
||||
export const ACTIVITY_SPEC: GlobalActivity = 'spec';
|
||||
export const ACTIVITY_DEBUG: GlobalActivity = 'debug';
|
||||
export const ACTIVITY_UNIT_TEST: GlobalActivity = 'unittest';
|
||||
export const ACTIVITY_HOME: GlobalActivity = 'home';
|
||||
export const ACTIVITY_MIGRATION: GlobalActivity = 'migration';
|
||||
|
||||
export const isWorkspaceActivity = (activity?: string): activity is GlobalActivity =>
|
||||
isDesignActivity(activity) || isCollectionActivity(activity);
|
||||
@@ -178,7 +176,6 @@ export const isDesignActivity = (activity?: string): activity is GlobalActivity
|
||||
return true;
|
||||
|
||||
case ACTIVITY_HOME:
|
||||
case ACTIVITY_MIGRATION:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -192,7 +189,6 @@ export const isCollectionActivity = (activity?: string): activity is GlobalActiv
|
||||
case ACTIVITY_SPEC:
|
||||
case ACTIVITY_UNIT_TEST:
|
||||
case ACTIVITY_HOME:
|
||||
case ACTIVITY_MIGRATION:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -204,7 +200,6 @@ export const isValidActivity = (activity: string): activity is GlobalActivity =>
|
||||
case ACTIVITY_DEBUG:
|
||||
case ACTIVITY_UNIT_TEST:
|
||||
case ACTIVITY_HOME:
|
||||
case ACTIVITY_MIGRATION:
|
||||
return true;
|
||||
|
||||
default:
|
||||
|
||||
@@ -12,11 +12,6 @@ export function clickLink(href: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export function getDesignerDataDir() {
|
||||
const { app } = electron.remote || electron;
|
||||
return process.env.DESIGNER_DATA_PATH || join(app.getPath('appData'), 'Insomnia Designer');
|
||||
}
|
||||
|
||||
/**
|
||||
* This environment variable is added by electron-builder.
|
||||
* see: https://www.electron.build/configuration/nsis.html#portable\
|
||||
|
||||
@@ -1,252 +0,0 @@
|
||||
import fs from 'fs';
|
||||
import fsx from 'fs-extra';
|
||||
import { difference } from 'lodash';
|
||||
import NeDB from 'nedb';
|
||||
import fsPath from 'path';
|
||||
|
||||
import type { BaseModel } from '../models';
|
||||
import * as models from '../models';
|
||||
import { getModelName } from '../models';
|
||||
import type { Settings } from '../models/settings';
|
||||
import { forceWorkspaceScopeToDesign } from '../sync/git/force-workspace-scope-to-design';
|
||||
import { database as db } from './database';
|
||||
|
||||
async function loadDesignerDb(
|
||||
types: string[],
|
||||
designerDataDir: string,
|
||||
): Promise<Record<string, any>> {
|
||||
const designerDb = {};
|
||||
types.forEach(type => {
|
||||
designerDb[type] = []; // initialize each type to empty array
|
||||
});
|
||||
const promises = types.map(
|
||||
type =>
|
||||
new Promise<void>((resolve, reject) => {
|
||||
const filePath = fsPath.join(designerDataDir, `insomnia.${type}.db`);
|
||||
|
||||
if (!fs.existsSync(filePath)) {
|
||||
console.log(`[db] db file for ${type} not found: ${filePath}`);
|
||||
resolve();
|
||||
}
|
||||
|
||||
// Load the data
|
||||
const collection = new NeDB({
|
||||
autoload: true,
|
||||
filename: filePath,
|
||||
corruptAlertThreshold: 0.9,
|
||||
});
|
||||
// Find every entry and store in memory
|
||||
collection.find({}, (err, docs: BaseModel[]) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
(designerDb[type] as Record<string, any>[]).push(...docs);
|
||||
resolve();
|
||||
});
|
||||
}),
|
||||
);
|
||||
await Promise.all(promises);
|
||||
// Return entries, but no longer linked to the database files
|
||||
return designerDb;
|
||||
}
|
||||
|
||||
type DBType = Record<string, BaseModel[]>;
|
||||
|
||||
export interface MigrationOptions {
|
||||
useDesignerSettings: boolean;
|
||||
copyPlugins: boolean;
|
||||
copyWorkspaces: boolean;
|
||||
designerDataDir: string;
|
||||
coreDataDir: string;
|
||||
}
|
||||
|
||||
export interface MigrationResult {
|
||||
error?: Error;
|
||||
}
|
||||
|
||||
async function createCoreBackup(modelTypes: string[], coreDataDir: string) {
|
||||
console.log('[db-merge] creating backup');
|
||||
const backupDir = fsPath.join(coreDataDir, 'core-backup');
|
||||
await fsx.remove(backupDir);
|
||||
await fsx.ensureDir(backupDir);
|
||||
// Copy db files
|
||||
const filesToCopy = modelTypes.map(modelType => `insomnia.${modelType}.db`);
|
||||
|
||||
for (const entryName of filesToCopy) {
|
||||
const src = fsPath.join(coreDataDir, entryName);
|
||||
const dest = fsPath.join(backupDir, entryName);
|
||||
await fsx.copy(src, dest);
|
||||
}
|
||||
|
||||
// Copy dirs
|
||||
const dirsToCopy = ['plugins', 'responses', 'version-control'];
|
||||
await copyDirs(dirsToCopy, coreDataDir, backupDir);
|
||||
console.log(`[db-merge] backup created at ${backupDir}`);
|
||||
return backupDir;
|
||||
}
|
||||
|
||||
async function migratePlugins(designerDataDir: string, coreDataDir: string) {
|
||||
const designerPluginDir = fsPath.join(designerDataDir, 'plugins');
|
||||
const corePluginDir = fsPath.join(coreDataDir, 'plugins');
|
||||
// get list of plugins in Designer
|
||||
const designerPlugins = await readDirs(designerPluginDir);
|
||||
await removeDirs(designerPlugins, corePluginDir);
|
||||
await copyDirs(designerPlugins, designerPluginDir, corePluginDir);
|
||||
// Remove plugin bundle from installed plugins because it's included with the app now
|
||||
const pluginsToDelete = [
|
||||
'insomnia-plugin-kong-bundle',
|
||||
'insomnia-plugin-kong-declarative-config',
|
||||
'insomnia-plugin-kong-kubernetes-config',
|
||||
'insomnia-plugin-kong-portal',
|
||||
];
|
||||
await removeDirs(pluginsToDelete, corePluginDir);
|
||||
}
|
||||
|
||||
async function readDirs(srcDir: string) {
|
||||
if (existsAndIsDirectory(srcDir)) {
|
||||
return await fs.promises.readdir(srcDir);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async function copyDirs(dirs: string[], srcDir: string, destDir: string) {
|
||||
for (const dir of dirs.filter(c => c)) {
|
||||
const src = fsPath.join(srcDir, dir);
|
||||
const dest = fsPath.join(destDir, dir);
|
||||
|
||||
// If source exists, ensure the destination exists, and copy into it
|
||||
if (existsAndIsDirectory(src)) {
|
||||
await fsx.ensureDir(dest);
|
||||
await fsx.copy(src, dest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function removeDirs(dirs: string[], srcDir: string) {
|
||||
for (const dir of dirs.filter(c => c)) {
|
||||
const dirToRemove = fsPath.join(srcDir, dir);
|
||||
|
||||
if (existsAndIsDirectory(dirToRemove)) {
|
||||
await fsx.remove(dirToRemove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function existsAndIsDirectory(name: string) {
|
||||
return fs.existsSync(name) && fs.statSync(name).isDirectory();
|
||||
}
|
||||
|
||||
export default async function migrateFromDesigner({
|
||||
useDesignerSettings,
|
||||
designerDataDir,
|
||||
coreDataDir,
|
||||
copyPlugins,
|
||||
copyWorkspaces,
|
||||
}: MigrationOptions) {
|
||||
console.log(
|
||||
`[db-merge] starting process for migrating from ${designerDataDir} to ${coreDataDir}`,
|
||||
);
|
||||
const nonWorkspaceModels = [
|
||||
models.stats.type, // TODO: investigate further any implications that may invalidate collected stats
|
||||
models.settings.type,
|
||||
];
|
||||
// Every model except those to ignore and settings is a "workspace" model
|
||||
const workspaceModels = difference(models.types(), nonWorkspaceModels);
|
||||
const modelTypesToMerge = [];
|
||||
|
||||
if (useDesignerSettings) {
|
||||
// @ts-expect-error -- TSCONVERSION
|
||||
modelTypesToMerge.push(models.settings.type);
|
||||
console.log('[db-merge] keeping settings from Insomnia Designer');
|
||||
} else {
|
||||
console.log('[db-merge] keeping settings from Insomnia Core');
|
||||
}
|
||||
|
||||
if (copyWorkspaces) {
|
||||
// @ts-expect-error -- TSCONVERSION
|
||||
modelTypesToMerge.push(...workspaceModels);
|
||||
}
|
||||
|
||||
let backupDir = '';
|
||||
|
||||
try {
|
||||
// Create core backup
|
||||
backupDir = await createCoreBackup(modelTypesToMerge, coreDataDir);
|
||||
// Load designer database
|
||||
const designerDb: DBType = await loadDesignerDb(modelTypesToMerge, designerDataDir);
|
||||
|
||||
// For each model, batch upsert entries into the Core database
|
||||
for (const modelType of modelTypesToMerge) {
|
||||
const entries = designerDb[modelType];
|
||||
|
||||
// Persist some settings from core
|
||||
if (modelType === models.settings.type) {
|
||||
const coreSettings = await models.settings.getOrCreate();
|
||||
const settingsToPersist: (keyof Settings)[] = [
|
||||
'_id',
|
||||
'hasPromptedToMigrateFromDesigner',
|
||||
];
|
||||
settingsToPersist.forEach(setting => {
|
||||
if (coreSettings.hasOwnProperty(setting)) {
|
||||
entries[0][setting] = coreSettings[setting];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// For each workspace coming from Designer, mark workspace.scope as 'design'
|
||||
if (modelType === models.workspace.type) {
|
||||
entries.forEach(forceWorkspaceScopeToDesign);
|
||||
}
|
||||
|
||||
const entryCount = entries.length;
|
||||
console.log(
|
||||
`[db-merge] merging ${entryCount} ${getModelName(modelType, entryCount)} from Designer`,
|
||||
);
|
||||
await db.batchModifyDocs({
|
||||
upsert: entries,
|
||||
remove: [],
|
||||
});
|
||||
}
|
||||
|
||||
if (copyWorkspaces) {
|
||||
console.log('[db-merge] migrating version control data from designer to core');
|
||||
await copyDirs(['version-control'], designerDataDir, coreDataDir);
|
||||
console.log('[db-merge] migrating response cache from designer to core');
|
||||
await copyDirs(['responses'], designerDataDir, coreDataDir);
|
||||
}
|
||||
|
||||
if (copyPlugins) {
|
||||
console.log('[db-merge] migrating plugins from designer to core');
|
||||
await migratePlugins(designerDataDir, coreDataDir);
|
||||
}
|
||||
|
||||
console.log('[db-merge] done!');
|
||||
return {};
|
||||
} catch (error) {
|
||||
console.log('[db-merge] an error occurred while migrating');
|
||||
console.error(error);
|
||||
await restoreCoreBackup(backupDir, coreDataDir);
|
||||
return {
|
||||
error,
|
||||
} as MigrationResult;
|
||||
}
|
||||
}
|
||||
|
||||
export async function restoreCoreBackup(backupDir: string, coreDataDir: string) {
|
||||
if (!backupDir) {
|
||||
console.log('[db-merge] nothing to restore; no backup was created');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!existsAndIsDirectory(backupDir)) {
|
||||
console.log(`[db-merge] nothing to restore: backup directory doesn't exist at ${backupDir}`);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[db-merge] restoring from backup');
|
||||
await removeDirs(['plugins', 'responses', 'version-control'], coreDataDir);
|
||||
await fsx.copy(backupDir, coreDataDir);
|
||||
console.log('[db-merge] restored from backup');
|
||||
}
|
||||
@@ -57,7 +57,6 @@ export function init(): BaseSettings {
|
||||
* So by default this flag is set to false, and is toggled to true during initialization for new users.
|
||||
*/
|
||||
hasPromptedAnalytics: false,
|
||||
hasPromptedToMigrateFromDesigner: false,
|
||||
hotKeyRegistry: hotkeys.newDefaultRegistry(),
|
||||
httpProxy: '',
|
||||
httpsProxy: '',
|
||||
|
||||
@@ -106,7 +106,7 @@ export class SettingsModal extends PureComponent<Props, State> {
|
||||
</Tab>
|
||||
</TabList>
|
||||
<TabPanel className="react-tabs__tab-panel pad scrollable">
|
||||
<General hideModal={this.hide} />
|
||||
<General />
|
||||
</TabPanel>
|
||||
<TabPanel className="react-tabs__tab-panel pad scrollable">
|
||||
<ImportExport
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { EnvironmentHighlightColorStyle, HttpVersion, HttpVersions, UpdateChannel } from 'insomnia-common';
|
||||
import { Tooltip } from 'insomnia-components';
|
||||
import React, { FC, Fragment, useCallback } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import {
|
||||
ACTIVITY_MIGRATION,
|
||||
EditorKeyMap,
|
||||
isDevelopment,
|
||||
isMac,
|
||||
@@ -18,7 +17,6 @@ import { docsKeyMaps } from '../../../common/documentation';
|
||||
import { strings } from '../../../common/strings';
|
||||
import * as models from '../../../models';
|
||||
import { initNewOAuthSession } from '../../../network/o-auth-2/misc';
|
||||
import { setActiveActivity } from '../../redux/modules/global';
|
||||
import { selectSettings, selectStats } from '../../redux/selectors';
|
||||
import { Link } from '../base/link';
|
||||
import { CheckForUpdatesButton } from '../check-for-updates-button';
|
||||
@@ -59,13 +57,6 @@ const DevelopmentOnlySettings: FC = () => {
|
||||
<hr className="pad-top" />
|
||||
<h2>Development</h2>
|
||||
|
||||
<div className="form-row pad-top-sm">
|
||||
<BooleanSetting
|
||||
label="Has been prompted to migrate from Insomnia Designer"
|
||||
setting="hasPromptedToMigrateFromDesigner"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="form-row pad-top-sm">
|
||||
<BooleanSetting
|
||||
label="Has seen analytics prompt"
|
||||
@@ -92,19 +83,8 @@ const DevelopmentOnlySettings: FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
interface Props {
|
||||
hideModal: () => void;
|
||||
}
|
||||
|
||||
export const General: FC<Props> = ({ hideModal }) => {
|
||||
const dispatch = useDispatch();
|
||||
export const General: FC = () => {
|
||||
const settings = useSelector(selectSettings);
|
||||
|
||||
const handleStartMigration = useCallback(() => {
|
||||
dispatch(setActiveActivity(ACTIVITY_MIGRATION));
|
||||
hideModal();
|
||||
}, [hideModal, dispatch]);
|
||||
|
||||
return (
|
||||
<div className="pad-bottom">
|
||||
<div className="row-fill row-fill--top">
|
||||
@@ -466,15 +446,6 @@ export const General: FC<Props> = ({ hideModal }) => {
|
||||
setting="allowNotificationRequests"
|
||||
/>
|
||||
|
||||
<hr className="pad-top" />
|
||||
|
||||
<h2>Migrate from Designer</h2>
|
||||
<div className="form-row--start pad-top-sm">
|
||||
<button className="btn btn--clicky pointer" onClick={handleStartMigration}>
|
||||
Show migration workflow
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<DevelopmentOnlySettings />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,325 +0,0 @@
|
||||
import { Button, ToggleSwitch } from 'insomnia-components';
|
||||
import React, { FunctionComponent, useCallback, useMemo, useState } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useMount } from 'react-use';
|
||||
|
||||
import { ACTIVITY_HOME } from '../../common/constants';
|
||||
import { getDataDirectory, getDesignerDataDir, restartApp } from '../../common/electron-helpers';
|
||||
import type { MigrationOptions } from '../../common/migrate-from-designer';
|
||||
import migrateFromDesigner, { existsAndIsDirectory } from '../../common/migrate-from-designer';
|
||||
import * as models from '../../models';
|
||||
import coreLogo from '../images/insomnia-core-logo.png';
|
||||
import { setActiveActivity } from '../redux/modules/global';
|
||||
import { HelpTooltip } from './help-tooltip';
|
||||
import { PageLayout } from './page-layout';
|
||||
import type { WrapperProps } from './wrapper';
|
||||
|
||||
type Step = 'options' | 'migrating' | 'results';
|
||||
|
||||
interface SettingProps {
|
||||
label: string;
|
||||
name: keyof MigrationOptions;
|
||||
options: MigrationOptions;
|
||||
}
|
||||
|
||||
type TextSettingProps = SettingProps & {
|
||||
handleChange: (arg0: React.SyntheticEvent<HTMLInputElement>) => void;
|
||||
errorMessage?: string;
|
||||
};
|
||||
|
||||
const TextSetting: FunctionComponent<TextSettingProps> = ({ handleChange, label, name, options, errorMessage }) => {
|
||||
if (!options.hasOwnProperty(name)) {
|
||||
throw new Error(`Invalid text setting name ${name}`);
|
||||
}
|
||||
|
||||
const hasError = !!errorMessage;
|
||||
return (
|
||||
<div className="form-control form-control--outlined margin-bottom">
|
||||
<label>
|
||||
{label}
|
||||
<input
|
||||
className={hasError ? 'input--error' : ''}
|
||||
type="text"
|
||||
name={name}
|
||||
// @ts-expect-error -- TSCONVERSION this is a genuine error. booleans shoudl not be allowed here
|
||||
defaultValue={options[name]}
|
||||
onBlur={handleChange}
|
||||
/>
|
||||
{hasError && <div className="font-error space-top">{errorMessage}</div>}
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
type BooleanSettingProps = SettingProps & {
|
||||
handleChange: (arg0: boolean, arg1: Record<string, any>, arg2: string) => void;
|
||||
help?: string;
|
||||
};
|
||||
|
||||
const BooleanSetting = ({ handleChange, label, name, options, help }: BooleanSettingProps) => {
|
||||
if (!options.hasOwnProperty(name)) {
|
||||
throw new Error(`Invalid text setting name ${name}`);
|
||||
}
|
||||
|
||||
const labelNode = useMemo(
|
||||
() => (
|
||||
<>
|
||||
{label}
|
||||
{help && <HelpTooltip className="space-left">{help}</HelpTooltip>}
|
||||
</>
|
||||
),
|
||||
[help, label],
|
||||
);
|
||||
return (
|
||||
<ToggleSwitch
|
||||
labelClassName="row margin-bottom wide"
|
||||
checked={Boolean(options[name])}
|
||||
// @ts-expect-error -- TSCONVERSION
|
||||
id={name}
|
||||
label={labelNode}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
interface OptionsProps {
|
||||
start: (arg0: MigrationOptions) => void;
|
||||
cancel: () => void;
|
||||
}
|
||||
|
||||
const Options = ({ start, cancel }: OptionsProps) => {
|
||||
const [options, setOptions] = useState<MigrationOptions>(() => ({
|
||||
useDesignerSettings: false,
|
||||
copyWorkspaces: false,
|
||||
copyPlugins: false,
|
||||
designerDataDir: getDesignerDataDir(),
|
||||
coreDataDir: getDataDirectory(),
|
||||
}));
|
||||
const handleInputChange = useCallback((e: React.SyntheticEvent<HTMLInputElement>) => {
|
||||
const { name, value } = e.currentTarget;
|
||||
setOptions(prevOpts => ({ ...prevOpts, [name]: value }));
|
||||
}, []);
|
||||
const handleSwitchChange = useCallback(
|
||||
(checked: boolean, _event, id: string) => {
|
||||
setOptions(prevOpts => ({ ...prevOpts, [id]: checked }));
|
||||
},
|
||||
[],
|
||||
);
|
||||
const {
|
||||
coreDataDir,
|
||||
designerDataDir,
|
||||
useDesignerSettings,
|
||||
copyWorkspaces,
|
||||
copyPlugins,
|
||||
} = options;
|
||||
const coreExists = useMemo(() => existsAndIsDirectory(coreDataDir), [coreDataDir]);
|
||||
const designerExists = useMemo(() => existsAndIsDirectory(designerDataDir), [
|
||||
designerDataDir,
|
||||
]);
|
||||
const hasSomethingToMigrate = useDesignerSettings || copyWorkspaces || copyPlugins;
|
||||
const dirsExist = coreExists && designerExists;
|
||||
const canStart = hasSomethingToMigrate && dirsExist;
|
||||
return (
|
||||
<>
|
||||
<p>
|
||||
From the list below, select the individual items you would like to migrate from Designer.
|
||||
</p>
|
||||
<div className="text-left">
|
||||
<BooleanSetting
|
||||
label="Copy Workspaces"
|
||||
name="copyWorkspaces"
|
||||
options={options}
|
||||
handleChange={handleSwitchChange}
|
||||
help={
|
||||
'This includes all resources linked to a workspace (eg. requests, proto files, api specs, environments, etc)'
|
||||
}
|
||||
/>
|
||||
<BooleanSetting
|
||||
label="Copy Plugins"
|
||||
name="copyPlugins"
|
||||
options={options}
|
||||
handleChange={handleSwitchChange}
|
||||
help={
|
||||
'Merge plugins between Designer and Insomnia, keeping the Designer version where a duplicate exists'
|
||||
}
|
||||
/>
|
||||
<BooleanSetting
|
||||
label="Copy Designer Application Settings"
|
||||
name="useDesignerSettings"
|
||||
options={options}
|
||||
handleChange={handleSwitchChange}
|
||||
help={'Keep user preferences from Designer'}
|
||||
/>
|
||||
<details>
|
||||
<summary className="margin-bottom">Advanced options</summary>
|
||||
<TextSetting
|
||||
label="Designer Data Directory"
|
||||
name="designerDataDir"
|
||||
options={options}
|
||||
handleChange={handleInputChange}
|
||||
errorMessage={designerExists ? undefined : 'Directory does not exist'}
|
||||
/>
|
||||
<TextSetting
|
||||
label="Insomnia Data Directory"
|
||||
name="coreDataDir"
|
||||
options={options}
|
||||
handleChange={handleInputChange}
|
||||
errorMessage={coreExists ? undefined : 'Directory does not exist'}
|
||||
/>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<div className="margin-top">
|
||||
<Button
|
||||
key="start"
|
||||
bg="surprise"
|
||||
radius="3px"
|
||||
size="medium"
|
||||
variant="contained"
|
||||
onClick={() => start(options)}
|
||||
disabled={!canStart}
|
||||
>
|
||||
Start Migration
|
||||
</Button>
|
||||
<button key="cancel" className="btn btn--super-compact" onClick={cancel}>
|
||||
Skip for now
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const Migrating = () => (
|
||||
<>
|
||||
<p>
|
||||
<strong>Migrating</strong>
|
||||
</p>
|
||||
<p>
|
||||
<i className="fa fa-spin fa-refresh" />
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
|
||||
const RestartButton = () => (
|
||||
<button key="restart" className="btn btn--clicky" onClick={restartApp}>
|
||||
Restart Now
|
||||
</button>
|
||||
);
|
||||
|
||||
const Success = () => (
|
||||
<>
|
||||
<p>
|
||||
<strong>Migrated successfully!</strong>
|
||||
</p>
|
||||
<p>
|
||||
<i className="fa fa-check" />
|
||||
</p>
|
||||
|
||||
<p>Please restart the application for your changes to take effect.</p>
|
||||
|
||||
<div className="margin-top">
|
||||
<RestartButton />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
interface FailProps {
|
||||
error: Error;
|
||||
}
|
||||
|
||||
const Fail = ({ error }: FailProps) => (
|
||||
<>
|
||||
<p>
|
||||
<strong>Something went wrong!!</strong>
|
||||
</p>
|
||||
<p>
|
||||
<i className="fa fa-exclamation" />
|
||||
</p>
|
||||
|
||||
<div className="wide text-left">
|
||||
<p>
|
||||
Something went wrong with the migration and all changes made have been reverted. Please
|
||||
restart the application.
|
||||
</p>
|
||||
|
||||
{error && (
|
||||
<details>
|
||||
<summary>Additional information</summary>
|
||||
<pre className="pad-top-sm selectable">
|
||||
<code className="wide">{error.stack || error}</code>
|
||||
</pre>
|
||||
</details>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="margin-top">
|
||||
<RestartButton />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
const MigrationBody = () => {
|
||||
// The migration step does not need to be in redux, but a loading state does need to exist there.
|
||||
const [step, setStep] = useState<Step>('options');
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
const start = useCallback(async (options: MigrationOptions) => {
|
||||
setStep('migrating');
|
||||
const { error } = await migrateFromDesigner(options);
|
||||
|
||||
if (error) {
|
||||
setError(error);
|
||||
}
|
||||
|
||||
setStep('results');
|
||||
}, []);
|
||||
|
||||
const reduxDispatch = useDispatch();
|
||||
const cancel = useCallback(() => {
|
||||
reduxDispatch(setActiveActivity(ACTIVITY_HOME));
|
||||
}, [reduxDispatch]);
|
||||
|
||||
useMount(() => (
|
||||
models.settings.patch({ hasPromptedToMigrateFromDesigner: true })
|
||||
));
|
||||
|
||||
switch (step) {
|
||||
case 'options':
|
||||
return <Options start={start} cancel={cancel} />;
|
||||
|
||||
case 'migrating':
|
||||
return <Migrating />;
|
||||
|
||||
case 'results':
|
||||
return error ? <Fail error={error} /> : <Success />;
|
||||
|
||||
default:
|
||||
throw new Error(`${step} is not recognized as a migration step.`);
|
||||
}
|
||||
};
|
||||
|
||||
interface Props {
|
||||
wrapperProps: WrapperProps;
|
||||
}
|
||||
|
||||
export const WrapperMigration: FunctionComponent<Props> = ({ wrapperProps }) => (
|
||||
<PageLayout
|
||||
wrapperProps={wrapperProps}
|
||||
renderPageBody={() => (
|
||||
<div className="migration">
|
||||
<div className="migration__background theme--sidebar" />
|
||||
<div className="migration__content theme--dialog">
|
||||
<div className="img-container">
|
||||
<img src={coreLogo} alt="Kong" />
|
||||
</div>
|
||||
<header className="migration__content__header">
|
||||
<h1>Migrate from Insomnia Designer</h1>
|
||||
<h2>Insomnia Designer and Core are now Insomnia!</h2>
|
||||
</header>
|
||||
<div className="migration__content__body">
|
||||
<MigrationBody />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
@@ -6,7 +6,6 @@ import type { GlobalActivity } from '../../common/constants';
|
||||
import {
|
||||
ACTIVITY_DEBUG,
|
||||
ACTIVITY_HOME,
|
||||
ACTIVITY_MIGRATION,
|
||||
ACTIVITY_SPEC,
|
||||
ACTIVITY_UNIT_TEST,
|
||||
AUTOBIND_CFG,
|
||||
@@ -79,7 +78,6 @@ import { WrapperModal } from './modals/wrapper-modal';
|
||||
import { WrapperDebug } from './wrapper-debug';
|
||||
import { WrapperDesign } from './wrapper-design';
|
||||
import WrapperHome from './wrapper-home';
|
||||
import { WrapperMigration } from './wrapper-migration';
|
||||
import { WrapperUnitTest } from './wrapper-unit-test';
|
||||
|
||||
const spectral = initializeSpectral();
|
||||
@@ -700,8 +698,6 @@ export class Wrapper extends PureComponent<WrapperProps, State> {
|
||||
wrapperProps={this.props}
|
||||
/>
|
||||
)}
|
||||
|
||||
{activity === ACTIVITY_MIGRATION && <WrapperMigration wrapperProps={this.props} />}
|
||||
</Fragment>
|
||||
</Fragment>
|
||||
);
|
||||
|
||||
@@ -12,7 +12,6 @@ import { parse as urlParse } from 'url';
|
||||
import { SegmentEvent, trackSegmentEvent } from '../../common/analytics';
|
||||
import {
|
||||
ACTIVITY_HOME,
|
||||
ACTIVITY_MIGRATION,
|
||||
AUTOBIND_CFG,
|
||||
COLLAPSE_SIDEBAR_REMS,
|
||||
DEFAULT_PANE_HEIGHT,
|
||||
@@ -1041,7 +1040,7 @@ class App extends PureComponent<AppProps, State> {
|
||||
} = this.props;
|
||||
let title;
|
||||
|
||||
if (activity === ACTIVITY_HOME || activity === ACTIVITY_MIGRATION) {
|
||||
if (activity === ACTIVITY_HOME) {
|
||||
title = getAppName();
|
||||
} else if (activeWorkspace && activeWorkspaceName) {
|
||||
title = activeProject.name;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import fs from 'fs';
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
import thunk from 'redux-thunk';
|
||||
|
||||
@@ -6,13 +5,11 @@ import { globalBeforeEach } from '../../../../__jest__/before-each';
|
||||
import {
|
||||
ACTIVITY_DEBUG,
|
||||
ACTIVITY_HOME,
|
||||
ACTIVITY_MIGRATION,
|
||||
ACTIVITY_SPEC,
|
||||
ACTIVITY_UNIT_TEST,
|
||||
GlobalActivity,
|
||||
SORT_MODIFIED_DESC,
|
||||
} from '../../../../common/constants';
|
||||
import { getDesignerDataDir } from '../../../../common/electron-helpers';
|
||||
import * as models from '../../../../models';
|
||||
import { DEFAULT_PROJECT_ID } from '../../../../models/project';
|
||||
import {
|
||||
@@ -35,23 +32,17 @@ jest.mock('../../../../common/analytics');
|
||||
const middlewares = [thunk];
|
||||
const mockStore = configureMockStore(middlewares);
|
||||
|
||||
const createSettings = (
|
||||
hasPromptedMigration: boolean,
|
||||
hasPromptedAnalytics: boolean,
|
||||
) => {
|
||||
const createSettings = (hasPromptedAnalytics: boolean) => {
|
||||
const settings = models.settings.init();
|
||||
settings.hasPromptedToMigrateFromDesigner = hasPromptedMigration;
|
||||
settings.hasPromptedAnalytics = hasPromptedAnalytics;
|
||||
return settings;
|
||||
};
|
||||
|
||||
describe('global', () => {
|
||||
let fsExistsSyncSpy;
|
||||
beforeEach(async () => {
|
||||
await globalBeforeEach();
|
||||
jest.resetAllMocks();
|
||||
global.localStorage.clear();
|
||||
fsExistsSyncSpy = jest.spyOn(fs, 'existsSync');
|
||||
});
|
||||
|
||||
describe('setActiveActivity', () => {
|
||||
@@ -60,7 +51,6 @@ describe('global', () => {
|
||||
ACTIVITY_DEBUG,
|
||||
ACTIVITY_UNIT_TEST,
|
||||
ACTIVITY_HOME,
|
||||
ACTIVITY_MIGRATION,
|
||||
])('should update local storage and track event: %s', (activity: GlobalActivity) => {
|
||||
const expectedEvent = {
|
||||
type: SET_ACTIVE_ACTIVITY,
|
||||
@@ -177,7 +167,7 @@ describe('global', () => {
|
||||
ACTIVITY_UNIT_TEST,
|
||||
ACTIVITY_HOME,
|
||||
])('should initialize %s from local storage', async activity => {
|
||||
const settings = createSettings(true, true);
|
||||
const settings = createSettings(true);
|
||||
const store = mockStore({
|
||||
global: {},
|
||||
entities: {
|
||||
@@ -193,30 +183,12 @@ describe('global', () => {
|
||||
expect(store.getActions()).toEqual([expectedEvent]);
|
||||
});
|
||||
|
||||
it('should go to home if initialized at migration', async () => {
|
||||
const settings = createSettings(true, true);
|
||||
const store = mockStore({
|
||||
global: {},
|
||||
entities: {
|
||||
settings: [settings],
|
||||
},
|
||||
});
|
||||
const activity = ACTIVITY_MIGRATION;
|
||||
global.localStorage.setItem(`${LOCALSTORAGE_PREFIX}::activity`, JSON.stringify(activity));
|
||||
const expectedEvent = {
|
||||
type: SET_ACTIVE_ACTIVITY,
|
||||
activity: ACTIVITY_HOME,
|
||||
};
|
||||
store.dispatch(initActiveActivity());
|
||||
expect(store.getActions()).toEqual([expectedEvent]);
|
||||
});
|
||||
|
||||
it.each(
|
||||
'something',
|
||||
null,
|
||||
undefined,
|
||||
)('should go to home if initialized with an unsupported value: %s', async activity => {
|
||||
const settings = createSettings(true, true);
|
||||
const settings = createSettings(true);
|
||||
const store = mockStore({
|
||||
global: {},
|
||||
entities: {
|
||||
@@ -233,7 +205,7 @@ describe('global', () => {
|
||||
});
|
||||
|
||||
it('should go to home if local storage key not found', async () => {
|
||||
const settings = createSettings(true, true);
|
||||
const settings = createSettings(true);
|
||||
const store = mockStore({
|
||||
global: {},
|
||||
entities: {
|
||||
@@ -248,62 +220,5 @@ describe('global', () => {
|
||||
expect(store.getActions()).toEqual([expectedEvent]);
|
||||
});
|
||||
|
||||
it('should go to home if initialized at migration seen', async () => {
|
||||
const settings = createSettings(true, true);
|
||||
const store = mockStore({
|
||||
global: {},
|
||||
entities: {
|
||||
settings: [settings],
|
||||
},
|
||||
});
|
||||
const activity = ACTIVITY_MIGRATION;
|
||||
global.localStorage.setItem(`${LOCALSTORAGE_PREFIX}::activity`, JSON.stringify(activity));
|
||||
const expectedEvent = {
|
||||
type: SET_ACTIVE_ACTIVITY,
|
||||
activity: ACTIVITY_HOME,
|
||||
};
|
||||
store.dispatch(initActiveActivity());
|
||||
expect(store.getActions()).toEqual([expectedEvent]);
|
||||
});
|
||||
|
||||
it('should prompt to migrate', async () => {
|
||||
const settings = createSettings(false, true);
|
||||
fsExistsSyncSpy.mockReturnValue(true);
|
||||
const store = mockStore({
|
||||
global: {},
|
||||
entities: {
|
||||
settings: [settings],
|
||||
},
|
||||
});
|
||||
const activity = ACTIVITY_HOME;
|
||||
global.localStorage.setItem(`${LOCALSTORAGE_PREFIX}::activity`, JSON.stringify(activity));
|
||||
const expectedEvent = {
|
||||
type: SET_ACTIVE_ACTIVITY,
|
||||
activity: ACTIVITY_MIGRATION,
|
||||
};
|
||||
store.dispatch(initActiveActivity());
|
||||
expect(store.getActions()).toEqual([expectedEvent]);
|
||||
expect(fsExistsSyncSpy).toHaveBeenCalledWith(getDesignerDataDir());
|
||||
});
|
||||
|
||||
it('should not prompt to migrate if default directory not found', async () => {
|
||||
const settings = createSettings(false, true);
|
||||
fsExistsSyncSpy.mockReturnValue(false);
|
||||
const store = mockStore({
|
||||
global: {},
|
||||
entities: {
|
||||
settings: [settings],
|
||||
},
|
||||
});
|
||||
const activity = ACTIVITY_HOME;
|
||||
global.localStorage.setItem(`${LOCALSTORAGE_PREFIX}::activity`, JSON.stringify(activity));
|
||||
const expectedEvent = {
|
||||
type: SET_ACTIVE_ACTIVITY,
|
||||
activity,
|
||||
};
|
||||
store.dispatch(initActiveActivity());
|
||||
expect(store.getActions()).toEqual([expectedEvent]);
|
||||
expect(fsExistsSyncSpy).toHaveBeenCalledWith(getDesignerDataDir());
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,11 +11,9 @@ import type { DashboardSortOrder, GlobalActivity } from '../../../common/constan
|
||||
import {
|
||||
ACTIVITY_DEBUG,
|
||||
ACTIVITY_HOME,
|
||||
ACTIVITY_MIGRATION,
|
||||
isValidActivity,
|
||||
} from '../../../common/constants';
|
||||
import { database } from '../../../common/database';
|
||||
import { getDesignerDataDir } from '../../../common/electron-helpers';
|
||||
import {
|
||||
exportRequestsData,
|
||||
exportRequestsHAR,
|
||||
@@ -45,7 +43,7 @@ import {
|
||||
TAB_INDEX_PLUGINS,
|
||||
TAB_INDEX_THEMES,
|
||||
} from '../../components/modals/settings-modal';
|
||||
import { selectActiveActivity, selectActiveProjectName, selectSettings, selectStats, selectWorkspacesForActiveProject } from '../selectors';
|
||||
import { selectActiveProjectName, selectStats, selectWorkspacesForActiveProject } from '../selectors';
|
||||
import { importUri } from './import';
|
||||
import { activateWorkspace } from './workspace';
|
||||
|
||||
@@ -667,7 +665,6 @@ function _normalizeActivity(activity: GlobalActivity): GlobalActivity {
|
||||
*/
|
||||
export const initActiveActivity = () => (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const settings = selectSettings(state);
|
||||
// Default to home
|
||||
let activeActivity = ACTIVITY_HOME;
|
||||
|
||||
@@ -680,21 +677,7 @@ export const initActiveActivity = () => (dispatch, getState) => {
|
||||
// Nothing here...
|
||||
}
|
||||
|
||||
activeActivity = _normalizeActivity(activeActivity);
|
||||
let overrideActivity: GlobalActivity | null = null;
|
||||
|
||||
if (activeActivity === ACTIVITY_MIGRATION) {
|
||||
// If relaunched after a migration, go to the next activity
|
||||
// Don't need to do this for migration because that doesn't require a restart
|
||||
overrideActivity = ACTIVITY_HOME;
|
||||
} else {
|
||||
// Always check if user has been prompted to migrate or onboard
|
||||
if (!settings.hasPromptedToMigrateFromDesigner && fs.existsSync(getDesignerDataDir())) {
|
||||
overrideActivity = ACTIVITY_MIGRATION;
|
||||
}
|
||||
}
|
||||
|
||||
const initializeToActivity = overrideActivity || activeActivity;
|
||||
const initializeToActivity = _normalizeActivity(activeActivity);
|
||||
if (initializeToActivity === state.global.activeActivity) {
|
||||
// no need to dispatch the action twice if it has already been set to the correct value.
|
||||
return;
|
||||
@@ -705,17 +688,6 @@ export const initActiveActivity = () => (dispatch, getState) => {
|
||||
export const initFirstLaunch = () => async (dispatch, getState) => {
|
||||
const state = getState();
|
||||
|
||||
const activeActivity = selectActiveActivity(state);
|
||||
// If the active activity is migration, then don't initialize into the analytics prompt, because we'll migrate the analytics opt-in setting from Designer.
|
||||
if (activeActivity === ACTIVITY_MIGRATION) {
|
||||
const { hasPromptedToMigrateFromDesigner } = selectSettings(state);
|
||||
if (!hasPromptedToMigrateFromDesigner) {
|
||||
await models.settings.patch({ hasPromptedAnalytics: true });
|
||||
dispatch(setIsFinishedBooting(true));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const stats = selectStats(state);
|
||||
if (stats.launches > 1) {
|
||||
dispatch(setIsFinishedBooting(true));
|
||||
|
||||
@@ -56,7 +56,6 @@ export interface Settings {
|
||||
fontVariantLigatures: boolean;
|
||||
forceVerticalLayout: boolean;
|
||||
hasPromptedAnalytics: boolean;
|
||||
hasPromptedToMigrateFromDesigner: boolean;
|
||||
hotKeyRegistry: HotKeyRegistry;
|
||||
httpProxy: string;
|
||||
httpsProxy: string;
|
||||
|
||||
@@ -73,17 +73,6 @@ export const loadDb = async ({
|
||||
const dir = src || appDataDir || getAppDataDir(getDefaultAppName());
|
||||
db = await neDbAdapter(dir, filterTypes);
|
||||
db && logger.debug(`Data store configured from app data directory at \`${path.resolve(dir)}\``); // Try to load from the Designer data dir, if the Core data directory does not exist
|
||||
|
||||
if (!db && !appDataDir && !src) {
|
||||
const designerDir = getAppDataDir('Insomnia Designer');
|
||||
db = await neDbAdapter(designerDir);
|
||||
db &&
|
||||
logger.debug(
|
||||
`Data store configured from Insomnia Designer app data directory at \`${path.resolve(
|
||||
designerDir,
|
||||
)}\``,
|
||||
);
|
||||
}
|
||||
} // return empty db
|
||||
|
||||
appDataDir && logger.warn(
|
||||
|
||||
3
packages/insomnia-smoke-test/.gitignore
vendored
3
packages/insomnia-smoke-test/.gitignore
vendored
@@ -18,6 +18,3 @@ fixtures/inso-nedb/insomnia.CookieJar.db
|
||||
fixtures/inso-nedb/insomnia.GitRepository.db
|
||||
fixtures/inso-nedb/insomnia.OAuth2Token.db
|
||||
fixtures/inso-nedb/insomnia.PluginData.db
|
||||
|
||||
# ignore new database models added since designer
|
||||
fixtures/basic-designer/insomnia.Project.db
|
||||
|
||||
@@ -33,7 +33,7 @@ PWDEBUG=1 npm run test:smoke:dev # Write Insomnia tests with the
|
||||
DEBUG=pw:browser,pw:api npm run test:smoke:dev # Run Insomnia tests, with verbose output
|
||||
```
|
||||
|
||||
Sometimes, you might need to run tests against a _packaged_ application. A packaged application is the final artifact which bundles all of the various resources together, and is created for distribution in the form of a `.dmg` or `.exe`, etc. Packaging takes longer to do and is only required for edge cases (such as a <!-- TODO(TSCONVERSION) update this link -->[plugin installation](https://github.com/Kong/insomnia/blob/357b8f05f89fd5c07a75d8418670abe37b2882dc/packages/insomnia-smoke-test/designer/app.test.js#L36)), so we typically run tests against a build. To run packaged tests, from the root:
|
||||
Sometimes, you might need to run tests against a _packaged_ application. A packaged application is the final artifact which bundles all of the various resources together, and is created for distribution in the form of a `.dmg` or `.exe`, etc. Packaging takes longer to do and is only required for edge cases, so we typically run tests against a build. To run packaged tests, from the root:
|
||||
|
||||
```shell
|
||||
npm run app-package:smoke # Package Insomnia
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
{"_id":"spc_bf4e17489f7c49cfb74a6722744066b2","type":"ApiSpec","parentId":"wrk_53481b87089c49008da88e2ebf48438e","modified":1613973681201,"created":1613973668125,"fileName":"BASIC-DESIGNER-FIXTURE","contents":"","contentType":"yaml"}
|
||||
@@ -1 +0,0 @@
|
||||
{"_id":"jar_6fa8be5aaab927c09ca7f5871d995217a548e272","type":"CookieJar","parentId":"wrk_53481b87089c49008da88e2ebf48438e","modified":1613973668156,"created":1613973668156,"name":"Default Jar","cookies":[]}
|
||||
@@ -1 +0,0 @@
|
||||
{"_id":"env_6fa8be5aaab927c09ca7f5871d995217a548e272","type":"Environment","parentId":"wrk_53481b87089c49008da88e2ebf48438e","modified":1613973668154,"created":1613973668154,"name":"Base Environment","data":{},"dataPropertyOrder":null,"color":null,"isPrivate":false,"metaSortKey":1613973668154}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,2 +0,0 @@
|
||||
{"_id":"sta_380865ffe61042d0a73454aaed572db4","type":"Stats","parentId":null,"modified":1613973665818,"created":1613973665814,"currentLaunch":1613973665817,"lastLaunch":null,"currentVersion":"2020.5.2","lastVersion":null,"launches":1,"createdRequests":0,"deletedRequests":0,"executedRequests":0}
|
||||
{"_id":"sta_380865ffe61042d0a73454aaed572db4","type":"Stats","parentId":null,"modified":1613974089067,"created":1613973665814,"currentLaunch":1613974089067,"lastLaunch":1613973665817,"currentVersion":"2020.5.2","lastVersion":"2020.5.2","launches":2,"createdRequests":0,"deletedRequests":0,"executedRequests":0}
|
||||
@@ -1 +0,0 @@
|
||||
{"_id":"wrk_53481b87089c49008da88e2ebf48438e","type":"Workspace","parentId":null,"modified":1613973668125,"created":1613973668125,"name":"BASIC-DESIGNER-FIXTURE","description":"","scope":"spec"}
|
||||
@@ -1 +0,0 @@
|
||||
{"_id":"wrkm_5200884fd0f449458e8f7eec6ddca28d","type":"WorkspaceMeta","parentId":"wrk_53481b87089c49008da88e2ebf48438e","modified":1613973668157,"created":1613973668157,"activeActivity":null,"activeEnvironmentId":null,"activeRequestId":null,"activeUnitTestSuiteId":null,"cachedGitLastAuthor":null,"cachedGitLastCommitTime":null,"cachedGitRepositoryBranch":null,"gitRepositoryId":null,"hasSeen":true,"paneHeight":0.5,"paneWidth":0.5,"previewHidden":false,"sidebarFilter":"","sidebarHidden":false,"sidebarWidth":19}
|
||||
@@ -10,7 +10,6 @@ export const loadFixture = async (fixturePath: string) => {
|
||||
};
|
||||
|
||||
export const randomDataPath = () => path.join(os.tmpdir(), 'insomnia-smoke-test', `${uuid.v4()}`);
|
||||
export const DESIGNER_DATA_PATH = path.join(__dirname, '..', 'fixtures', 'basic-designer');
|
||||
export const INSOMNIA_DATA_PATH = randomDataPath();
|
||||
|
||||
const pathLookup = {
|
||||
|
||||
@@ -1,30 +1,24 @@
|
||||
// Read more about creating fixtures https://playwright.dev/docs/test-fixtures
|
||||
import { ElectronApplication, Page, test as baseTest } from '@playwright/test';
|
||||
import { ElectronApplication, test as baseTest } from '@playwright/test';
|
||||
import { platform } from 'os';
|
||||
|
||||
import {
|
||||
cwd,
|
||||
DESIGNER_DATA_PATH,
|
||||
executablePath,
|
||||
INSOMNIA_DATA_PATH,
|
||||
mainPath,
|
||||
randomDataPath,
|
||||
} from './paths';
|
||||
|
||||
interface EnvOptions {
|
||||
INSOMNIA_DATA_PATH: string;
|
||||
DESIGNER_DATA_PATH?: string;
|
||||
}
|
||||
|
||||
export const test = baseTest.extend<{
|
||||
app: ElectronApplication;
|
||||
appWithDesignerDataPath: ElectronApplication;
|
||||
pageWithDesignerDataPath: Page;
|
||||
}>({
|
||||
app: async ({ playwright }, use) => {
|
||||
const options: EnvOptions = {
|
||||
INSOMNIA_DATA_PATH: randomDataPath(),
|
||||
DESIGNER_DATA_PATH: 'doesnt-exist',
|
||||
};
|
||||
|
||||
const electronApp = await playwright._electron.launch({
|
||||
@@ -54,39 +48,6 @@ export const test = baseTest.extend<{
|
||||
|
||||
await use(page);
|
||||
|
||||
await page.close();
|
||||
},
|
||||
appWithDesignerDataPath: async ({ playwright }, use) => {
|
||||
const options: EnvOptions = {
|
||||
INSOMNIA_DATA_PATH,
|
||||
DESIGNER_DATA_PATH,
|
||||
};
|
||||
|
||||
const electronApp = await playwright._electron.launch({
|
||||
cwd,
|
||||
executablePath,
|
||||
args: process.env.BUNDLE === 'package' ? [] : [mainPath],
|
||||
env: {
|
||||
...process.env,
|
||||
...options,
|
||||
PLAYWRIGHT: 'true',
|
||||
},
|
||||
});
|
||||
|
||||
await use(electronApp);
|
||||
|
||||
// Closing the window (page) doesn't close the app on osx
|
||||
if (platform() === 'darwin') {
|
||||
await electronApp.close();
|
||||
}
|
||||
},
|
||||
pageWithDesignerDataPath: async ({ appWithDesignerDataPath }, use) => {
|
||||
const page = await appWithDesignerDataPath.firstWindow();
|
||||
|
||||
if (process.platform === 'win32') await page.reload();
|
||||
|
||||
await use(page);
|
||||
|
||||
await page.close();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -31,18 +31,3 @@ test('can send requests', async ({ app, page }) => {
|
||||
await page.click('text=http://127.0.0.1:4010/auth/basicSend >> button');
|
||||
await page.click('text=200 OK');
|
||||
});
|
||||
|
||||
test.describe.serial('given a designer and data directory', () => {
|
||||
test('should complete migration dialog', async ({ pageWithDesignerDataPath: page }) => {
|
||||
await page.click('text=Copy Workspaces');
|
||||
await page.click('text=Copy Plugins');
|
||||
await page.click('text=Copy Designer Application Settings');
|
||||
await page.click('text=Start Migration');
|
||||
await page.click('text=Migrated successfully!');
|
||||
});
|
||||
|
||||
test('then on restart should see the migrated workspace', async ({ pageWithDesignerDataPath: page }) => {
|
||||
await page.click('text=Don\'t share usage analytics');
|
||||
await page.click('text=BASIC-DESIGNER-FIXTURE');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
"include": [
|
||||
"cli",
|
||||
"core",
|
||||
"designer",
|
||||
"fixtures",
|
||||
"modules",
|
||||
"server"
|
||||
|
||||
Reference in New Issue
Block a user