Skip to content

Commit

Permalink
feat!: support typescript configurations (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
AriPerkkio authored Dec 31, 2021
1 parent 223700c commit d6f2ec3
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 50 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Check out the use case description from eslint-remote-tester's documentation: [P
| :-----------------------------: | :------------------: |
| `v1` | `1.0.1` or above |
| `v2` | `1.0.1` or above |
| `v3` | `2.1.1` or above |

## Configuration:

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"@actions/core": "^1.2.6",
"@actions/exec": "^1.0.4",
"@actions/github": "^4.0.0",
"eslint-remote-tester": "^1.2.0",
"eslint-remote-tester": "^2.1.1",
"semver": "^7.3.4"
},
"devDependencies": {
Expand All @@ -41,6 +41,7 @@
"prettier": "^2.2.1",
"rimraf": "^3.0.2",
"ts-jest": "24",
"ts-node": "^10.4.0",
"typescript": "^4.1.3"
},
"husky": {
Expand Down
2 changes: 1 addition & 1 deletion src/peer-dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ interface DependencyInfo {
// Changes to minVersion's require major release
const DEPENDENCY_TO_INFO: Record<PeerDependency, DependencyInfo> = {
'eslint-remote-tester': {
minVersion: '1.0.1',
minVersion: '2.1.1',
exportPath: 'eslint-remote-tester/dist/exports-for-compare-action',
packageJsonPath: 'eslint-remote-tester/package.json',
bin: 'eslint-remote-tester',
Expand Down
66 changes: 44 additions & 22 deletions src/run-tester.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import fs from 'fs';
import path from 'path';
import { exec } from '@actions/exec';
import { Config } from 'eslint-remote-tester/dist/exports-for-compare-action';
import type { Config } from 'eslint-remote-tester';

import {
requirePeerDependency,
ESLINT_REMOTE_TESTER_BIN,
} from './peer-dependencies';

const INTERNAL_CONFIG = './eslint-remote-tester-runner-internal.config.js';
const INTERNAL_CONFIG = './eslint-remote-tester-runner-internal.config';
export const RESULTS_TMP = '/tmp/results.json';

/**
Expand All @@ -19,19 +19,7 @@ const DEFAULT_CONFIG: Partial<Config> = {
CI: true,
};

// prettier-ignore
const CONFIGURATION_TEMPLATE = (
pathToUsersConfiguration: string
) =>
`// Generated by eslint-remote-tester-run-action
const fs = require('fs');
// Load user's eslint-remote-tester.config.js
const usersConfig = require('${pathToUsersConfiguration}');
module.exports = {
...usersConfig,
const CONFIGURATION_TEMPLATE_BASE = `
// Values from eslint-remote-tester-run-action's default configuration
...${JSON.stringify(DEFAULT_CONFIG, null, 4)},
Expand All @@ -43,7 +31,35 @@ module.exports = {
await usersConfig.onComplete(results, comparisonResults, repositoryCount);
}
}
`;

const CONFIGURATION_TEMPLATE_JS = (pathToUsersConfiguration: string) =>
`// Generated by eslint-remote-tester-run-action
const fs = require('fs');
// Load user's eslint-remote-tester.config.js
const usersConfig = require('${pathToUsersConfiguration}');
module.exports = {
...usersConfig,
${CONFIGURATION_TEMPLATE_BASE}
};
`;

const CONFIGURATION_TEMPLATE_TS = (pathToUsersConfiguration: string) =>
`// Generated by eslint-remote-tester-run-action
import fs from 'fs';
import type { Config } from 'eslint-remote-tester';
// Load user's eslint-remote-tester.config.ts
import usersConfig from '${pathToUsersConfiguration.replace(/\.ts$/, '')}';
const config: Config = {
...usersConfig,
${CONFIGURATION_TEMPLATE_BASE}
};
export default config;
`;

/**
Expand All @@ -65,27 +81,33 @@ export default async function runTester(configLocation: string): Promise<void> {
);
}

const extension = usersConfigLocation.split('.').pop();
const configTemplate =
extension === 'ts'
? CONFIGURATION_TEMPLATE_TS
: CONFIGURATION_TEMPLATE_JS;
const createdConfig = `${INTERNAL_CONFIG}.${extension}`;

// Write eslint-remote-tester configuration file
fs.writeFileSync(
INTERNAL_CONFIG,
CONFIGURATION_TEMPLATE(usersConfigLocation)
);
fs.writeFileSync(createdConfig, configTemplate(usersConfigLocation));

const { loadConfig, validateConfig } = requirePeerDependency(
'eslint-remote-tester'
);
let config: Config;

// Useless try-catch required by esbuild
// eslint-disable-next-line no-useless-catch
try {
config = require(path.resolve(INTERNAL_CONFIG));
config = loadConfig(path.resolve(createdConfig));
} catch (e) {
throw e;
}

// Validate configuration before run
const { validateConfig } = requirePeerDependency('eslint-remote-tester');
await validateConfig(config, false);

await exec(`${ESLINT_REMOTE_TESTER_BIN} --config ${INTERNAL_CONFIG}`, [], {
await exec(`${ESLINT_REMOTE_TESTER_BIN} --config ${createdConfig}`, [], {
ignoreReturnCode: true,
env: { ...process.env, NODE_OPTIONS: '--max_old_space_size=5120' },
});
Expand Down
12 changes: 12 additions & 0 deletions test/eslint-remote-tester.typescript.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { Config } from 'eslint-remote-tester';

const config: Config = {
repositories: ['AriPerkkio/eslint-remote-tester-integration-test-target'],
extensions: ['.ts'],
eslintrc: {
root: true,
extends: ['eslint:recommended'],
},
};

export default config;
114 changes: 99 additions & 15 deletions test/run-tester.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,20 @@ import { ESLINT_REMOTE_TESTER_BIN } from '../src/peer-dependencies';
import { sanitizeStackTrace } from './utils';
import { Config } from 'eslint-remote-tester/dist/exports-for-compare-action';

const EXPECTED_RUN_CONFIG = './eslint-remote-tester-runner-internal.config.js';
const CONFIG = './test/eslint-remote-tester.config.js';
const EXPECTED_RUN_CONFIG = './eslint-remote-tester-runner-internal.config';
const CONFIG_JS = './test/eslint-remote-tester.config.js';
const CONFIG_TS = './test/eslint-remote-tester.typescript.config.ts';
const INVALID_CONFIG = './test/eslint-remote-tester.invalid.config.js';
const CONFIG_WITH_ON_COMPLETE =
'./test/eslint-remote-tester.config.onComplete.js';

jest.mock('@actions/exec', () => ({ exec: jest.fn() }));

function readRunConfig() {
function readRunConfig(extension: 'js' | 'ts') {
let content: Config;

jest.isolateModules(() => {
content = require(resolve(EXPECTED_RUN_CONFIG));
content = require(resolve(`${EXPECTED_RUN_CONFIG}.${extension}`));
});

return content!;
Expand All @@ -28,20 +29,24 @@ function readRunConfig() {
function cleanup() {
jest.resetModules();

if (fs.existsSync(EXPECTED_RUN_CONFIG)) {
fs.unlinkSync(EXPECTED_RUN_CONFIG);
}
['js', 'ts'].forEach(extension => {
const name = `${EXPECTED_RUN_CONFIG}.${extension}`;

if (fs.existsSync(name)) {
fs.unlinkSync(name);
}
});
}

describe('run-tester', () => {
beforeEach(cleanup);
afterEach(cleanup);

test('runs eslint-remote-tester with provided configuration', async () => {
await runTester(CONFIG);
test('runs eslint-remote-tester with provided Javascript configuration', async () => {
await runTester(CONFIG_JS);

expect(exec).toHaveBeenCalledWith(
`${ESLINT_REMOTE_TESTER_BIN} --config ${EXPECTED_RUN_CONFIG}`,
`${ESLINT_REMOTE_TESTER_BIN} --config ${EXPECTED_RUN_CONFIG}.js`,
[],
{
ignoreReturnCode: true,
Expand All @@ -52,6 +57,85 @@ describe('run-tester', () => {
);
});

test('creates CommonJS module when using Javascript configuration file', async () => {
await runTester(CONFIG_JS);

const configContents = fs.readFileSync(
`${EXPECTED_RUN_CONFIG}.js`,
'utf8'
);

expect(sanitizeStackTrace(configContents)).toMatchInlineSnapshot(`
"// Generated by eslint-remote-tester-run-action
const fs = require('fs');
// Load user's eslint-remote-tester.config.js
const usersConfig = require('<removed>/test/eslint-remote-tester.config.js');
module.exports = {
...usersConfig,
// Values from eslint-remote-tester-run-action's default configuration
...{
\\"cache\\": false,
\\"CI\\": true
},
onComplete: async function onComplete(results, comparisonResults, repositoryCount) {
// Write results to cache
fs.writeFileSync('/tmp/results.json', JSON.stringify({ results, repositoryCount }));
if(usersConfig.onComplete) {
await usersConfig.onComplete(results, comparisonResults, repositoryCount);
}
}
};
"
`);
});

test('creates ES module when using Typescript configuration file', async () => {
await runTester(CONFIG_TS);

const configContents = fs.readFileSync(
`${EXPECTED_RUN_CONFIG}.ts`,
'utf8'
);

expect(sanitizeStackTrace(configContents)).toMatchInlineSnapshot(`
"// Generated by eslint-remote-tester-run-action
import fs from 'fs';
import type { Config } from 'eslint-remote-tester';
// Load user's eslint-remote-tester.config.ts
import usersConfig from '<removed>/test/eslint-remote-tester.typescript.config';
const config: Config = {
...usersConfig,
// Values from eslint-remote-tester-run-action's default configuration
...{
\\"cache\\": false,
\\"CI\\": true
},
onComplete: async function onComplete(results, comparisonResults, repositoryCount) {
// Write results to cache
fs.writeFileSync('/tmp/results.json', JSON.stringify({ results, repositoryCount }));
if(usersConfig.onComplete) {
await usersConfig.onComplete(results, comparisonResults, repositoryCount);
}
}
};
export default config;
"
`);
});

test('throws if given configuration does not exist', () => {
return expect(runTester('./non-existing-config')).rejects.toThrowError(
/(?=.*Unable to find eslint-remote-tester config with path)(?=.*non-existing-config)/
Expand All @@ -61,7 +145,7 @@ describe('run-tester', () => {
test('uses onComplete from users configuration', async () => {
await runTester(CONFIG_WITH_ON_COMPLETE);

expect(sanitizeStackTrace(readRunConfig().onComplete!.toString()))
expect(sanitizeStackTrace(readRunConfig('js').onComplete!.toString()))
.toMatchInlineSnapshot(`
"async function onComplete(results, comparisonResults, repositoryCount) {
// Write results to cache
Expand All @@ -75,15 +159,15 @@ describe('run-tester', () => {
});

test('cache is disabled by default', async () => {
await runTester(CONFIG);
await runTester(CONFIG_JS);

expect(readRunConfig().cache).toBe(false);
expect(readRunConfig('js').cache).toBe(false);
});

test('CI is enabled by default', async () => {
await runTester(CONFIG);
await runTester(CONFIG_JS);

expect(readRunConfig().CI).toBe(true);
expect(readRunConfig('js').CI).toBe(true);
});

test('configuration is validated', () => {
Expand Down
Loading

0 comments on commit d6f2ec3

Please sign in to comment.