Skip to content

Commit

Permalink
feat: get test results for ref tests
Browse files Browse the repository at this point in the history
  • Loading branch information
AnWeber committed Oct 28, 2024
1 parent 3684ea6 commit 5400fc7
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 56 deletions.
12 changes: 10 additions & 2 deletions src/documentStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { logToOutputChannelFactory, LogChannel, resetOutputChannel } from './io'
import * as utils from './utils';
import * as httpyac from 'httpyac';
import * as vscode from 'vscode';
import { registerVscodePlugins } from './plugin';
import { HttpRegionExecutedEvent, registerVscodePluginsFactory } from './plugin';

export enum HttpFileChangedEventType {
CHANGED,
Expand Down Expand Up @@ -46,12 +46,20 @@ export class DocumentStore extends utils.DisposeProvider implements IDocumentSto

documentStoreChangedEmitter: vscode.EventEmitter<void>;
private httpFileChangedEmitter: vscode.EventEmitter<HttpFileChangedEvent>;
private httpRegionExecutedEmitter: vscode.EventEmitter<HttpRegionExecutedEvent>;

public get httpRegionExecuted(): vscode.Event<HttpRegionExecutedEvent> {
return this.httpRegionExecutedEmitter.event;
}

constructor() {
super();
this.documentStoreChangedEmitter = new vscode.EventEmitter<void>();
this.httpRegionExecutedEmitter = new vscode.EventEmitter<HttpRegionExecutedEvent>();
this.httpFileChangedEmitter = new vscode.EventEmitter<HttpFileChangedEvent>();
this.httpFileStore = new httpyac.store.HttpFileStore({ vscode: registerVscodePlugins });
this.httpFileStore = new httpyac.store.HttpFileStore({
vscode: registerVscodePluginsFactory(this.httpRegionExecutedEmitter),
});
this.getDocumentPathLike = document => document.uri;
this.activeEnvironment = getConfigSetting().environmentSelectedOnStart;

Expand Down
27 changes: 21 additions & 6 deletions src/plugin/vscodeHttpyacPlugin.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
import { HttpyacHooksApi, io } from 'httpyac';
import { HttpFile, HttpRegion, HttpyacHooksApi, io, ProcessorContext } from 'httpyac';
import { bailOnFailedTestInterceptor } from './bailOnFailedTestInterceptor';
import { provideOutputChannelLogger } from './outputChannelProvider';
import * as vscode from 'vscode';
import { errorNotificationHandler } from './errorNotificationHandler';

export function registerVscodePlugins(api: HttpyacHooksApi) {
api.hooks.execute.addInterceptor(errorNotificationHandler);
api.hooks.execute.addInterceptor(bailOnFailedTestInterceptor);
api.hooks.provideVariables.addHook('provideOutputChannelLogger', provideOutputChannelLogger);
io.javascriptProvider.require.vscode = vscode;
export function registerVscodePluginsFactory(httpRegionExecutedEmitter: vscode.EventEmitter<HttpRegionExecutedEvent>) {
return (api: HttpyacHooksApi) => {
api.hooks.execute.addInterceptor(errorNotificationHandler);
api.hooks.execute.addInterceptor(bailOnFailedTestInterceptor);
api.hooks.execute.addInterceptor({
id: 'httpRegionExecuted',
afterTrigger: async function bail(hookContext: { args: [ProcessorContext] }) {
const context = hookContext.args[0];
httpRegionExecutedEmitter.fire(context);
return true;
},
});
api.hooks.provideVariables.addHook('provideOutputChannelLogger', provideOutputChannelLogger);
io.javascriptProvider.require.vscode = vscode;
};
}

export type HttpRegionExecutedEvent = {
httpRegion: HttpRegion;
httpFile: HttpFile;
};
6 changes: 5 additions & 1 deletion src/provider/test/testItemResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,13 +258,17 @@ export class TestItemResolver extends DisposeProvider {
return getConfigSetting().testHiearchy === 'flattened';
}

public getTestItemForHttpRegion(httpRegion: httpyac.HttpRegion, fileUri: vscode.Uri) {
return this.createTestItem(TestItemKind.httpRegion, httpRegion.symbol.name, fileUri, httpRegion.id);
}

private createHttpFileTestItem(httpFile: httpyac.HttpFile, parent: vscode.TestItem) {
const fileUri = toUri(httpFile.fileName);
if (fileUri) {
const items: Array<vscode.TestItem> = [];
for (const httpRegion of httpFile.httpRegions) {
if (!httpRegion.isGlobal()) {
const testItem = this.createTestItem(TestItemKind.httpRegion, httpRegion.symbol.name, fileUri, httpRegion.id);
const testItem = this.getTestItemForHttpRegion(httpRegion, fileUri);
const requestLine =
httpRegion.symbol.children?.find(obj => obj.kind === httpyac.HttpSymbolKind.requestLine)?.startLine ||
httpRegion.symbol.startLine;
Expand Down
127 changes: 80 additions & 47 deletions src/provider/test/testRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { StoreController } from '../storeController';
import { logTestRun } from './testRunOutput';
import { isHttpFileItem, isHttpRegionTestItem } from './testItemKind';
import { resetBail } from '../../plugin';
import { toUri } from '../../io';

interface TestRunContext {
testRun: vscode.TestRun;
Expand All @@ -29,29 +30,51 @@ export class TestRunner {
const testRun = this.testController.createTestRun(request);
const testItems: Array<vscode.TestItem> = await this.testItemResolver.resolveTestItemsForRequest(request);

await this.resetEnvironmentIfNeeded();
const processedHttpRegions: Array<httpyac.ProcessedHttpRegion> = [];
const testFuncs = (await this.enqueuedTestItems(testItems, testRun)).map(items => async () => {
for (const item of items) {
if (!token.isCancellationRequested && isHttpRegionTestItem(item)) {
await this.runTestItem(item, {
testRun,
testItems,
token,
processedHttpRegions,
});
} else {
testRun.skipped(item);
}
const testStartTime = Date.now();
const duration = () => Date.now() - testStartTime;
const disposeHttpRegionExecuted = this.documentStore.httpRegionExecuted(({ httpRegion, httpFile }) => {
const fileUri = toUri(httpFile.fileName);
if (fileUri) {
this.setTestResult(
httpRegion,
testRun,
this.testItemResolver.getTestItemForHttpRegion(httpRegion, fileUri),
duration
);
}
});
const repeatTimes = getConfigSetting().testRunRepeatTimes || 1;
for (let index = 0; index < repeatTimes; index++) {
await httpyac.utils.promiseQueue(getConfigSetting().testMaxConcurrency || 1, ...testFuncs);

try {
await this.resetEnvironmentIfNeeded();
const processedHttpRegions: Array<httpyac.ProcessedHttpRegion> = [];
const testFuncs = (await this.enqueuedTestItems(testItems, testRun)).map(items => async () => {
for (const item of items) {
if (!token.isCancellationRequested && isHttpRegionTestItem(item)) {
await this.runTestItem(
item,
{
testRun,
testItems,
token,
processedHttpRegions,
},
duration
);
} else {
testRun.skipped(item);
}
}
});
const repeatTimes = getConfigSetting().testRunRepeatTimes || 1;
for (let index = 0; index < repeatTimes; index++) {
await httpyac.utils.promiseQueue(getConfigSetting().testMaxConcurrency || 1, ...testFuncs);
}
logTestRun(processedHttpRegions);
testRun.end();
resetBail();
} finally {
disposeHttpRegionExecuted.dispose();
}
logTestRun(processedHttpRegions);
testRun.end();
resetBail();
}

private async resetEnvironmentIfNeeded() {
Expand Down Expand Up @@ -85,9 +108,11 @@ export class TestRunner {
return result;
}

private async runTestItem(testItem: vscode.TestItem, testRunContext: TestRunContext): Promise<void> {
const testStartTime = Date.now();
const duration = () => Date.now() - testStartTime;
private async runTestItem(
testItem: vscode.TestItem,
testRunContext: TestRunContext,
duration: () => number
): Promise<void> {
testRunContext.testRun.started(testItem);
const sendContext = await this.getSendContext(testItem, testRunContext);
if (
Expand All @@ -98,30 +123,6 @@ export class TestRunner {
) {
try {
await this.documentStore.send(sendContext);
const testResults = sendContext.httpRegion?.testResults;

if (testResults?.some(t => t.status === httpyac.TestResultStatus.ERROR)) {
const testResult = testResults?.find(t => t.status === httpyac.TestResultStatus.ERROR);
testRunContext.testRun.errored(testItem, new vscode.TestMessage(testResult?.message || ''), duration());
} else if (testResults?.find(t => t.status === httpyac.TestResultStatus.SKIPPED)) {
testRunContext.testRun.skipped(testItem);
} else if (!testResults || testResults.every(t => t.status === httpyac.TestResultStatus.SUCCESS)) {
testRunContext.testRun.passed(testItem, duration());
} else {
testRunContext.testRun.failed(
testItem,
testResults.reduce((prev, obj) => {
if (obj.status !== httpyac.TestResultStatus.SUCCESS) {
prev.push(new vscode.TestMessage(obj.message));
if (obj.error) {
prev.push(new vscode.TestMessage(obj.error.displayMessage));
}
}
return prev;
}, [] as Array<vscode.TestMessage>),
duration()
);
}
} catch (err) {
httpyac.io.log.error(err);
testRunContext.testRun.errored(
Expand All @@ -135,6 +136,38 @@ export class TestRunner {
}
}

private setTestResult(
httpRegion: httpyac.HttpRegion,
testRun: vscode.TestRun,
testItem: vscode.TestItem,
duration: () => number
) {
const testResults = httpRegion?.testResults;

if (testResults?.some(t => t.status === httpyac.TestResultStatus.ERROR)) {
const testResult = testResults?.find(t => t.status === httpyac.TestResultStatus.ERROR);
testRun.errored(testItem, new vscode.TestMessage(testResult?.message || ''), duration());
} else if (testResults?.find(t => t.status === httpyac.TestResultStatus.SKIPPED)) {
testRun.skipped(testItem);
} else if (!testResults || testResults.every(t => t.status === httpyac.TestResultStatus.SUCCESS)) {
testRun.passed(testItem, duration());
} else {
testRun.failed(
testItem,
testResults.reduce((prev, obj) => {
if (obj.status !== httpyac.TestResultStatus.SUCCESS) {
prev.push(new vscode.TestMessage(obj.message));
if (obj.error) {
prev.push(new vscode.TestMessage(obj.error.displayMessage));
}
}
return prev;
}, [] as Array<vscode.TestMessage>),
duration()
);
}
}

private async getSendContext(
testItem: vscode.TestItem,
testRunContext: TestRunContext
Expand Down

0 comments on commit 5400fc7

Please sign in to comment.