mirror of
https://github.com/strapi/strapi.git
synced 2025-09-26 00:39:49 +00:00
Add tests and refactor
This commit is contained in:
parent
63d58433fc
commit
4190687975
@ -338,28 +338,23 @@ class TransferEngine<
|
|||||||
async transfer(): Promise<ITransferResults<S, D>> {
|
async transfer(): Promise<ITransferResults<S, D>> {
|
||||||
try {
|
try {
|
||||||
await this.bootstrap();
|
await this.bootstrap();
|
||||||
await this.init();
|
// await this.init();
|
||||||
|
// const isValidTransfer = await this.integrityCheck();
|
||||||
const isValidTransfer = await this.integrityCheck();
|
// if (!isValidTransfer) {
|
||||||
|
// // TODO: provide the log from the integrity check
|
||||||
if (!isValidTransfer) {
|
// throw new Error(
|
||||||
// TODO: provide the log from the integrity check
|
// `Unable to transfer the data between ${this.sourceProvider.name} and ${this.destinationProvider.name}.\nPlease refer to the log above for more information.`
|
||||||
throw new Error(
|
// );
|
||||||
`Unable to transfer the data between ${this.sourceProvider.name} and ${this.destinationProvider.name}.\nPlease refer to the log above for more information.`
|
// }
|
||||||
);
|
// await this.beforeTransfer();
|
||||||
}
|
|
||||||
|
|
||||||
await this.beforeTransfer();
|
|
||||||
|
|
||||||
// Run the transfer stages
|
// Run the transfer stages
|
||||||
await this.transferSchemas();
|
// await this.transferSchemas();
|
||||||
await this.transferEntities();
|
// await this.transferEntities();
|
||||||
await this.transferAssets();
|
// await this.transferAssets();
|
||||||
await this.transferLinks();
|
// await this.transferLinks();
|
||||||
await this.transferConfiguration();
|
// await this.transferConfiguration();
|
||||||
|
|
||||||
// Gracefully close the providers
|
// Gracefully close the providers
|
||||||
await this.close();
|
// await this.close();
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
// Rollback the destination provider if an exception is thrown during the transfer
|
// Rollback the destination provider if an exception is thrown during the transfer
|
||||||
// Note: This will be configurable in the future
|
// Note: This will be configurable in the future
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
import type { IRemoteStrapiDestinationProviderOptions } from '..';
|
||||||
|
|
||||||
|
import { createRemoteStrapiDestinationProvider } from '..';
|
||||||
|
|
||||||
|
const defaultOptions: IRemoteStrapiDestinationProviderOptions = {
|
||||||
|
strategy: 'restore',
|
||||||
|
url: 'ws://test.com/admin/transfer',
|
||||||
|
};
|
||||||
|
|
||||||
|
jest.mock('../utils', () => ({
|
||||||
|
dispatch: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('ws', () => ({
|
||||||
|
WebSocket: jest.fn().mockImplementation(() => {
|
||||||
|
return {
|
||||||
|
...jest.requireActual('ws').WebSocket,
|
||||||
|
send: jest.fn(),
|
||||||
|
once: jest.fn((type, callback) => {
|
||||||
|
callback();
|
||||||
|
return {
|
||||||
|
once: jest.fn((t, c) => c),
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Remote Strapi Destination', () => {
|
||||||
|
describe('Bootstrap', () => {
|
||||||
|
test('Should not have a defined websocket connection if bootstrap has not been called', () => {
|
||||||
|
const provider = createRemoteStrapiDestinationProvider(defaultOptions);
|
||||||
|
|
||||||
|
expect(provider.ws).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Should have a defined websocket connection if bootstrap has been called', async () => {
|
||||||
|
const provider = createRemoteStrapiDestinationProvider(defaultOptions);
|
||||||
|
await provider.bootstrap();
|
||||||
|
|
||||||
|
expect(provider.ws).not.toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,43 @@
|
|||||||
|
import { WebSocket } from 'ws';
|
||||||
|
import { dispatch } from '../utils';
|
||||||
|
|
||||||
|
jest.mock('ws', () => ({
|
||||||
|
WebSocket: jest.fn().mockImplementation(() => {
|
||||||
|
return {
|
||||||
|
...jest.requireActual('ws').WebSocket,
|
||||||
|
send: jest.fn(),
|
||||||
|
once: jest.fn(),
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Remote Strapi Destination Utils', () => {
|
||||||
|
test('Dispatch method sends payload', () => {
|
||||||
|
const ws = new WebSocket('ws://test/admin/transfer');
|
||||||
|
const message = {
|
||||||
|
test: 'hello',
|
||||||
|
};
|
||||||
|
|
||||||
|
dispatch(ws, message);
|
||||||
|
|
||||||
|
expect.extend({
|
||||||
|
toContain(receivedString, expected) {
|
||||||
|
const jsonReceived = JSON.parse(receivedString);
|
||||||
|
const pass = Object.keys(expected).every((key) => jsonReceived[key] === expected[key]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: () =>
|
||||||
|
`Expected ${jsonReceived} ${!pass && 'not'} to contain properties ${expected}`,
|
||||||
|
pass,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
expect(ws.send).toHaveBeenCalledWith(expect.toContain(message), expect.anything());
|
||||||
|
});
|
||||||
|
});
|
@ -13,6 +13,7 @@ import type {
|
|||||||
IAsset,
|
IAsset,
|
||||||
} from '../../../types';
|
} from '../../../types';
|
||||||
import type { ILocalStrapiDestinationProviderOptions } from '../local-strapi-destination-provider';
|
import type { ILocalStrapiDestinationProviderOptions } from '../local-strapi-destination-provider';
|
||||||
|
import { dispatch } from './utils';
|
||||||
|
|
||||||
interface ITokenAuth {
|
interface ITokenAuth {
|
||||||
type: 'token';
|
type: 'token';
|
||||||
@ -25,7 +26,7 @@ interface ICredentialsAuth {
|
|||||||
password: string;
|
password: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IRemoteStrapiDestinationProvider
|
export interface IRemoteStrapiDestinationProviderOptions
|
||||||
extends Pick<ILocalStrapiDestinationProviderOptions, 'restore' | 'strategy'> {
|
extends Pick<ILocalStrapiDestinationProviderOptions, 'restore' | 'strategy'> {
|
||||||
url: string;
|
url: string;
|
||||||
auth?: ITokenAuth | ICredentialsAuth;
|
auth?: ITokenAuth | ICredentialsAuth;
|
||||||
@ -34,7 +35,7 @@ interface IRemoteStrapiDestinationProvider
|
|||||||
type Actions = 'bootstrap' | 'close' | 'beforeTransfer' | 'getMetadata' | 'getSchemas';
|
type Actions = 'bootstrap' | 'close' | 'beforeTransfer' | 'getMetadata' | 'getSchemas';
|
||||||
|
|
||||||
export const createRemoteStrapiDestinationProvider = (
|
export const createRemoteStrapiDestinationProvider = (
|
||||||
options: IRemoteStrapiDestinationProvider
|
options: IRemoteStrapiDestinationProviderOptions
|
||||||
) => {
|
) => {
|
||||||
return new RemoteStrapiDestinationProvider(options);
|
return new RemoteStrapiDestinationProvider(options);
|
||||||
};
|
};
|
||||||
@ -44,61 +45,28 @@ class RemoteStrapiDestinationProvider implements IDestinationProvider {
|
|||||||
|
|
||||||
type: ProviderType = 'destination';
|
type: ProviderType = 'destination';
|
||||||
|
|
||||||
options: IRemoteStrapiDestinationProvider;
|
options: IRemoteStrapiDestinationProviderOptions;
|
||||||
|
|
||||||
ws: WebSocket | null;
|
ws: WebSocket | null;
|
||||||
|
|
||||||
constructor(options: IRemoteStrapiDestinationProvider) {
|
constructor(options: IRemoteStrapiDestinationProviderOptions) {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.ws = null;
|
this.ws = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async #dispatch<U = unknown, T extends object = object>(message: T): Promise<U> {
|
|
||||||
const { ws } = this;
|
|
||||||
|
|
||||||
if (!ws) {
|
|
||||||
throw new Error('No ws connection found');
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const uuid = v4();
|
|
||||||
const payload = JSON.stringify({ ...message, uuid });
|
|
||||||
|
|
||||||
ws.send(payload, (error) => {
|
|
||||||
if (error) {
|
|
||||||
reject(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ws.once('message', (raw) => {
|
|
||||||
const response: { uuid: string; data: U; error: string | null } = JSON.parse(
|
|
||||||
raw.toString()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.error) {
|
|
||||||
return reject(new Error(response.error));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.uuid === uuid) {
|
|
||||||
return resolve(response.data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async #dispatchAction<T = unknown>(action: Actions) {
|
async #dispatchAction<T = unknown>(action: Actions) {
|
||||||
return this.#dispatch<T>({ type: 'action', action });
|
return dispatch<T>(this.ws, { type: 'action', action });
|
||||||
}
|
}
|
||||||
|
|
||||||
async #dispatchTransfer<T = unknown>(stage: TransferStage, data: T) {
|
async #dispatchTransfer<T = unknown>(stage: TransferStage, data: T) {
|
||||||
try {
|
try {
|
||||||
await this.#dispatch({ type: 'transfer', stage, data });
|
await dispatch(this.ws, { type: 'transfer', stage, data });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof Error) {
|
if (e instanceof Error) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Error('Unexected error');
|
return new Error('Unexpected error');
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -131,7 +99,7 @@ class RemoteStrapiDestinationProvider implements IDestinationProvider {
|
|||||||
// Wait for the connection to be made to the server, then init the transfer
|
// Wait for the connection to be made to the server, then init the transfer
|
||||||
await new Promise<void>((resolve, reject) => {
|
await new Promise<void>((resolve, reject) => {
|
||||||
ws.once('open', async () => {
|
ws.once('open', async () => {
|
||||||
await this.#dispatch({ type: 'init', kind: 'push', data: { strategy, restore } });
|
await dispatch(this.ws, { type: 'init', kind: 'push', data: { strategy, restore } });
|
||||||
resolve();
|
resolve();
|
||||||
}).once('error', reject);
|
}).once('error', reject);
|
||||||
});
|
});
|
||||||
@ -204,6 +172,7 @@ class RemoteStrapiDestinationProvider implements IDestinationProvider {
|
|||||||
return new Writable({
|
return new Writable({
|
||||||
objectMode: true,
|
objectMode: true,
|
||||||
final: async (callback) => {
|
final: async (callback) => {
|
||||||
|
console.log('FINAL');
|
||||||
const e = await this.#dispatchTransfer('assets', null);
|
const e = await this.#dispatchTransfer('assets', null);
|
||||||
callback(e);
|
callback(e);
|
||||||
},
|
},
|
||||||
@ -217,6 +186,8 @@ class RemoteStrapiDestinationProvider implements IDestinationProvider {
|
|||||||
data: { filename, filepath, stats },
|
data: { filename, filepath, stats },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log('is writing');
|
||||||
|
|
||||||
for await (const chunk of stream) {
|
for await (const chunk of stream) {
|
||||||
await this.#dispatchTransfer('assets', {
|
await this.#dispatchTransfer('assets', {
|
||||||
step: 'stream',
|
step: 'stream',
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
import { v4 } from 'uuid';
|
||||||
|
import { WebSocket } from 'ws';
|
||||||
|
|
||||||
|
export async function dispatch<U = unknown, T extends object = object>(
|
||||||
|
ws: WebSocket | null,
|
||||||
|
message: T
|
||||||
|
): Promise<U> {
|
||||||
|
if (!ws) {
|
||||||
|
throw new Error('No websocket connection found');
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const uuid = v4();
|
||||||
|
const payload = JSON.stringify({ ...message, uuid });
|
||||||
|
|
||||||
|
ws.send(payload, (error) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ws.once('message', (raw) => {
|
||||||
|
const response: { uuid: string; data: U; error: string | null } = JSON.parse(raw.toString());
|
||||||
|
|
||||||
|
if (response.error) {
|
||||||
|
return reject(new Error(response.error));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.uuid === uuid) {
|
||||||
|
return resolve(response.data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
@ -5,12 +5,9 @@ import { Writable, PassThrough } from 'stream';
|
|||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
import {
|
import {
|
||||||
IAsset,
|
IAsset,
|
||||||
IConfiguration,
|
|
||||||
Message,
|
Message,
|
||||||
ILink,
|
|
||||||
IMetadata,
|
IMetadata,
|
||||||
PushTransferMessage,
|
PushTransferMessage,
|
||||||
PushEntitiesTransferMessage,
|
|
||||||
TransferKind,
|
TransferKind,
|
||||||
InitMessage,
|
InitMessage,
|
||||||
PushTransferStage,
|
PushTransferStage,
|
||||||
@ -38,8 +35,8 @@ interface IPushController {
|
|||||||
beforeTransfer(): Promise<void>;
|
beforeTransfer(): Promise<void>;
|
||||||
};
|
};
|
||||||
transfer: {
|
transfer: {
|
||||||
[key in PushTransferStage]: <T extends PushTransferMessage, P extends PushTransferStage = key>(
|
[key in PushTransferStage]: <T extends PushTransferMessage>(
|
||||||
value: T extends { stage: P; data: infer U } ? U : never
|
value: T extends { stage: key; data: infer U } ? U : never
|
||||||
) => Promise<void>;
|
) => Promise<void>;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -66,7 +63,7 @@ const createPushController = (options: ILocalStrapiDestinationProviderOptions):
|
|||||||
streams,
|
streams,
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
async getSchemas() {
|
async getSchemas(): Promise<Strapi.Schemas> {
|
||||||
return provider.getSchemas();
|
return provider.getSchemas();
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -112,35 +109,35 @@ const createPushController = (options: ILocalStrapiDestinationProviderOptions):
|
|||||||
await writeAsync(streams.configuration!, config);
|
await writeAsync(streams.configuration!, config);
|
||||||
},
|
},
|
||||||
|
|
||||||
async assets(asset: any) {
|
async assets(payload) {
|
||||||
if (asset === null) {
|
console.log('llega');
|
||||||
|
if (payload === null) {
|
||||||
streams.assets?.end();
|
streams.assets?.end();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { step, assetID } = asset;
|
const { step, assetID } = payload;
|
||||||
|
|
||||||
if (!streams.assets) {
|
if (!streams.assets) {
|
||||||
streams.assets = await provider.getAssetsStream();
|
streams.assets = await provider.getAssetsStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
// on init, we create a passthrough stream for the asset chunks
|
|
||||||
// send to the assets destination stream the metadata for the current asset
|
|
||||||
// + the stream that we just created for the asset
|
|
||||||
if (step === 'start') {
|
if (step === 'start') {
|
||||||
assets[assetID] = { ...asset.data, stream: new PassThrough() };
|
assets[assetID] = { ...payload.data, stream: new PassThrough() };
|
||||||
writeAsync(streams.assets!, assets[assetID]);
|
writeAsync(streams.assets, assets[assetID]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// propagate the chunk
|
|
||||||
if (step === 'stream') {
|
if (step === 'stream') {
|
||||||
await writeAsync(assets[assetID].stream, Buffer.from(asset.data.chunk));
|
const chunk = Buffer.from(payload.data.chunk.data);
|
||||||
|
|
||||||
|
await writeAsync(assets[assetID].stream, chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
// on end, we indicate that all the chunks have been sent
|
|
||||||
if (step === 'end') {
|
if (step === 'end') {
|
||||||
await new Promise<void>((resolve, reject) => {
|
await new Promise<void>((resolve, reject) => {
|
||||||
assets[assetID].stream
|
const { stream } = assets[assetID];
|
||||||
|
|
||||||
|
stream
|
||||||
.on('close', () => {
|
.on('close', () => {
|
||||||
delete assets[assetID];
|
delete assets[assetID];
|
||||||
resolve();
|
resolve();
|
||||||
@ -271,11 +268,9 @@ const createTransferController =
|
|||||||
|
|
||||||
if (msg.type === 'transfer') {
|
if (msg.type === 'transfer') {
|
||||||
await answer(() => {
|
await answer(() => {
|
||||||
const fn = state.controller?.transfer[msg.stage];
|
const { stage, data } = msg;
|
||||||
|
|
||||||
type Msg = typeof msg;
|
return state.controller?.transfer[stage](data as never);
|
||||||
|
|
||||||
fn?.<Msg, Msg['stage']>(msg.data);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -299,18 +294,3 @@ const register = (strapi: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default register;
|
export default register;
|
||||||
|
|
||||||
/**
|
|
||||||
* entities:start
|
|
||||||
* entities:transfer
|
|
||||||
* entities:end
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* assets:start
|
|
||||||
*
|
|
||||||
* assets:transfer:start
|
|
||||||
* assets:transfer:stream
|
|
||||||
* assets:transfer:end
|
|
||||||
*
|
|
||||||
* assets:end
|
|
||||||
*/
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const utils = require('../transfer/utils');
|
const utils = require('../../transfer/utils');
|
||||||
|
|
||||||
const mockDataTransfer = {
|
const mockDataTransfer = {
|
||||||
createLocalFileDestinationProvider: jest.fn(),
|
createLocalFileDestinationProvider: jest.fn(),
|
||||||
@ -18,12 +18,12 @@ jest.mock(
|
|||||||
{ virtual: true }
|
{ virtual: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
const exportCommand = require('../transfer/export');
|
const exportCommand = require('../../transfer/export');
|
||||||
|
|
||||||
const exit = jest.spyOn(process, 'exit').mockImplementation(() => {});
|
const exit = jest.spyOn(process, 'exit').mockImplementation(() => {});
|
||||||
jest.spyOn(console, 'error').mockImplementation(() => {});
|
jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||||
|
|
||||||
jest.mock('../transfer/utils');
|
jest.mock('../../transfer/utils');
|
||||||
|
|
||||||
const defaultFileName = 'defaultFilename';
|
const defaultFileName = 'defaultFilename';
|
||||||
|
|
@ -0,0 +1,98 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const utils = require('../../transfer/utils');
|
||||||
|
|
||||||
|
const mockDataTransfer = {
|
||||||
|
createRemoteStrapiDestinationProvider: jest.fn(),
|
||||||
|
createLocalStrapiSourceProvider: jest.fn(),
|
||||||
|
createTransferEngine: jest.fn().mockReturnValue({
|
||||||
|
transfer: jest.fn().mockReturnValue(Promise.resolve({})),
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
jest.mock(
|
||||||
|
'@strapi/data-transfer',
|
||||||
|
() => {
|
||||||
|
return mockDataTransfer;
|
||||||
|
},
|
||||||
|
{ virtual: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
const transferCommand = require('../../transfer/transfer');
|
||||||
|
|
||||||
|
const exit = jest.spyOn(process, 'exit').mockImplementation(() => {});
|
||||||
|
jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||||
|
|
||||||
|
jest.mock('../../transfer/utils');
|
||||||
|
|
||||||
|
const destinationUrl = 'ws://strapi.com';
|
||||||
|
|
||||||
|
describe('transfer', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.resetAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('uses destination url provided by user without authentication', async () => {
|
||||||
|
await transferCommand({ from: 'local', to: destinationUrl });
|
||||||
|
|
||||||
|
expect(mockDataTransfer.createRemoteStrapiDestinationProvider).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
url: destinationUrl,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(exit).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('uses destination url provided by user with authentication', async () => {
|
||||||
|
// TODO when authentication is implemented
|
||||||
|
});
|
||||||
|
|
||||||
|
it('uses restore as the default strategy', async () => {
|
||||||
|
await transferCommand({ from: 'local', to: destinationUrl });
|
||||||
|
|
||||||
|
expect(mockDataTransfer.createRemoteStrapiDestinationProvider).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
strategy: 'restore',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('uses destination url provided by user without authentication', async () => {
|
||||||
|
await transferCommand({ from: 'local', to: destinationUrl });
|
||||||
|
|
||||||
|
expect(mockDataTransfer.createRemoteStrapiDestinationProvider).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
url: destinationUrl,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(exit).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('uses destination url provided by user with authentication', async () => {
|
||||||
|
// TODO when authentication is implemented
|
||||||
|
});
|
||||||
|
|
||||||
|
it('uses restore as the default strategy', async () => {
|
||||||
|
await transferCommand({ from: 'local', to: destinationUrl });
|
||||||
|
|
||||||
|
expect(mockDataTransfer.createRemoteStrapiDestinationProvider).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
strategy: 'restore',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('uses local strapi instance when local specified', async () => {
|
||||||
|
await transferCommand({ from: 'local', to: destinationUrl });
|
||||||
|
|
||||||
|
expect(mockDataTransfer.createLocalStrapiSourceProvider).toHaveBeenCalled();
|
||||||
|
expect(utils.createStrapiInstance).toHaveBeenCalled();
|
||||||
|
|
||||||
|
expect(exit).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates the transfer engine successfully', async () => {
|
||||||
|
await transferCommand({ from: 'local', to: destinationUrl });
|
||||||
|
});
|
||||||
|
});
|
@ -17,12 +17,10 @@ const {
|
|||||||
} = require('./utils');
|
} = require('./utils');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef ImportCommandOptions Options given to the CLI import command
|
* @typedef TransferCommandOptions Options given to the CLI import command
|
||||||
*
|
*
|
||||||
* @property {string} [file] The file path to import
|
* @property {string} [from] The source strapi project
|
||||||
* @property {boolean} [encrypt] Used to encrypt the final archive
|
* @property {string} [to] The destination strapi project
|
||||||
* @property {string} [key] Encryption key, only useful when encryption is enabled
|
|
||||||
* @property {boolean} [compress] Used to compress the final archive
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const logger = console;
|
const logger = console;
|
||||||
@ -32,7 +30,7 @@ const logger = console;
|
|||||||
*
|
*
|
||||||
* It transfers data from a local file to a local strapi instance
|
* It transfers data from a local file to a local strapi instance
|
||||||
*
|
*
|
||||||
* @param {ImportCommandOptions} opts
|
* @param {TransferCommandOptions} opts
|
||||||
*/
|
*/
|
||||||
module.exports = async (opts) => {
|
module.exports = async (opts) => {
|
||||||
// Validate inputs from Commander
|
// Validate inputs from Commander
|
||||||
|
Loading…
x
Reference in New Issue
Block a user