Skip to content
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

Use a comment as the patch handle #684

Merged
merged 2 commits into from
Jun 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/docs/create_a_test.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,15 @@ test('myTest', async () => {
});
```

The line `await qawolf.create();` at the end of your test is a placeholder for where new test code will be added if you continue to use the browser. This allows you to optionally edit your test code as you go along. When you finish creating a test, this line is removed.
The line `// 🐺 create code here` at the end of your test is a placeholder for where new test code will be added if you continue to use the browser. This allows you to optionally edit your test code as you go along. When you finish creating a test, this line is removed.

## Edit as you go

The test code is created in real-time, so you can edit the test as you create it.

:::tip

- You can move `await qawolf.create();` anywhere in your test
- You can move `// 🐺 create code here` anywhere in your test

:::

Expand Down
10 changes: 5 additions & 5 deletions docs/docs/edit_a_test.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ Now let's run our test in edit mode, which allows us to add steps to an existing
npx qawolf edit myTest
```

The first few steps of our test will now run. For TodoMVC, this means that the first todo item will be created. The test will then pause where `qawolf.create` is called.
The first few steps of our test will now run. For TodoMVC, this means that the first todo item will be created. The test will then pause where `qawolf.create` is called and replace it with a comment: `// 🐺 create code here`.

```js
// ...
Expand All @@ -97,13 +97,13 @@ test('myTest', async () => {
await page.click('[placeholder="What needs to be done?"]');
await page.type('[placeholder="What needs to be done?"]', 'create test!');
await page.press('[placeholder="What needs to be done?"]', 'Enter');
await qawolf.create(); // test will pause here
// 🐺 create code here
await page.click('.toggle');
await page.click('text=Clear completed');
});
```

Any actions you take in the browser will be converted to code and inserted where `await qawolf.create();` is. To add a second todo item, let's 1) click on the todo input to focus it, 2) type `update test!`, and 3) press `Enter` to save the todo. Our test code now looks like this:
Any actions you take in the browser will be converted to code and inserted where `// 🐺 create code here` is. To add a second todo item, let's 1) click on the todo input to focus it, 2) type `update test!`, and 3) press `Enter` to save the todo. Our test code now looks like this:

```js
// ...
Expand All @@ -116,13 +116,13 @@ test('myTest', async () => {
await page.click('[placeholder="What needs to be done?"]');
await page.type('[placeholder="What needs to be done?"]', 'update test!');
await page.press('[placeholder="What needs to be done?"]', 'Enter');
await qawolf.create(); // this line will be removed on save
// 🐺 create code here
await page.click('.toggle');
await page.click('text=Clear completed');
});
```

Now that we've added our second todo item, let's save our test. In the command line, choose `💾 Save and exit` to save your updated test. The line `await qawolf.create();` will be removed when your test is saved.
Now that we've added our second todo item, let's save our test. In the command line, choose `💾 Save and exit` to save your updated test. The line `// 🐺 create code here` will be removed when your test is saved.

To run your updated test, use the following command:

