Skip to content

Commit 0b32ba9

Browse files
only expose the internal testing API when running under test
1 parent 94c9b4d commit 0b32ba9

File tree

3 files changed

+57
-14
lines changed

3 files changed

+57
-14
lines changed

src/SwiftExtensionApi.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import configuration, { handleConfigurationChangeEvent } from "./configuration";
2323
import { ContextKeys, createContextKeys } from "./contextKeys";
2424
import { registerDebugger } from "./debugger/debugAdapterFactory";
2525
import { makeDebugConfigurations } from "./debugger/launch";
26-
import { Api } from "./extension";
26+
import { InternalApi } from "./extension";
2727
import { SwiftLogger } from "./logging/SwiftLogger";
2828
import { SwiftLoggerFactory } from "./logging/SwiftLoggerFactory";
2929
import { SwiftEnvironmentVariablesManager, SwiftTerminalProfileProvider } from "./terminal";
@@ -43,7 +43,7 @@ type State = (
4343
| { type: "failed"; error: Error }
4444
) & { activatedBy: Error };
4545

46-
export class SwiftExtensionApi implements Api {
46+
export class SwiftExtensionApi implements InternalApi {
4747
private state?: State;
4848

4949
get workspaceContext(): WorkspaceContext | undefined {

src/extension.ts

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { SwiftExtensionApi } from "./SwiftExtensionApi";
2020
import { WorkspaceContext } from "./WorkspaceContext";
2121
import { ContextKeys } from "./contextKeys";
2222
import { SwiftLogger } from "./logging/SwiftLogger";
23+
import { IS_RUNNING_UNDER_TEST } from "./utilities/utilities";
2324

2425
/**
2526
* External API as exposed by the extension. Can be queried by other extensions
@@ -64,7 +65,9 @@ export interface Api {
6465
task: (ctx: WorkspaceContext) => T | Promise<T>,
6566
token?: vscode.CancellationToken
6667
): Promise<T>;
68+
}
6769

70+
export interface InternalApi extends Api {
6871
/**
6972
* Activate the extension.
7073
*
@@ -89,18 +92,52 @@ export interface Api {
8992
dispose(): void;
9093
}
9194

92-
let extensionApi: Api | undefined = undefined;
95+
let extensionApi: InternalApi | undefined = undefined;
9396

9497
/**
9598
* Activate the extension. This is the main entry point.
9699
*/
97100
export async function activate(context: vscode.ExtensionContext): Promise<Api> {
98101
extensionApi = new SwiftExtensionApi(context);
99102
extensionApi.activate();
100-
return extensionApi;
103+
// When testing, expose the internal API for testing purposes
104+
if (IS_RUNNING_UNDER_TEST) {
105+
return extensionApi;
106+
}
107+
// Otherwise, hide the internal API using a proxy
108+
return {
109+
get contextKeys() {
110+
if (!extensionApi) {
111+
throw Error("The Swift extension has been deactivated.");
112+
}
113+
return extensionApi.contextKeys;
114+
},
115+
116+
get logger() {
117+
if (!extensionApi) {
118+
throw Error("The Swift extension has been deactivated.");
119+
}
120+
return extensionApi.logger;
121+
},
122+
123+
get waitForWorkspaceContext() {
124+
if (!extensionApi) {
125+
throw Error("The Swift extension has been deactivated.");
126+
}
127+
return extensionApi.waitForWorkspaceContext;
128+
},
129+
130+
get withWorkspaceContext() {
131+
if (!extensionApi) {
132+
throw Error("The Swift extension has been deactivated.");
133+
}
134+
return extensionApi.withWorkspaceContext;
135+
},
136+
} satisfies Api;
101137
}
102138

103139
export function deactivate(): void {
104140
extensionApi?.deactivate();
105141
extensionApi?.dispose();
142+
extensionApi = undefined;
106143
}

test/integration-tests/utilities/testutilities.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { FolderContext } from "@src/FolderContext";
2121
import { FolderOperation, WorkspaceContext } from "@src/WorkspaceContext";
2222
import configuration from "@src/configuration";
2323
import { getLLDBLibPath } from "@src/debugger/lldb";
24-
import { Api } from "@src/extension";
24+
import { InternalApi } from "@src/extension";
2525
import { SwiftLogger } from "@src/logging/SwiftLogger";
2626
import { buildAllTaskName, resetBuildAllTaskCache } from "@src/tasks/SwiftTaskProvider";
2727
import { Extension } from "@src/utilities/extensions";
@@ -103,15 +103,15 @@ function configureLogDumpOnTimeout(timeout: number, logger: ExtensionActivationL
103103
}
104104

105105
const extensionBootstrapper = (() => {
106-
let activatedAPI: Api | undefined = undefined;
106+
let activatedAPI: InternalApi | undefined = undefined;
107107
const testTitle = (currentTest: Mocha.Test) => currentTest.titlePath().join(" → ");
108108
let activationLogger: ExtensionActivationLogger;
109109
let logOnError: <T>(prefix: string, work: () => Thenable<T> | T) => Promise<T>;
110110

111111
function testRunnerSetup(
112112
before: Mocha.HookFunction,
113113
setup:
114-
| ((this: Mocha.Context, api: Api) => Promise<(() => Promise<void>) | void>)
114+
| ((this: Mocha.Context, api: InternalApi) => Promise<(() => Promise<void>) | void>)
115115
| undefined,
116116
after: Mocha.HookFunction,
117117
teardown: ((this: Mocha.Context) => Promise<void>) | undefined,
@@ -297,26 +297,26 @@ const extensionBootstrapper = (() => {
297297

298298
return {
299299
// Activates the extension and adds the defaultPackage to the workspace.
300-
// We can only truly call `vscode.Extension<Api>.activate()` once for an entire
300+
// We can only truly call `vscode.Extension<InternalApi>.activate()` once for an entire
301301
// test run, so after it is called once we switch over to calling activate on
302302
// the returned API object which behaves like the extension is being launched for
303303
// the first time _as long as everything is disposed of properly in `deactivate()`_.
304-
async activateExtension(testAssets?: string[], callSite?: Error): Promise<Api> {
304+
async activateExtension(testAssets?: string[], callSite?: Error): Promise<InternalApi> {
305305
const extensionId = "swiftlang.swift-vscode";
306-
const ext = vscode.extensions.getExtension<Api>(extensionId);
306+
const ext = vscode.extensions.getExtension<InternalApi>(extensionId);
307307
if (!ext) {
308308
throw new Error(`Unable to find extension "${extensionId}"`);
309309
}
310310

311311
// We can only _really_ call activate through
312-
// `vscode.extensions.getExtension<Api>("swiftlang.swift-vscode")` once.
312+
// `vscode.extensions.getExtension<InternalApi>("swiftlang.swift-vscode")` once.
313313
// Subsequent activations must be done through the returned API object.
314314
if (!activatedAPI) {
315315
activationLogger.info(
316316
"Performing the one and only extension activation for this test run."
317317
);
318318
for (const depId of [Extension.CODELLDB, Extension.LLDBDAP]) {
319-
const dep = vscode.extensions.getExtension<Api>(depId);
319+
const dep = vscode.extensions.getExtension<InternalApi>(depId);
320320
if (!dep) {
321321
throw new Error(`Unable to find extension "${depId}"`);
322322
}
@@ -418,7 +418,10 @@ const extensionBootstrapper = (() => {
418418
},
419419

420420
activateExtensionForSuite: function (config?: {
421-
setup?: (this: Mocha.Context, api: Api) => Promise<(() => Promise<void>) | void>;
421+
setup?: (
422+
this: Mocha.Context,
423+
api: InternalApi
424+
) => Promise<(() => Promise<void>) | void>;
422425
teardown?: (this: Mocha.Context) => Promise<void>;
423426
testAssets?: string[];
424427
requiresLSP?: boolean;
@@ -436,7 +439,10 @@ const extensionBootstrapper = (() => {
436439
},
437440

438441
activateExtensionForTest: function (config?: {
439-
setup?: (this: Mocha.Context, api: Api) => Promise<(() => Promise<void>) | void>;
442+
setup?: (
443+
this: Mocha.Context,
444+
api: InternalApi
445+
) => Promise<(() => Promise<void>) | void>;
440446
teardown?: (this: Mocha.Context) => Promise<void>;
441447
testAssets?: string[];
442448
requiresLSP?: boolean;

0 commit comments

Comments
 (0)