Skip to content

Commit 6fb1d32

Browse files
committed
fix: resolve default site directory dynamically
1 parent 66551f4 commit 6fb1d32

File tree

5 files changed

+121
-29
lines changed

5 files changed

+121
-29
lines changed

apps/studio/src/ipc-handlers.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,7 @@ import { supportedEditorConfig, SupportedEditor } from 'src/modules/user-setting
8787
import { getUserEditor, getUserTerminal } from 'src/modules/user-settings/lib/ipc-handlers';
8888
import { winFindEditorPath } from 'src/modules/user-settings/lib/win-editor-path';
8989
import { SiteServer, stopAllServers as triggerStopAllServers } from 'src/site-server';
90-
import {
91-
DEFAULT_SITE_PATH,
92-
getSiteThumbnailPath,
93-
resolveDefaultSiteDirectory,
94-
} from 'src/storage/paths';
90+
import { getSiteThumbnailPath, resolveDefaultSiteDirectory } from 'src/storage/paths';
9591
import {
9692
loadUserData,
9793
lockAppdata,
@@ -700,7 +696,8 @@ export async function copySite(
700696
}
701697
const sourceSite = sourceServer.details;
702698

703-
const finalSitePath = nodePath.join( DEFAULT_SITE_PATH, sanitizeFolderName( siteName ) );
699+
const defaultSiteDirectory = await resolveDefaultSiteDirectory();
700+
const finalSitePath = nodePath.join( defaultSiteDirectory, sanitizeFolderName( siteName ) );
704701

705702
console.log( `Copying site '${ sourceSite.name }' to '${ siteName }'` );
706703

apps/studio/src/storage/paths.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export function getUserDataCertificatesPath(): string {
3636
return path.join( getAppDataPath(), getAppName(), 'certificates' );
3737
}
3838

39-
export const DEFAULT_SITE_PATH = path.join(
39+
const defaultSitePath = path.join(
4040
( process.env.E2E && process.env.E2E_HOME_PATH
4141
? process.env.E2E_HOME_PATH
4242
: app?.getPath( 'home' ) ) || '',
@@ -155,5 +155,5 @@ export async function resolveDefaultSiteDirectory(): Promise< string > {
155155
}
156156
}
157157

158-
return DEFAULT_SITE_PATH;
158+
return defaultSitePath;
159159
}

apps/studio/src/tests/index.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ vi.mock( 'src/storage/paths', () => ( {
3939
getCliPath: vi.fn().mockReturnValue( '/mock/cli/path' ),
4040
getBundledNodeBinaryPath: vi.fn().mockReturnValue( '/mock/node/binary' ),
4141
getSiteThumbnailPath: vi.fn().mockReturnValue( '/mock/thumbnail.png' ),
42-
DEFAULT_SITE_PATH: '/mock/default/site/path',
42+
resolveDefaultSiteDirectory: vi.fn().mockResolvedValue( '/mock/default/site/path' ),
4343
} ) );
4444
vi.mock( 'src/modules/cli/lib/execute-command', () => {
4545
const mockEventEmitter = {

apps/studio/src/tests/ipc-handlers.test.ts

Lines changed: 114 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import fs from 'fs';
66
import { normalize } from 'path';
77
import * as Sentry from '@sentry/electron/main';
88
import { bumpStat } from '@studio/common/lib/bump-stat';
9+
import { recursiveCopyDirectory } from '@studio/common/lib/fs-utils';
910
import { StatsGroup, StatsMetric } from '@studio/common/types/stats';
1011
import { readFile } from 'atomically';
1112
import { vi } from 'vitest';
@@ -14,12 +15,16 @@ import {
1415
isFullscreen,
1516
importSite,
1617
getXdebugEnabledSite,
18+
copySite,
1719
loadThemeDetails,
1820
} from 'src/ipc-handlers';
1921
import { importBackup, defaultImporterOptions } from 'src/lib/import-export/import/import-manager';
2022
import { BackupArchiveInfo } from 'src/lib/import-export/import/types';
2123
import { getMainWindow } from 'src/main-window';
2224
import { SiteServer } from 'src/site-server';
25+
import { resolveDefaultSiteDirectory } from 'src/storage/paths';
26+
import { loadUserData } from 'src/storage/user-data';
27+
import type { UserData } from 'src/storage/storage-types';
2328

2429
vi.mock( 'fs' );
2530
vi.mock( 'fs-extra' );
@@ -37,7 +42,14 @@ vi.mock( 'src/storage/paths', () => ( {
3742
getCliPath: vi.fn().mockReturnValue( '/mock/cli/path' ),
3843
getBundledNodeBinaryPath: vi.fn().mockReturnValue( '/mock/node/binary' ),
3944
getSiteThumbnailPath: vi.fn().mockReturnValue( '/mock/thumbnail.png' ),
40-
DEFAULT_SITE_PATH: '/mock/default/site/path',
45+
resolveDefaultSiteDirectory: vi.fn().mockResolvedValue( '/mock/default/site/path' ),
46+
} ) );
47+
vi.mock( 'src/storage/user-data', () => ( {
48+
loadUserData: vi.fn().mockResolvedValue( { sites: [] } ),
49+
saveUserData: vi.fn().mockResolvedValue( undefined ),
50+
lockAppdata: vi.fn().mockResolvedValue( undefined ),
51+
unlockAppdata: vi.fn().mockResolvedValue( undefined ),
52+
updateAppdata: vi.fn().mockResolvedValue( undefined ),
4153
} ) );
4254
vi.mock( 'src/site-server' );
4355
vi.mock( 'src/lib/wordpress-setup', () => ( {
@@ -266,17 +278,69 @@ describe( 'importSite', () => {
266278
} );
267279
} );
268280

281+
describe( 'copySite', () => {
282+
it( 'uses the resolved default site directory for the new path', async () => {
283+
const sourceSite = {
284+
details: {
285+
id: 'source-site-id',
286+
name: 'Source Site',
287+
path: '/source/path',
288+
port: 9998,
289+
phpVersion: '8.3',
290+
running: false,
291+
adminPassword: 'source-password',
292+
themeDetails: { name: 'Theme', path: '/themes/theme' },
293+
},
294+
};
295+
296+
vi.mocked( SiteServer.get, { partial: true } ).mockReturnValue(
297+
sourceSite as unknown as SiteServer
298+
);
299+
vi.mocked( recursiveCopyDirectory ).mockResolvedValue( undefined );
300+
vi.mocked( resolveDefaultSiteDirectory ).mockResolvedValue( '/mock/default/site/path' );
301+
vi.mocked( fs.existsSync ).mockReturnValue( false );
302+
303+
const result = await copySite(
304+
mockIpcMainInvokeEvent,
305+
'source-site-id',
306+
'new-site-id',
307+
'MySite'
308+
);
309+
310+
expect( resolveDefaultSiteDirectory ).toHaveBeenCalled();
311+
expect( recursiveCopyDirectory ).toHaveBeenCalledWith(
312+
sourceSite.details.path,
313+
'/mock/default/site/path/mysite'
314+
);
315+
expect( result.path ).toBe( '/mock/default/site/path/mysite' );
316+
} );
317+
} );
318+
269319
describe( 'getXdebugEnabledSite', () => {
270320
it( 'should return null when no site has Xdebug enabled', async () => {
271-
const mockUserDataWithoutXdebug = {
321+
const mockUserDataWithoutXdebug: UserData = {
272322
sites: [
273-
{ id: 'site-1', name: 'Site 1', path: '/path/to/site-1', enableXdebug: false },
274-
{ id: 'site-2', name: 'Site 2', path: '/path/to/site-2' },
323+
{
324+
id: 'site-1',
325+
name: 'Site 1',
326+
path: '/path/to/site-1',
327+
enableXdebug: false,
328+
running: false as const,
329+
port: 9999,
330+
phpVersion: '8.3',
331+
},
332+
{
333+
id: 'site-2',
334+
name: 'Site 2',
335+
path: '/path/to/site-2',
336+
running: false as const,
337+
port: 9999,
338+
phpVersion: '8.3',
339+
},
275340
],
341+
snapshots: [],
276342
};
277-
vi.mocked( readFile ).mockResolvedValue(
278-
Buffer.from( JSON.stringify( mockUserDataWithoutXdebug ) )
279-
);
343+
vi.mocked( loadUserData ).mockResolvedValue( mockUserDataWithoutXdebug );
280344
vi.mocked( fs.existsSync ).mockReturnValue( true );
281345

282346
const result = await getXdebugEnabledSite( mockIpcMainInvokeEvent );
@@ -285,15 +349,31 @@ describe( 'getXdebugEnabledSite', () => {
285349
} );
286350

287351
it( 'should return the site that has Xdebug enabled', async () => {
288-
const mockUserDataWithXdebug = {
352+
const mockUserDataWithXdebug: UserData = {
289353
sites: [
290-
{ id: 'site-1', name: 'Site 1', path: '/path/to/site-1', enableXdebug: false },
291-
{ id: 'site-2', name: 'Site 2', path: '/path/to/site-2', enableXdebug: true },
354+
{
355+
id: 'site-1',
356+
name: 'Site 1',
357+
path: '/path/to/site-1',
358+
enableXdebug: false,
359+
running: false as const,
360+
port: 9999,
361+
phpVersion: '8.3',
362+
},
363+
{
364+
id: 'site-2',
365+
name: 'Site 2',
366+
path: '/path/to/site-2',
367+
enableXdebug: true,
368+
running: true as const,
369+
port: 9999,
370+
phpVersion: '8.3',
371+
url: 'https://site-2.test',
372+
},
292373
],
374+
snapshots: [],
293375
};
294-
vi.mocked( readFile ).mockResolvedValue(
295-
Buffer.from( JSON.stringify( mockUserDataWithXdebug ) )
296-
);
376+
vi.mocked( loadUserData ).mockResolvedValue( mockUserDataWithXdebug );
297377
vi.mocked( fs.existsSync ).mockReturnValue( true );
298378
vi.mocked( SiteServer.get, { partial: true } ).mockReturnValue( {
299379
details: {
@@ -323,15 +403,30 @@ describe( 'getXdebugEnabledSite', () => {
323403
} );
324404

325405
it( 'should return the first site when multiple have Xdebug enabled', async () => {
326-
const mockUserDataWithMultipleXdebug = {
406+
const mockUserDataWithMultipleXdebug: UserData = {
327407
sites: [
328-
{ id: 'site-1', name: 'Site 1', path: '/path/to/site-1', enableXdebug: true },
329-
{ id: 'site-2', name: 'Site 2', path: '/path/to/site-2', enableXdebug: true },
408+
{
409+
id: 'site-1',
410+
name: 'Site 1',
411+
path: '/path/to/site-1',
412+
enableXdebug: true,
413+
running: false as const,
414+
port: 9999,
415+
phpVersion: '8.3',
416+
},
417+
{
418+
id: 'site-2',
419+
name: 'Site 2',
420+
path: '/path/to/site-2',
421+
enableXdebug: true,
422+
running: false as const,
423+
port: 9999,
424+
phpVersion: '8.3',
425+
},
330426
],
427+
snapshots: [],
331428
};
332-
vi.mocked( readFile ).mockResolvedValue(
333-
Buffer.from( JSON.stringify( mockUserDataWithMultipleXdebug ) )
334-
);
429+
vi.mocked( loadUserData ).mockResolvedValue( mockUserDataWithMultipleXdebug );
335430
vi.mocked( fs.existsSync ).mockReturnValue( true );
336431
vi.mocked( SiteServer.get, { partial: true } ).mockReturnValue( {
337432
details: {

apps/studio/src/tests/main-window.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ vi.mock( 'src/storage/paths', () => ( {
2424
getCliPath: vi.fn().mockReturnValue( '/mock/cli/path' ),
2525
getBundledNodeBinaryPath: vi.fn().mockReturnValue( '/mock/node/binary' ),
2626
getSiteThumbnailPath: vi.fn().mockReturnValue( '/mock/thumbnail.png' ),
27-
DEFAULT_SITE_PATH: '/mock/default/site/path',
27+
resolveDefaultSiteDirectory: vi.fn().mockResolvedValue( '/mock/default/site/path' ),
2828
} ) );
2929

3030
// Create a simpler mock that tracks event handlers

0 commit comments

Comments
 (0)