Expand Down
9 changes: 5 additions & 4 deletions src/create-code/CodeUpdater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@ export abstract class CodeUpdater extends EventEmitter {
protected async _prepare(): Promise<void> {
const code = await this._loadCode();

const patchLine = getLineIncludes(code, PATCH_HANDLE);
if (!patchLine) {
throw new Error(`Could not find "${PATCH_HANDLE}"`);
}
const createLine = getLineIncludes(code, `qawolf.create()`);
if (!createLine) return;

const updatedCode = code.replace(createLine.trim(), PATCH_HANDLE);
await this._update(updatedCode);
}

public async finalize(): Promise<void> {
Expand Down
8 changes: 4 additions & 4 deletions src/create-code/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import { bold } from 'kleur';
import { findLast } from 'lodash';
import { CreateManager } from './CreateManager';
import { getLineIncludes } from './format';
import { PATCH_HANDLE } from './patchCode';
import { CREATE_HANDLE } from './patchCode';
import { Registry } from '../utils';

const debug = Debug('qawolf:create');

export const getCreatePath = async (
callerFileNames: string[],
): Promise<string> => {
debug(`search caller files for ${PATCH_HANDLE} %j`, callerFileNames);
debug(`search caller files for ${CREATE_HANDLE} %j`, callerFileNames);

const codes = await Promise.all(
callerFileNames.map(async (filename) => {
Expand All @@ -29,11 +29,11 @@ export const getCreatePath = async (

const item = findLast(
codes,
({ code }) => !!getLineIncludes(code, PATCH_HANDLE),
({ code }) => !!getLineIncludes(code, CREATE_HANDLE),
);

if (!item) {
throw new Error(`Could not find ${PATCH_HANDLE} in caller`);
throw new Error(`Could not find ${CREATE_HANDLE} in caller`);
}

return item.filename;
Expand Down
4 changes: 3 additions & 1 deletion src/create-code/patchCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ type PatchOptions = {
patch: string;
};

export const PATCH_HANDLE = 'await qawolf.create();';
export const CREATE_HANDLE = 'qawolf.create()';

export const PATCH_HANDLE = '// 🐺 create code here';

export const canPatch = (code: string): boolean => {
return code.includes(PATCH_HANDLE);
Expand Down
20 changes: 16 additions & 4 deletions test/create-code/CodeFileUpdater.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { outputFile, pathExists, readFile, remove } from 'fs-extra';
import { buildSteps } from '../../src/build-workflow/buildSteps';
import { CodeFileUpdater } from '../../src/create-code/CodeFileUpdater';
import { PATCH_HANDLE } from '../../src/create-code/patchCode';
import { CREATE_HANDLE, PATCH_HANDLE } from '../../src/create-code/patchCode';

// require manually since fs is mocked
// eslint-disable-next-line @typescript-eslint/no-var-requires
Expand All @@ -23,20 +23,20 @@ describe('CodeFileUpdater', () => {

describe('discard', () => {
it('reverts to initial code', async () => {
const initialCode = `initialCode()\n${PATCH_HANDLE}`;
const initialCode = `initialCode()\n${CREATE_HANDLE}`;
mockedReadFile.mockResolvedValue(initialCode);
const updater = await CodeFileUpdater.create('revertpath');
await updater.discard();

const reverted = mockedOutputFile.mock.calls[0];
const reverted = mockedOutputFile.mock.calls[1];
expect(reverted[0]).toEqual('revertpath');
expect(reverted[1]).toEqual(initialCode);
expect(mockedRemove.mock.calls.length).toEqual(0);
});

it('removes code if QAW_CREATE is set to true', async () => {
process.env.QAW_CREATE = 'true';
const initialCode = `initialCode()\n${PATCH_HANDLE}`;
const initialCode = `initialCode()\n${CREATE_HANDLE}`;
mockedReadFile.mockResolvedValue(initialCode);
const updater = await CodeFileUpdater.create('removepath');
await updater.discard();
Expand All @@ -46,6 +46,18 @@ describe('CodeFileUpdater', () => {
});

describe('create', () => {
it('replaces qawolf.create call with the patch handle', async () => {
mockedReadFile.mockResolvedValue(
` someCode();\n await qawolf.create();\n otherCode();`,
);
await CodeFileUpdater.create('somepath');

const updatedFile = mockedOutputFile.mock.calls[0][1];
expect(updatedFile).toBe(
` someCode();\n ${PATCH_HANDLE}\n otherCode();`,
);
});

it('throws an error if qawolf.create is not found', async () => {
mockedReadFile.mockResolvedValue('no create');
// eslint-disable-next-line jest/valid-expect
Expand Down
4 changes: 2 additions & 2 deletions test/create-code/__snapshots__/CodeFileUpdater.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ exports[`CodeFileUpdater update saves code with new steps 1`] = `
" someCode();
await page.click('text=\\"Log in\\"');
await page.click(\\"#username\\");
await qawolf.create();
// 🐺 create code here
otherCode();"
`;

Expand All @@ -17,6 +17,6 @@ exports[`CodeFileUpdater update saves code with new steps 2`] = `
await page.type(\\"#password\\", \\"SuperSecretPassword!\\");
await page.press(\\"#password\\", \\"Enter\\");
await page.click('text=\\"Log out\\"');
await qawolf.create();
// 🐺 create code here
otherCode();"
`;
2 changes: 1 addition & 1 deletion test/create-code/__snapshots__/CodeReconciler.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports[`CodeReconciler.reconcile inserts new expressions 1`] = `
"await page.click('text=\\"Log in\\"');
await qawolf.create();"
// 🐺 create code here"
`;

exports[`CodeReconciler.reconcile updates the last expression 1`] = `
Expand Down