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

[TS migration] Migrate 'utils' workflow test to TypeScript #83

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
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
1,460 changes: 197 additions & 1,263 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
"test:e2e:dev": "ts-node tests/e2e/testRunner.ts --config ./config.dev.ts",
"gh-actions-unused-styles": "./.github/scripts/findUnusedKeys.sh",
"workflow-test": "./workflow_tests/scripts/runWorkflowTests.sh",
"workflow-test:generate": "ts-node workflow_tests/utils/preGenerateTest.js",
"workflow-test:generate": "ts-node workflow_tests/utils/preGenerateTest.ts",
"setup-https": "mkcert -install && mkcert -cert-file config/webpack/certificate.pem -key-file config/webpack/key.pem dev.new.expensify.com localhost 127.0.0.1",
"e2e-test-runner-build": "ncc build tests/e2e/testRunner.ts -o tests/e2e/dist/"
},
Expand Down Expand Up @@ -286,6 +286,7 @@
"shellcheck": "^1.1.0",
"style-loader": "^2.0.0",
"time-analytics-webpack-plugin": "^0.1.17",
"ts-jest": "^29.1.2",
"ts-node": "^10.9.2",
"type-fest": "^4.10.2",
"typescript": "^5.3.2",
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,6 @@
}
},
"exclude": ["**/node_modules/*", "**/dist/*", ".github/actions/**/index.js", "**/docs/*"],
"include": ["src", "desktop", "web", "website", "docs", "assets", "config", "tests", "jest", "__mocks__", ".github/**/*", ".storybook/**/*"],
"include": ["src", "desktop", "web", "website", "docs", "assets", "config", "tests", "jest", "__mocks__", ".github/**/*", ".storybook/**/*", "workflow_tests"],
"extends": "expo/tsconfig.base"
}
1 change: 1 addition & 0 deletions workflow_tests/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module.exports = {
verbose: true,
transform: {
'^.+\\.jsx?$': 'babel-jest',
'^.+\\.tsx?$': 'ts-jest',
},
clearMocks: true,
resetMocks: true,
Expand Down
44 changes: 0 additions & 44 deletions workflow_tests/utils/ExtendedAct.js

This file was deleted.

50 changes: 50 additions & 0 deletions workflow_tests/utils/ExtendedAct.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/* eslint-disable @typescript-eslint/dot-notation */
// This eslint-disable comment is here to allow accessing private properties in the Act class
import type {RunOpts, Workflow} from '@kie/act-js';
import * as kieActJs from '@kie/act-js';
import path from 'path';
import {JobMocker} from './JobMocker';
import type {MockJob} from './JobMocker';

type ExtendedActOpts = RunOpts & {actor?: string; workflowFile?: string; mockJobs?: Record<string, MockJob>};

// @ts-expect-error Override shouldn't be done on private methods wait until https://github.com/kiegroup/act-js/issues/77 is resolved or try to create a params workaround
class ExtendedAct extends kieActJs.Act {
async parseRunOpts(opts?: ExtendedActOpts) {
const {cwd, actArguments, proxy} = await super['parseRunOpts'](opts);
if (opts?.actor) {
actArguments.push('--actor', opts.actor);
}
return {cwd, actArguments, proxy};
}

async runEvent(event: string, opts?: ExtendedActOpts) {
const {mockJobs, ...vanillaOpts} = opts ?? {};

if (mockJobs) {
await this.handleJobMocking((workflow) => workflow.events.includes(event), {mockJobs, workflowFile: opts?.workflowFile, cwd: opts?.cwd});
}
return super.runEvent(event, vanillaOpts);
}

async handleJobMocking(filter: (workflow: Workflow) => boolean, opts?: ExtendedActOpts) {
let workflowFiles: string[];
if (opts?.workflowFile) {
workflowFiles = [path.basename(opts.workflowFile)];
} else if (this['workflowFile'] !== this['cwd']) {
workflowFiles = [path.basename(this['workflowFile'])];
} else {
const availableWorkflows = await this.list(undefined, opts?.cwd, opts?.workflowFile);
workflowFiles = availableWorkflows.filter(filter).map((workflow: Workflow) => workflow.workflowFile);
}
return Promise.all(
workflowFiles.map((workflowFile) => {
const jobMocker = new JobMocker(workflowFile, opts?.cwd ?? this['cwd']);
return jobMocker.mock(opts?.mockJobs);
}),
);
}
}

// eslint-disable-next-line import/prefer-default-export
export {ExtendedAct};
Original file line number Diff line number Diff line change
@@ -1,17 +1,48 @@
const fs = require('fs');
const path = require('path');
const yaml = require('yaml');
const _ = require('underscore');
import type {PathOrFileDescriptor} from 'fs';
import fs from 'fs';
import path from 'path';
import yaml from 'yaml';

// eslint-disable-next-line @typescript-eslint/naming-convention
type YamlMockJob = Omit<MockJob, 'runsOn'> & {'runs-on'?: string};

type YamlWorkflow = {
jobs: Record<string, YamlMockJob>;
};

type MockJob = {
steps: MockJobStep[];
uses?: string;
secrets?: string[];
with?: string;
outputs?: string[];
runsOn: string;
};

type MockJobStep = {
id?: string;
name: string;
run?: string;
mockWith?: string;
with?: string;
envs?: string[];
inputs?: string[];
};

class JobMocker {
constructor(workflowFile, cwd) {
workflowFile: string;

cwd: string;

constructor(workflowFile: string, cwd: string) {
this.workflowFile = workflowFile;
this.cwd = cwd;
}

async mock(mockJobs) {
mock(mockJobs: Record<string, MockJob> = {}) {
const filePath = this.getWorkflowPath();
const workflow = await this.readWorkflowFile(filePath);
const workflow = this.readWorkflowFile(filePath);

Object.entries(mockJobs).forEach(([jobId, mockJob]) => {
const job = this.locateJob(workflow, jobId);
if (job) {
Expand All @@ -21,13 +52,13 @@ class JobMocker {
if (job.secrets) {
delete job.secrets;
}
let jobWith;
let jobWith: string | undefined;
if (job.with) {
jobWith = job.with;
delete job.with;
}
job.steps = _(mockJob.steps).map((step) => {
const mockStep = {
job.steps = mockJob.steps.map((step) => {
const mockStep: MockJobStep = {
name: step.name,
run: step.mockWith,
};
Expand All @@ -52,7 +83,7 @@ class JobMocker {
return this.writeWorkflowFile(filePath, workflow);
}

locateJob(workflow, jobId) {
locateJob(workflow: YamlWorkflow, jobId: string) {
return workflow.jobs[jobId];
}

Expand All @@ -69,15 +100,17 @@ class JobMocker {
throw new Error(`Could not locate ${this.workflowFile}`);
}

async readWorkflowFile(location) {
return yaml.parse(fs.readFileSync(location, 'utf8'));
readWorkflowFile(location: PathOrFileDescriptor) {
const test: YamlWorkflow = yaml.parse(fs.readFileSync(location, 'utf8'));

return test;
}

async writeWorkflowFile(location, data) {
writeWorkflowFile(location: PathOrFileDescriptor, data: YamlWorkflow) {
return fs.writeFileSync(location, yaml.stringify(data), 'utf8');
}
}

module.exports = {
JobMocker,
};
// eslint-disable-next-line import/prefer-default-export
export {JobMocker};
export type {MockJob, YamlWorkflow, YamlMockJob, MockJobStep};
Loading
Loading