Skip to content

Commit

Permalink
refactor action and add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason3S committed Mar 3, 2024
1 parent ce05199 commit b0ceef5
Show file tree
Hide file tree
Showing 11 changed files with 121 additions and 50 deletions.
2 changes: 1 addition & 1 deletion action-src/fixtures/cspell.json
@@ -1,5 +1,5 @@
{
"version": "0.1",
"version": "0.2",
"words": ["camelcase", "octokit", "pollyjs", "repos", "shrinkwrap", "streetsidesoftware"],
"ignorePaths": ["node_modules", "action/", "cspell.json", "__recordings__", "**/*.json"],
"overrides": [
Expand Down
4 changes: 4 additions & 0 deletions action-src/fixtures/sampleCode/ts/cspell.config.yaml
@@ -0,0 +1,4 @@
import:
- "../../cspell.json"
files:
- "*.ts"
6 changes: 3 additions & 3 deletions action-src/src/action.test.ts
Expand Up @@ -3,7 +3,7 @@ import * as path from 'path';
import { Context } from '@actions/github/lib/context.js';
import { action } from './action.js';
import { AppError } from './error.js';
import { fetchGithubActionFixture, root } from './test/helper.js';
import { fetchGithubActionFixture, root, sourceDir } from './test/helper.js';
import { beforeEach, describe, expect, test, vi } from 'vitest';

const configFile = path.resolve(root, 'cspell.json');
Expand Down Expand Up @@ -97,8 +97,8 @@ describe('Validate Action', () => {
INPUT_FILES: files,
INPUT_INCREMENTAL_FILES_ONLY: incremental ? 'true' : 'false',
INPUT_CHECK_DOT_FILES: dot,
INPUT_ROOT: path.resolve(root, 'fixtures'),
INPUT_CONFIG: path.resolve(root, 'fixtures/cspell.json'),
INPUT_ROOT: path.resolve(sourceDir, 'fixtures'),
INPUT_CONFIG: path.resolve(sourceDir, 'fixtures/cspell.json'),
};
const context = createContextFromFile(contextFile, params);
await expect(action(context)).resolves.toBe(expected);
Expand Down
49 changes: 7 additions & 42 deletions action-src/src/action.ts
Expand Up @@ -3,19 +3,18 @@ import { debug, info, error, warning, setFailed, setOutput } from '@actions/core
import type { Context as GitHubContext } from '@actions/github/lib/context.js';
import type { RunResult } from 'cspell';
import * as glob from 'cspell-glob';
import { ActionParams, validateActionParams } from './ActionParams.js';
import { validateActionParams } from './ActionParams.js';
import { getActionParams } from './getActionParams.js';
import { CSpellReporterForGithubAction } from './reporter.js';
import { lint, LintOptions } from './spell.js';
import { gitListFilesForPullRequest, gitListFilesForPush, gitRoot } from './git.js';

import type { PushEvent, PullRequestEvent } from '@octokit/webhooks-types';
import { checkDotMap } from './checkDotMap.js';
import { checkSpellingForContext } from './checkSpellingForContext.js';

const core = { debug, error, info, warning };

const defaultGlob = '**';

interface Context {
export interface Context {
githubContext: GitHubContext;
files: string;
useEventFiles: boolean;
Expand All @@ -25,38 +24,6 @@ interface Context {
type EventNames = 'push' | 'pull_request';
const supportedIncrementalEvents = new Set<EventNames | string>(['push', 'pull_request']);

const checkDotMap = {
true: true,
false: false,
explicit: undefined,
} as const;

async function checkSpelling(
params: ActionParams,
globs: string[],
files: string[] | undefined,
): Promise<RunResult | true> {
const options: LintOptions = {
root: params.root || process.cwd(),
config: params.config || undefined,
checkDotFiles: checkDotMap[params.check_dot_files],
files,
};

if (!globs.length && !files?.length) {
return true;
}

const reporterOptions = {
verbose: params.verbose === 'true',
};

const collector = new CSpellReporterForGithubAction(params.inline, reporterOptions, core);
await lint(globs, options, collector.reporter);

return collector.result;
}

function friendlyEventName(eventName: EventNames | string): string {
switch (eventName) {
case 'push':
Expand All @@ -72,7 +39,7 @@ function isSupportedEvent(eventName: EventNames | string): eventName is EventNam
return supportedIncrementalEvents.has(eventName);
}

async function gatherGitCommitFilesFromContext(context: Context): Promise<string[] | undefined> {
export async function gatherGitCommitFilesFromContext(context: Context): Promise<string[] | undefined> {
if (context.useEventFiles) {
const eventFiles = await gatherFiles(context);
if (!eventFiles) return undefined;
Expand All @@ -82,7 +49,7 @@ async function gatherGitCommitFilesFromContext(context: Context): Promise<string
}
}

async function gatherFileGlobsFromContext(context: Context): Promise<Set<string>> {
export async function gatherFileGlobsFromContext(context: Context): Promise<Set<string>> {
const files = new Set<string>(
context.files
.split('\n')
Expand Down Expand Up @@ -155,9 +122,7 @@ export async function action(githubContext: GitHubContext): Promise<boolean> {
};

core.info(friendlyEventName(eventName));
const fileList = await gatherGitCommitFilesFromContext(context);
const files = await gatherFileGlobsFromContext(context);
const result = await checkSpelling(params, fileList ? [] : [...files], fileList);
const result = await checkSpellingForContext(params, context);
if (result === true) {
return true;
}
Expand Down
5 changes: 5 additions & 0 deletions action-src/src/checkDotMap.ts
@@ -0,0 +1,5 @@
export const checkDotMap = {
true: true,
false: false,
explicit: undefined,
} as const;
30 changes: 30 additions & 0 deletions action-src/src/checkSpelling.ts
@@ -0,0 +1,30 @@
import { debug, info, error, warning } from '@actions/core';
import type { RunResult } from 'cspell';
import { ActionParams } from './ActionParams.js';
import { CSpellReporterForGithubAction } from './reporter.js';
import { lint, LintOptions } from './spell.js';
import { checkDotMap } from './checkDotMap.js';

const core = { debug, error, info, warning };

export async function checkSpelling(
params: ActionParams,
globs: string[],
files: string[] | undefined,
): Promise<RunResult> {
const options: LintOptions = {
root: params.root || process.cwd(),
config: params.config || undefined,
checkDotFiles: checkDotMap[params.check_dot_files],
files,
};

const reporterOptions = {
verbose: params.verbose === 'true',
};

const collector = new CSpellReporterForGithubAction(params.inline, reporterOptions, core);
await lint(globs, options, collector.reporter);

return collector.result;
}
11 changes: 11 additions & 0 deletions action-src/src/checkSpellingForContext.ts
@@ -0,0 +1,11 @@
import type { RunResult } from 'cspell';
import { ActionParams } from './ActionParams.js';
import { checkSpelling } from './checkSpelling.js';
import { Context, gatherGitCommitFilesFromContext, gatherFileGlobsFromContext } from './action.js';

export async function checkSpellingForContext(params: ActionParams, context: Context): Promise<true | RunResult> {
const fileList = await gatherGitCommitFilesFromContext(context);
const files = await gatherFileGlobsFromContext(context);
const result = await checkSpelling(params, fileList ? [] : [...files], fileList);
return result;
}
2 changes: 1 addition & 1 deletion action-src/src/git.test.ts
Expand Up @@ -31,7 +31,7 @@ describe('git', () => {
test.each`
contextFile | expected
${'./pull_request_2_context.json'} | ${ac(['README.md'])}
${'./pr_1594_context.json'} | ${ac(['action-src/build.mjs', 'package.json'])}
${'./pr_1594_context.json'} | ${ac(['action-src/build.mjs', 'package.json', 'action-src/package.json', 'action.yaml'])}
`('gitListFilesForContext $contextFile', async ({ contextFile, expected }) => {
const context = await readFixtureFileJSON<Context>(contextFile);
const files = await gitListFilesForContext(context);
Expand Down
41 changes: 40 additions & 1 deletion action-src/src/spell.test.ts
@@ -1,5 +1,5 @@
import * as spell from './spell.js';
import { root } from './test/helper.js';
import { root, sourceDir, resolveFiles, resolveFile } from './test/helper.js';
import { CSpellReporterForGithubAction, Logger } from './reporter.js';
import { describe, expect, test, vi } from 'vitest';

Expand Down Expand Up @@ -79,4 +79,43 @@ describe('Validate Spell Checking', () => {
await spell.lint([glob], options, reporter.reporter);
expect(info.sort()).toEqual(expected);
});

const defaultResult = {
cachedFiles: 0,
errors: 0,
files: 0,
filesWithIssues: new Set(),
issues: 0,
};

const sampleConfig = resolveFile('fixtures/cspell.json', sourceDir);
const sampleConfigTs = resolveFile('fixtures/sampleCode/ts/cspell.config.yaml', sourceDir);

test.only.each`
globs | files | options | expected
${[]} | ${['fixtures/sampleCode/ts/sample.ts']} | ${{}} | ${{ files: 1 }}
${[]} | ${['fixtures/sampleCode/ts/missing.ts']} | ${{}} | ${{ files: 0 }}
${[]} | ${['fixtures/sampleCode/ts/cspell.config.yaml']} | ${{ config: sampleConfig }} | ${{ files: 1 }}
${[]} | ${['fixtures/sampleCode/ts/cspell.config.yaml']} | ${{ config: sampleConfigTs }} | ${{ files: 0 }}
${['**/*.ts']} | ${['fixtures/sampleCode/ts/cspell.config.yaml']} | ${{ config: sampleConfig }} | ${{ files: 1 }}
${['**/ts/missing.ts']} | ${undefined} | ${{}} | ${{ files: 0 }}
`('Linting $globs $files $options', async ({ globs, files, options, expected }) => {
const opts: spell.LintOptions = {
root,
checkDotFiles: undefined,
files: resolveFiles(files, sourceDir),
...options,
};
const info: string[] = [];
const f = () => {};
const logger: Logger = {
error: vi.fn(f),
debug: vi.fn(f),
info: vi.fn((msg) => info.push(msg)),
warning: vi.fn(f),
};
const reporter = new CSpellReporterForGithubAction('none', { verbose: false }, logger);
await spell.lint(globs, opts, reporter.reporter);
expect(reporter.result).toEqual({ ...defaultResult, ...expected });
});
});
12 changes: 10 additions & 2 deletions action-src/src/spell.ts
Expand Up @@ -27,12 +27,20 @@ export async function lint(globs: string[], lintOptions: LintOptions, reporter:
(globs.length && !files) || (files && !globs.length),
'Either globs or files must be specified, but not both.',
);
// console.warn('lint: %o', { globs, lintOptions });
const options: CSpellApplicationOptions = { root, config, files, filterFiles: !files };
// It is expected that `files` in the configuration will be used to filter the files.
const mustFindFiles = !files;
const options: CSpellApplicationOptions = {
root,
config,
files,
// filterFiles: files ? false : undefined,
mustFindFiles,
};
if (checkDotFiles) {
options.dot = true;
} else if (checkDotFiles === false) {
options.dot = false;
}
console.warn('lint: %o', { globs, lintOptions, options });
await cspellAppLint(globs, options, reporter);
}
9 changes: 9 additions & 0 deletions action-src/src/test/helper.ts
Expand Up @@ -34,3 +34,12 @@ export function fetchGithubActionFixture(filename: string): Record<string, strin

return env;
}

export function resolveFile(file: string, rootDir = root): string {
return path.resolve(rootDir, file);
}

export function resolveFiles(files: string[] | undefined, rootDir?: string): string[] | undefined {
if (!files) return files;
return files.map((file) => resolveFile(file, rootDir));
}

0 comments on commit b0ceef5

Please sign in to comment.