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

feat: add bun2jest workflow #327

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
143 changes: 143 additions & 0 deletions .grit/workflows/bun2jest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import * as grit from '@getgrit/api';
import * as sdk from '@getgrit/workflows-sdk';

import { QueryBuilder } from '@getgrit/bridge';

/**
* Rewrite a Jest setup file to be usable as a --preload file
*/
async function transformTests(targetPath: string) {
grit.logging.debug(`Transforming Jest test files at ${targetPath}`);
const pattern = `or {
js"describe" where { add_import(js"describe", js"'bun:test'")},
js"it" where { add_import(js"it", js"'bun:test'")},
js"test($_)" where { add_import(js"test", js"'bun:test'")},
js"expect($_)" where { add_import(js"expect", js"'bun:test'")},
}`;
const query = new QueryBuilder(pattern);

const instanceCount = await query.run([targetPath]);
grit.logging.info(`Transformed Jest setup file at ${targetPath}, with ${instanceCount} changes`);

return targetPath;
}

/**
* Rewrite a Jest setup file to be usable as a --preload file
*/
async function transformSetupFile(targetPath: string) {
grit.logging.debug(`Transforming Jest setup file at ${targetPath}`);
const pattern = `js"$func($contents)" where {
$func <: or {
js"beforeAll" => js"beforeEachFile" where { add_import(js"beforeEachFile", js"'bun:test'")},
js"afterAll" => js"afterEachFile" where { add_import(js"afterEachFile", js"'bun:test'")},
}
}`;
const query = new QueryBuilder(pattern);

const instanceCount = await query.run([targetPath]);
grit.logging.info(`Transformed Jest setup file at ${targetPath}, with ${instanceCount} changes`);

return targetPath;
}

/**
* Fix the provided bun config
*/
async function fixBunConfig(targetPath: string, props: { [key: string]: any } = {}) {
grit.logging.debug(`Fixing Bun config at ${targetPath}`);
const pattern = `
language toml

file($body) where {
// $props = {preload: \`"foo.ts"\`},
$props = {${Object.entries(props).map(([key, value]) => `${key}: \`${value}\``).join(', ')}},
if ($body <: contains \`[test]
$existing\`) {
$props <: some bubble($existing) [$key, $value] where {
or {
$existing <: contains \`$key = $_\` => \`$key: $value\`,
$existing += \`\n$key = $value\`
}
}
} else {
$body += \`\n[test]\n\`,
$props <: some bubble($body) [$key, $value] where {
$body += \`$key = $value\n\`
}
}
}`;

grit.logging.debug(`Pattern: ${pattern}`);

const query = new QueryBuilder(pattern);

const instanceCount = await query.run([targetPath]);
grit.logging.info(`Fixed Bun config at ${targetPath}, with ${instanceCount} changes`);

return targetPath;
}

export default await sdk.defineWorkflow({
name: 'jest_to_bun',

run: async (options) => {
const targetDir = process.cwd();

const configRoot = targetDir;

// Look for a jest.config.json file
const targetFile = 'jest.config.js';
const config = await import(`${targetDir}/${targetFile}`);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding error handling for the import statement to manage cases where the jest.config.js file does not exist.


grit.logging.debug(`Successfully loaded config`, config);

// Props we want to set up
const props: { [key: string]: string } = {};

await transformTests(`${configRoot}/src`);

// Convert from setupFilesAfterEnv -> preload with beforeEachFile
if (config.setupFilesAfterEnv) {
const preloads = [];
for (const setupFile of config.setupFilesAfterEnv) {
const actualFile = `${configRoot}/${setupFile}`;
const fixed = await transformSetupFile(actualFile);
grit.logging.debug(`Adding ${fixed} to preload`);
preloads.push(setupFile);
}
props.preload = JSON.stringify(preloads);
}

if (config.bail) {
props.bail = config.bail;
}

if (config.collectCoverage) {
props.coverage = config.collectCoverage;
}

if (config.coverageThreshold?.global) {
let parts = [];
if (config.coverageThreshold.global.lines) {
parts.push(`line = ${config.coverageThreshold.global.lines / 100}`);
}
if (config.coverageThreshold.global.functions) {
parts.push(`function = ${config.coverageThreshold.global.functions / 100}`);
}
if (config.coverageThreshold.global.statements) {
parts.push(`statement = ${config.coverageThreshold.global.statements / 100}`);
}
props.coverageThreshold = `{${parts.join(', ')}}`;
}

// Apply the bunfig
const bunConfig = `${configRoot}/Bunfig.toml`;
await fixBunConfig(bunConfig, props);

return {
success: true,
message: 'Jest to Bun',
}
},
});
Loading