Skip to content

Commit

Permalink
test: sketched out some more test requirements
Browse files Browse the repository at this point in the history
  • Loading branch information
wheresrhys committed Aug 31, 2024
1 parent 5577416 commit f981e4d
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 90 deletions.
49 changes: 0 additions & 49 deletions packages/codemods/src/__test__/codemod.test.js

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,7 @@ describe('identifying fetch-mock instances', () => {
`,
);
});
// Identify fetch - mock references when mocking node - fetch in jest
// sandbox() instances
// sandbox() instances used by jest / vitest.mock
});
Empty file.
72 changes: 72 additions & 0 deletions packages/codemods/src/__test__/method-codemods.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { describe, it, expect } from 'vitest';
import { codemod } from '../index';
import jscodeshift from 'jscodeshift';

const prependFetchMock = (src) =>
`const fetchMock = require('fetch-mock');\n${src}`;

function expectCodemodResult(src, expected) {
expect(codemod(prependFetchMock(src), jscodeshift)).toEqual(
prependFetchMock(expected),
);
}

describe('codemods operating on methods', () => {
describe('converting mock() to route()', () => {
//Next to the first one in a file leave a comment explaining that they need to use mockGlobal() too
it('single .mock()', () => {
expectCodemodResult(
'fetchMock.mock("blah", 200)',
'fetchMock.route("blah", 200)',
);
});
it('multiple single .mock()', () => {
expectCodemodResult(
`
fetchMock.mock("blah", 200);
fetchMock.mock("bloop", 300);
`,
`
fetchMock.route("blah", 200);
fetchMock.route("bloop", 300);
`,
);
});
it('chained .mock()', () => {
expectCodemodResult(
`
fetchMock
.mock("blah", 200)
.mock("bloop", 300)
`,
`
fetchMock
.route("blah", 200)
.route("bloop", 300)
`,
);
});
it('chained .mock() after other method', () => {
expectCodemodResult(
`
fetchMock
.get("blah", 200)
.mock("bloop", 300)
`,
`
fetchMock
.get("blah", 200)
.route("bloop", 300)
`,
);
});
});

// .lastUrl() => .callHistory.lastCall()?.url
// .lastOptions() => .callHistory.lastCall()?.options
// .lastResponse() => .callHistory.lastCall()?.response
// .sandbox() => .fetchHandler(and maybe a comment about.createInstance())
// .getAny(), .postAny(), .putAny(), .deleteAny(), .headAny(), .patchAny(), .getAnyOnce(), .postAnyOnce(), .putAnyOnce(), .deleteAnyOnce(), .headAnyOnce(), .patchAnyOnce() => calls to the underlying method + options
// restore() / reset()... once I've decided how to implement these
// lastCall() => try to change uses of this to expect a callLog, but probably just insert a commemnt / error
});
61 changes: 61 additions & 0 deletions packages/codemods/src/__test__/option-codemods.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { describe, it, expect } from 'vitest';
import { codemod } from '../index';
import jscodeshift from 'jscodeshift';

const prependFetchMock = (src) =>
`const fetchMock = require('fetch-mock');\n${src}`;

function expectCodemodResult(src, expected) {
expect(codemod(prependFetchMock(src), jscodeshift)).toEqual(
prependFetchMock(expected),
);
}

describe('codemods operating on options', () => {
['overwriteRoutes', 'warnOnFallback', 'sendAsJson'].forEach((optionName) => {
describe(optionName, () => {
it('Removes as global option', () => {})[
('mock',
'sticky',
'once',
'any',
'anyOnce',
'get',
'getAny',
'getOnce',
'getAnyOnce',
'post',
'postAny',
'postOnce',
'postAnyOnce',
'put',
'putAny',
'putOnce',
'putAnyOnce',
'delete',
'deleteAny',
'deleteOnce',
'deleteAnyOnce',
'head',
'headAny',
'headOnce',
'headAnyOnce',
'patch',
'patchAny',
'patchOnce',
'patchAnyOnce')
].forEach((methodName) => {
describe(`when using ${methodName}`, () => {
it(`Removes as option on first parameter of ${methodName}()`, () => {});

it(`Removes as option on third parameter of ${methodName}()`, () => {});

it(`Removes third parameter of ${methodName}() if no other options remain`, () => {});
});
});
});
});
describe('fallbackToNetwork', () => {
// try to replace fallbackToNetwork: always with spyGlobal()... but probably just insert an error / comment that points at the docs
});
});
86 changes: 45 additions & 41 deletions packages/codemods/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,50 +1,54 @@
import type {
JSCodeshift, MemberExpression, Identifier, Transform, FileInfo, API
JSCodeshift,
MemberExpression,
Identifier,
FileInfo,
API,
} from 'jscodeshift';
export function codemod(source: string, j: JSCodeshift) {
const root = j(source);
const fetchMockVariableName = root
.find(j.CallExpression, {
callee: {
name: "require"
},
arguments: [{ value: "fetch-mock" }]
})
.closest(j.VariableDeclarator)
.get().value.id.name;
const root = j(source);
const fetchMockVariableName = root
.find(j.CallExpression, {
callee: {
name: 'require',
},
arguments: [{ value: 'fetch-mock' }],
})
.closest(j.VariableDeclarator)
.get().value.id.name;

const usesOfFetchmock = root
.find(j.CallExpression, {
callee: {
object: {
type: "Identifier",
name: fetchMockVariableName
}
}
})
.map((path) => {
const paths = [path];
while (path.parentPath.value.type !== "ExpressionStatement") {
path = path.parentPath;
if (path.value.type === "CallExpression") {
paths.push(path);
}
}
return paths;
})
.forEach((path) => {
const callee = path.value.callee as MemberExpression;
const property = callee.property as Identifier;
const method = property.name;
if (method === "mock") {
property.name = "route";
}
});
const usesOfFetchmock = root.find(j.CallExpression, {
callee: {
object: {
type: 'Identifier',
name: fetchMockVariableName,
},
},
});

return root.toSource();
}
usesOfFetchmock
.map((path) => {
const paths = [path];
while (path.parentPath.value.type !== 'ExpressionStatement') {
path = path.parentPath;
if (path.value.type === 'CallExpression') {
paths.push(path);
}
}
return paths;
})
.forEach((path) => {
const callee = path.value.callee as MemberExpression;
const property = callee.property as Identifier;
const method = property.name;
if (method === 'mock') {
property.name = 'route';
}
});

return root.toSource();
}

export default function transformer(file: FileInfo, api: API): string {
return codemod(file.source, api.j);
return codemod(file.source, api.j);
}

0 comments on commit f981e4d

Please sign in to comment.