-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(core): add esm plugin logic (#248)
- Loading branch information
Showing
16 changed files
with
302 additions
and
96 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import { describe, expect, it } from 'vitest'; | ||
import { | ||
AuditOutputs, | ||
OnProgress, | ||
auditOutputsSchema, | ||
} from '@code-pushup/models'; | ||
import { auditReport, echoRunnerConfig } from '@code-pushup/models/testing'; | ||
import { | ||
RunnerResult, | ||
executeRunnerConfig, | ||
executeRunnerFunction, | ||
} from './runner'; | ||
|
||
const validRunnerCfg = echoRunnerConfig([auditReport()], 'output.json'); | ||
|
||
describe('executeRunnerConfig', () => { | ||
it('should work with valid plugins', async () => { | ||
const runnerResult = await executeRunnerConfig(validRunnerCfg); | ||
|
||
// data sanity | ||
expect(runnerResult.date.endsWith('Z')).toBeTruthy(); | ||
expect(runnerResult.duration).toBeTruthy(); | ||
expect(runnerResult.audits[0]?.slug).toBe('mock-audit-slug'); | ||
|
||
// schema validation | ||
expect(() => auditOutputsSchema.parse(runnerResult.audits)).not.toThrow(); | ||
}); | ||
|
||
it('should use transform if provided', async () => { | ||
const runnerCfgWithTransform = { | ||
...validRunnerCfg, | ||
outputTransform: (audits: unknown) => | ||
(audits as AuditOutputs).map(a => ({ | ||
...a, | ||
displayValue: `transformed - ${a.slug}`, | ||
})), | ||
}; | ||
|
||
const runnerResult = await executeRunnerConfig(runnerCfgWithTransform); | ||
|
||
expect(runnerResult.audits[0]?.displayValue).toBe( | ||
'transformed - mock-audit-slug', | ||
); | ||
}); | ||
|
||
it('should throw if transform throws', async () => { | ||
const runnerCfgWithErrorTransform = { | ||
...validRunnerCfg, | ||
outputTransform: () => { | ||
return Promise.reject(new Error('transform mock error')); | ||
}, | ||
}; | ||
|
||
await expect( | ||
executeRunnerConfig(runnerCfgWithErrorTransform), | ||
).rejects.toThrow('transform mock error'); | ||
}); | ||
}); | ||
|
||
describe('executeRunnerFunction', () => { | ||
it('should execute valid plugin config', async () => { | ||
const nextSpy = vi.fn(); | ||
const runnerResult: RunnerResult = await executeRunnerFunction( | ||
(observer?: OnProgress) => { | ||
observer?.('update'); | ||
|
||
return Promise.resolve([ | ||
{ slug: 'mock-audit-slug', score: 0, value: 0 }, | ||
] satisfies AuditOutputs); | ||
}, | ||
nextSpy, | ||
); | ||
expect(nextSpy).toHaveBeenCalledWith('update'); | ||
expect(runnerResult.audits[0]?.slug).toBe('mock-audit-slug'); | ||
}); | ||
|
||
it('should throw if plugin throws', async () => { | ||
const nextSpy = vi.fn(); | ||
await expect( | ||
executeRunnerFunction( | ||
() => Promise.reject(new Error('plugin exec mock error')), | ||
nextSpy, | ||
), | ||
).rejects.toThrow('plugin exec mock error'); | ||
expect(nextSpy).not.toHaveBeenCalled(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import { join } from 'path'; | ||
import { | ||
AuditOutputs, | ||
OnProgress, | ||
RunnerConfig, | ||
RunnerFunction, | ||
} from '@code-pushup/models'; | ||
import { calcDuration, executeProcess, readJsonFile } from '@code-pushup/utils'; | ||
|
||
export type RunnerResult = { | ||
date: string; | ||
duration: number; | ||
audits: AuditOutputs; | ||
}; | ||
|
||
export async function executeRunnerConfig( | ||
cfg: RunnerConfig, | ||
onProgress?: OnProgress, | ||
): Promise<RunnerResult> { | ||
const { args, command, outputFile, outputTransform } = cfg; | ||
|
||
// execute process | ||
const { duration, date } = await executeProcess({ | ||
command, | ||
args, | ||
observer: { onStdout: onProgress }, | ||
}); | ||
|
||
// read process output from file system and parse it | ||
let audits = await readJsonFile<AuditOutputs>( | ||
join(process.cwd(), outputFile), | ||
); | ||
|
||
// transform unknownAuditOutputs to auditOutputs | ||
if (outputTransform) { | ||
audits = await outputTransform(audits); | ||
} | ||
|
||
// create runner result | ||
return { | ||
duration, | ||
date, | ||
audits, | ||
}; | ||
} | ||
|
||
export async function executeRunnerFunction( | ||
runner: RunnerFunction, | ||
onProgress?: OnProgress, | ||
): Promise<RunnerResult> { | ||
const date = new Date().toISOString(); | ||
const start = performance.now(); | ||
|
||
// execute plugin runner | ||
const audits = await runner(onProgress); | ||
|
||
// create runner result | ||
return { | ||
date, | ||
duration: calcDuration(start), | ||
audits, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.