Skip to content

Fix test fixture upgrade scripts #942

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Dec 12, 2022
Merged
6 changes: 3 additions & 3 deletions docs/contributing/test-case-recorder.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,19 @@ and can be run in vscode or via yarn in terminal.

### Autoformatting

To clean up the formatting of all of the yaml test cases, run `yarn run compile && node ./out/scripts/transformRecordedTests/index.js`
To clean up the formatting of all of the yaml test cases, run `yarn compile && yarn transform-recorded-tests`

### Upgrading fixtures

To upgrade all the test fixtures to the latest command version, run the command `yarn run compile && node ./out/scripts/transformRecordedTests/index.js upgrade`. This command should be idempotent.
To upgrade all the test fixtures to the latest command version, run the command `yarn compile && yarn transform-recorded-tests upgrade`. This command should be idempotent.

### Custom transformation

1. Add a new transformation to the `src/scripts/transformRecordedTests/transformations` directory. Look at the existing transformations in that directory for inspiration.
1. Change the value at the `custom` key in `AVAILABLE_TRANSFORMATIONS` at the top of
[`transformRecordedTests/index.ts`](../../src/scripts/transformRecordedTests/index.ts) to
point to your new transformation
1. Run `yarn run compile && node ./out/scripts/transformRecordedTests/index.js custom`
1. Run `yarn compile && yarn transform-recorded-tests custom`

Example of a custom transformation

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,8 @@
"test": "env CURSORLESS_TEST=true node ./out/test/scripts/runTestsCI.js",
"unused-exports": "ts-unused-exports tsconfig.json --showLineNumber",
"init-launch-sandbox": "node ./out/scripts/initLaunchSandbox.js",
"prepare-for-extension-publish": "node ./out/scripts/prepareForExtensionPublish.js"
"prepare-for-extension-publish": "node ./out/scripts/prepareForExtensionPublish.js",
"transform-recorded-tests": "node ./out/scripts/transformRecordedTests/index.js"
},
"devDependencies": {
"@types/chai": "^4.3.3",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ActionType } from "../../actions/actions.types";
import { OutdatedExtensionError } from "../../errors";
import { EnforceUndefined } from "../../libs/common/util/typeUtils";
import ide from "../../libs/cursorless-engine/singletons/ide.singleton";
import {
Modifier,
Expand Down Expand Up @@ -29,14 +30,13 @@ import { upgradeV2ToV3 } from "./upgradeV2ToV3";
*/
export function canonicalizeAndValidateCommand(
command: Command,
): CommandComplete {
): EnforceUndefined<CommandComplete> {
const commandUpgraded = upgradeCommand(command);
const {
action,
targets: inputPartialTargets,
usePrePhraseSnapshot = false,
version,
...rest
spokenForm,
} = commandUpgraded;

const actionName = canonicalizeActionName(action.name);
Expand All @@ -45,8 +45,8 @@ export function canonicalizeAndValidateCommand(
validateCommand(actionName, partialTargets);

return {
...rest,
version: LATEST_VERSION,
spokenForm,
action: {
name: actionName,
args: action.args ?? [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,10 @@ function upgradePrimitiveTarget(
return {
type,
isImplicit,
// Cursor token is just cursor position but treated as a token. This is done in the pipeline for normal cursor now
mark: mark?.type === "cursorToken" ? undefined : mark,
// Empty array of modifiers is not allowed
modifiers: modifiers.length > 0 ? modifiers : undefined,
// Cursor token is just cursor position but treated as a token. This is done in the pipeline for normal cursor now
mark: mark?.type === "cursorToken" ? undefined : mark,
};
}

Expand Down
19 changes: 19 additions & 0 deletions src/libs/common/util/typeUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
type GetOptional<T> = {
[K in keyof T as Pick<T, K> extends Required<Pick<T, K>> ? never : K]: T[K];
};

type GetRequired<T> = {
[K in keyof T as Pick<T, K> extends Required<Pick<T, K>> ? K : never]: T[K];
};

type UnionUndefined<T> = {
[K in keyof T]: T[K] | undefined;
};

/**
* Use this type to convert all optional keys in an interface to required undefined unions.
* Useful for passthrough objects that need manual extending
* { opt?: boolean; } => { opt: boolean | undefined; }
*/
export type EnforceUndefined<T> = GetRequired<T> &
UnionUndefined<Required<GetOptional<T>>>;
3 changes: 3 additions & 0 deletions src/scripts/transformRecordedTests/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Ensures that the aliases such as @cursorless/common that we define in
// package.json are active
import "module-alias/register";
import { getRecordedTestPaths } from "../../apps/cursorless-vscode-e2e/getFixturePaths";
import { identity } from "./transformations/identity";
import { upgrade } from "./transformations/upgrade";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import { EnforceUndefined } from "../../../libs/common/util/typeUtils";
import { TestCaseFixture } from "../../../testUtil/TestCaseFixture";

export function reorderFields(fixture: TestCaseFixture) {
export function reorderFields(
fixture: TestCaseFixture,
): EnforceUndefined<TestCaseFixture> {
return {
languageId: fixture.languageId,
command: fixture.command,
marksToCheck: fixture.marksToCheck,
initialState: fixture.initialState,
finalState: fixture.finalState,
decorations: fixture.decorations,
returnValue: fixture.returnValue,
thrownError: fixture.thrownError,
ide: fixture.ide,
postEditorOpenSleepTimeMs: fixture.postEditorOpenSleepTimeMs,
postCommandSleepTimeMs: fixture.postCommandSleepTimeMs,
fullTargets: fixture.fullTargets,
};
}
2 changes: 1 addition & 1 deletion src/testUtil/TestCase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,9 @@ export class TestCase {
finalState: this.finalState,
decorations: this.decorations,
returnValue: this.returnValue,
fullTargets: this.fullTargets,
thrownError: this.thrownError,
ide: this.spyIdeValues,
fullTargets: this.fullTargets,
};
return serialize(fixture);
}
Expand Down
17 changes: 7 additions & 10 deletions src/testUtil/cleanUpTestCaseCommand.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import { TestCaseCommand } from "./TestCaseFixture";
import { merge } from "lodash";

export function cleanUpTestCaseCommand(
command: TestCaseCommand,
): TestCaseCommand {
const { action, ...rest } = command;
const { args } = action;

return {
...rest,
action: {
...action,
args: args == null ? undefined : args.length === 0 ? undefined : args,
},
};
const { args } = command.action;
const result = merge({}, command);
if (args == null || args.length === 0) {
result.action.args = undefined;
}
return result;
}