Skip to content

Commit d254278

Browse files
authored
fix: scoped type generation (#24)
1 parent ae9a427 commit d254278

File tree

7 files changed

+50
-4
lines changed

7 files changed

+50
-4
lines changed

cypress/commands/example.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ export function functionExample(input: string) {
1818
cy.contains(input);
1919
}
2020

21+
export function functionExampleScoped(element: Cypress.JQueryWithSelector, input: string) {
22+
cy.log('Here is a scoped custom command!');
23+
cy.wrap(element).should('have.text', input);
24+
}
25+
2126
export const arrowFunctionExample = (input: string) => {
2227
cy.log('Here is a custom command from an arrow function!');
2328
cy.contains(input);
@@ -27,6 +32,7 @@ declare global {
2732
namespace Cypress {
2833
interface Chainable {
2934
functionExample(input: string): Chainable;
35+
functionExampleScoped(input: string): Chainable;
3036
arrowFunctionExample(input: string): Chainable;
3137
}
3238
}

cypress/e2e/e2e-example.cy.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ describe('Example Test', () => {
2626
cy.arrowFunctionExample(expectedText);
2727
});
2828

29+
it('should support scoped methods', () => {
30+
cy.contains(expectedText).functionExampleScoped(expectedText);
31+
});
32+
2933
it('should dynamically import nested custom commands', () => {
3034
cy.nestedExample(expectedText);
3135
});

src/common.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const COMMANDS_DIRECTORY = 'cypress/commands';
2+
3+
export const isScopedMethod = (methodName: string) => methodName.endsWith('Scoped');

src/generate-types-from-abstract-syntax-tree.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import generate from '@babel/generator';
2626
import { readFileSync } from 'fs';
2727
import { resolve } from 'path';
2828
import { format, Options } from 'prettier';
29+
import { isScopedMethod } from './common';
2930

3031
export const generateTypesFromAbstractSyntaxTree = (filePath: string, prettierConfig?: Options) => {
3132
const contents = readFileSync(resolve(filePath)).toString();
@@ -52,9 +53,10 @@ export const generateTypesFromAbstractSyntaxTree = (filePath: string, prettierCo
5253
}
5354
return parameter as Identifier;
5455
});
56+
const firstParamOmitted = parameters.slice(1);
5557
return {
5658
functionIdentifier,
57-
parameters
59+
parameters: isScopedMethod(functionIdentifier.name) ? firstParamOmitted : parameters
5860
};
5961
});
6062
const newInterface = generateInterface(customCommands);

src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ See the License for the specific language governing permissions and
1111
limitations under the License.
1212
*/
1313

14+
import { isScopedMethod } from './common';
15+
1416
before('Import Custom Commands', () => {
1517
cy.task('importCustomCommands').then(
1618
({ filePaths, commandsDirectory }: { filePaths: string[]; commandsDirectory: string }) => {
@@ -23,7 +25,7 @@ before('Import Custom Commands', () => {
2325
const methodNames = Object.keys(customCommandObject);
2426
methodNames.forEach((methodName: keyof Cypress.Chainable) => {
2527
const method = customCommandObject[methodName];
26-
if (methodName.endsWith('Scoped')) {
28+
if (isScopedMethod(methodName)) {
2729
Cypress.Commands.add(methodName, { prevSubject: 'element' }, method);
2830
} else {
2931
Cypress.Commands.add(methodName, method);

src/plugin.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ import { generateTypesFromAbstractSyntaxTree } from './generate-types-from-abstr
1616
import { writeFileSync } from 'fs';
1717
import { resolve, sep } from 'path';
1818
import { Options as PrettierConfig, resolveConfig } from 'prettier';
19-
20-
export const COMMANDS_DIRECTORY = 'cypress/commands';
19+
import { COMMANDS_DIRECTORY } from './common';
2120

2221
export type CypressCodegen = (
2322
on: Cypress.PluginEvents,

test/generate-types-from-abstract-syntax-tree.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,36 @@ declare global {
224224
}
225225
}
226226
}
227+
`);
228+
});
229+
230+
it('should generate a special type for scoped commands', async () => {
231+
(readFileSync as jest.Mock).mockReturnValue(`// some comment
232+
233+
export function functionExampleScoped(
234+
element: Cypress.JQueryWithSelector,
235+
input1: string
236+
) {
237+
cy.log('Here is a scoped custom command!');
238+
}
239+
`);
240+
const result = generateTypesFromAbstractSyntaxTree(filePath, prettierConfig);
241+
expect(result).toEqual(`// some comment
242+
243+
export function functionExampleScoped(
244+
element: Cypress.JQueryWithSelector,
245+
input1: string
246+
) {
247+
cy.log('Here is a scoped custom command!');
248+
}
249+
250+
declare global {
251+
namespace Cypress {
252+
interface Chainable {
253+
functionExampleScoped(input1: string): Chainable;
254+
}
255+
}
256+
}
227257
`);
228258
});
229259
});

0 commit comments

Comments
 (0)