util#format TypeScript Examples
The following examples show how to use
util#format.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: hooks.ts From posthog-foss with MIT License | 6 votes |
export function getFormattedMessage(
action: Action,
event: PluginEvent,
person: Person | undefined,
siteUrl: string,
webhookType: WebhookType
): [string, string] {
const messageFormat = action.slack_message_format || '[action.name] was triggered by [user.name]'
let messageText: string
let messageMarkdown: string
try {
const [tokens, tokenizedMessage] = getTokens(messageFormat)
const values: string[] = []
const markdownValues: string[] = []
for (const token of tokens) {
const tokenParts = token.match(/\w+/g) || []
const [value, markdownValue] = getValueOfToken(action, event, person, siteUrl, webhookType, tokenParts)
values.push(value)
markdownValues.push(markdownValue)
}
messageText = format(tokenizedMessage, ...values)
messageMarkdown = format(tokenizedMessage, ...markdownValues)
} catch (error) {
const [actionName, actionMarkdown] = getActionDetails(action, siteUrl, webhookType)
messageText = `⚠ Error: There are one or more formatting errors in the message template for action "${actionName}".`
messageMarkdown = `*⚠ Error: There are one or more formatting errors in the message template for action "${actionMarkdown}".*`
}
return [messageText, messageMarkdown]
}
Example #2
Source File: echo.ts From gitmars with GNU General Public License v3.0 | 6 votes |
/**
* 读取gitmars在线版本列表
*
* @param name - 需要查询的内容
* @returns {Object} arr 返回配置对象
*/
function echo(message: string): void {
let output = format(message)
output += '\n'
process.stdout.write(output)
}
Example #3
Source File: echo.ts From gitmars with GNU General Public License v3.0 | 6 votes |
/**
* 输出日志
* @example
*
* @param message - 需要输出的内容
* @param type - 输出的类型
*/
function echo(
message: string,
type?: 'warning' | 'info' | 'error' | 'success'
): void {
let output = format(message)
switch (type) {
case 'warning':
output = yellow(output)
break
case 'error':
output = red(output)
break
case 'success':
output = green(output)
break
default:
break
}
output += '\n'
process.stdout.write(output)
}
Example #4
Source File: installer.ts From azure-pipelines-tasks-flyway with MIT License | 6 votes |
function getDownloadUrl(version: string): string {
var url = format("https://repo1.maven.org/maven2/org/flywaydb/flyway-commandline/%s/flyway-commandline-%s-%s", version, version);
switch(os.type()){
case 'Linux':
return format(url, "linux-x64.tar.gz");
case 'Darwin':
return format(url, "macosx-x64.tar.gz");
case 'Windows_NT':
return format(url, "windows-x64.zip");
default:
throw new Error(`Operating system ${os.type()} is not supported.`);
}
}
Example #5
Source File: filestorage.ts From foodie with MIT License | 6 votes |
uploadImageToStorage = (file) => {
return new Promise((resolve, reject) => {
if (!file) {
reject('No image file');
}
let newFileName = `${file.originalname}`;
let fileUpload = bucket.file(newFileName);
const blobStream = fileUpload.createWriteStream({
metadata: {
contentType: file.mimetype
}
});
blobStream.on('error', (err) => {
console.log(err);
reject('Something is wrong! Unable to upload at the moment.');
});
blobStream.on('finish', () => {
// The public URL can be used to directly access the file via HTTP.
const url = format(`https://storage.googleapis.com/${bucket.name}/${fileUpload.name}`);
resolve(url);
});
blobStream.end(file.buffer);
});
}
Example #6
Source File: debug.ts From hoprnet with GNU General Public License v3.0 | 6 votes |
wrappedDebug = (namespace: any) => {
return (message: any, ...parameters: any[]) => {
if (process.env.TELEMETRY && process.env.TELEMETRY_ID) {
const log = format(message, ...parameters)
logger.info({ id: process.env.TELEMETRY_ID, log: log, ts: new Date(Date.now()).toISOString() })
}
return debug(namespace)(message, ...parameters)
}
}
Example #7
Source File: log-delivery.ts From cloudformation-cli-typescript-plugin with Apache License 2.0 | 6 votes |
log(message?: any, ...optionalParams: any[]): void {
const formatted = format(message, ...optionalParams);
const eventTime = new Date(Date.now());
for (const logPublisher of this.logPublishers) {
this.tracker.addSubmitted();
(async () => {
try {
await logPublisher.publishLogEvent(formatted, eventTime);
this.tracker.addCompleted();
} catch (err) {
console.error(err);
if (err.retryable === true) {
try {
await logPublisher.publishLogEvent(formatted, eventTime);
this.tracker.addCompleted();
} catch (err) {
console.error(err);
this.tracker.addFailed();
}
} else {
this.tracker.addFailed();
}
}
})();
}
}
Example #8
Source File: nexpect.ts From amplify-codegen with Apache License 2.0 | 6 votes |
function createExpectationError(expected: string | RegExp, actual: string) {
var expectation;
if (isRegExp(expected)) {
expectation = 'to match ' + expected;
} else {
expectation = 'to contain ' + JSON.stringify(expected);
}
var err = new AssertionError({
message: format('expected %j %s', actual, expectation),
actual: actual,
expected: expected,
});
return err;
}
Example #9
Source File: filesystem.ts From devoirs with MIT License | 6 votes |
async load(): Promise<Token> {
const path = await this.getPath();
if (!(await this.exists())) {
throw new Error(format('File not exists or not a file: %s', path));
}
return await readFile(path, {
encoding: this.encoding,
});
}
Example #10
Source File: client.ts From devoirs with MIT License | 6 votes |
transform = (assignment: Assignment) => {
const dueDateTime = moment(assignment.dueDateTime);
const nowDateTime = moment();
return {
...assignment,
dueDateTime: dueDateTime.format('ll LTS'),
isOverdue: !assignment.isCompleted && dueDateTime.isBefore(nowDateTime),
};
}
Example #11
Source File: log.ts From elephize with MIT License | 6 votes |
public _printLog(message: string, msgid: string, params: string[], severity: LogSeverity, context = '') {
if (this.baseDir && severity !== LogSeverity.SPECIAL) {
message = message.replace(this.baseDir, '[base]');
}
if (this.outDir && severity !== LogSeverity.SPECIAL) {
message = message.replace(this.outDir, '[out]');
}
let marker: string = chalk.dim(`[i #${msgid}]`);
switch (severity) {
case LogSeverity.ERROR:
marker = chalk.bgRedBright(chalk.black(`[E #${msgid}]`));
break;
case LogSeverity.WARN:
marker = chalk.bgYellowBright(chalk.black(`[W #${msgid}]`));
break;
case LogSeverity.SPECIAL:
marker = chalk.bgGreenBright(chalk.black(`[! #${msgid}]`));
break;
case LogSeverity.INFO:
default:
break;
}
message = format(message, ...params); // apply parameters to string strictly after hashing
const dt = new Date();
const pieces = [dt.getHours(), dt.getMinutes(), dt.getSeconds()].map((p) => p.toString().padStart(2, '0'));
const timer = chalk.ansi(90)(`[${pieces.join(':')}:${dt.getMilliseconds().toString().padStart(3, '0')}]`);
const str = `${marker}${timer} ${message}${context ? '\n ' + context : ''}`;
if (severity === LogSeverity.ERROR || this.forceStderr) {
writeSync(STDERR_FILE_DESCRIPTOR, str + (str.endsWith('\n') ? '' : '\n'));
} else {
writeSync(STDOUT_FILE_DESCRIPTOR, str + (str.endsWith('\n') ? '' : '\n'));
}
}
Example #12
Source File: log.ts From AIPerf with MIT License | 6 votes |
/**
* if the experiment is not in readonly mode, write log content to stream
* @param level log level
* @param param the params to be written
*/
private log(level: string, param: any[]): void {
if (!this.readonly) {
const logContent = `[${(new Date()).toLocaleString()}] ${level} ${format(param)}\n`;
if (this.writable && this.bufferSerialEmitter) {
const buffer: WritableStreamBuffer = new WritableStreamBuffer();
buffer.write(logContent);
buffer.end();
this.bufferSerialEmitter.feed(buffer.getContents());
} else {
console.log(logContent);
}
}
}
Example #13
Source File: client.ts From devoirs with MIT License | 5 votes |
async start(): Promise<void> {
const assetsDirectory = await this.resourceResolver.resolve('assets');
const page = await this.chromiumLauncher.launch(
format(
'file:///%s',
[...assetsDirectory.split(sep).map(encode), 'index.html'].join('/')
)
);
for (const c of await this.apiClient.getClasses()) {
const assignments = (await this.apiClient.getAssignments(c.id))
.sort(compare)
.map(transform);
await page.evaluate(
(c: Class, assignments: (Assignment & { isOverdue: boolean })[]) => {
const $classes = document.getElementById('classes');
const $class = document.createElement('li');
const $name = document.createElement('span');
const $assignments = document.createElement('ul');
for (const a of assignments) {
const $assignment = document.createElement('li');
$assignment.textContent = a.displayName;
$assignment.setAttribute('data-due-datetime', a.dueDateTime);
$assignment.setAttribute('data-overdue', a.isOverdue ? '1' : '0');
$assignment.setAttribute(
'data-completed',
a.isCompleted ? '1' : '0'
);
$assignments.appendChild($assignment);
}
$name.textContent = c.name;
$name.addEventListener('click', () => {
$class.classList.toggle('is-hidden');
});
$class.appendChild($name);
$class.appendChild($assignments);
$classes.appendChild($class);
},
(c as unknown) as JSONObject,
(assignments as unknown) as JSONObject
);
}
}
Example #14
Source File: update-electron-app.ts From tailchat with GNU General Public License v3.0 | 5 votes |
userAgent = format(
'%s/%s (%s: %s)',
pkg.name,
pkg.version,
os.platform(),
os.arch()
)
Example #15
Source File: Logger.ts From yumeko with GNU Affero General Public License v3.0 | 5 votes |
public date(): string {
return moment(Date.now()).format(momentFormat);
}
Example #16
Source File: Logger.ts From yumeko with GNU Affero General Public License v3.0 | 5 votes |
public color(input: unknown, hex: string): string {
input = typeof input === "string" ? input : format(input);
return chalk.hex(hex)(input);
}
Example #17
Source File: Logger.ts From yumeko with GNU Affero General Public License v3.0 | 5 votes |
public print(input: unknown): void {
process.stdout.write(`${format(input)}\n`);
}
Example #18
Source File: solidity-unit-testing.tsx From remix-project with MIT License | 4 votes |
SolidityUnitTesting = (props: Record<string, any>) => { // eslint-disable-line @typescript-eslint/no-explicit-any
const { helper, testTab, initialPath } = props
const { testTabLogic } = testTab
const [toasterMsg, setToasterMsg] = useState<string>('')
const [disableCreateButton, setDisableCreateButton] = useState<boolean>(true)
const [disableGenerateButton, setDisableGenerateButton] = useState<boolean>(false)
const [disableStopButton, setDisableStopButton] = useState<boolean>(true)
const [disableRunButton, setDisableRunButton] = useState<boolean>(false)
const [runButtonTitle, setRunButtonTitle] = useState<string>('Run tests')
const [stopButtonLabel, setStopButtonLabel] = useState<string>('Stop')
const [checkSelectAll, setCheckSelectAll] = useState<boolean>(true)
const [testsOutput, setTestsOutput] = useState<ReactElement[]>([])
const [testsExecutionStoppedHidden, setTestsExecutionStoppedHidden] = useState<boolean>(true)
const [progressBarHidden, setProgressBarHidden] = useState<boolean>(true)
const [testsExecutionStoppedErrorHidden, setTestsExecutionStoppedErrorHidden] = useState<boolean>(true)
let [testFiles, setTestFiles] = useState<TestObject[]>([]) // eslint-disable-line
const [pathOptions, setPathOptions] = useState<string[]>([''])
const [inputPathValue, setInputPathValue] = useState<string>('tests')
let [readyTestsNumber, setReadyTestsNumber] = useState<number>(0) // eslint-disable-line
let [runningTestsNumber, setRunningTestsNumber] = useState<number>(0) // eslint-disable-line
const areTestsRunning = useRef<boolean>(false)
const hasBeenStopped = useRef<boolean>(false)
const isDebugging = useRef<boolean>(false)
const allTests = useRef<string[]>([])
const selectedTests = useRef<string[]>([])
const currentTestFiles:any = useRef([]) // stores files for which tests have been run
const currentErrors:any = useRef([]) // eslint-disable-line @typescript-eslint/no-explicit-any
const defaultPath = 'tests'
let runningTestFileName: string
const filesContent: Record<string, Record<string, string>> = {}
const testsResultByFilename: Record<string, Record<string, Record<string, any>>> = {} // eslint-disable-line @typescript-eslint/no-explicit-any
const trimTestDirInput = (input: string) => {
if (input.includes('/')) return input.split('/').map(e => e.trim()).join('/')
else return input.trim()
}
const clearResults = () => {
setProgressBarHidden(true)
testTab.call('editor', 'clearAnnotations')
setTestsOutput([])
setTestsExecutionStoppedHidden(true)
setTestsExecutionStoppedErrorHidden(true)
}
const updateForNewCurrent = async (file: string | null = null) => {
// Ensure that when someone clicks on compilation error and that opens a new file
// Test result, which is compilation error in this case, is not cleared
if (currentErrors.current) {
if (Array.isArray(currentErrors.current) && currentErrors.current.length > 0) {
const errFiles = currentErrors.current.map((err:any) => { if (err.sourceLocation && err.sourceLocation.file) return err.sourceLocation.file }) // eslint-disable-line
if (errFiles.includes(file)) return
} else if (currentErrors.current.sourceLocation && currentErrors.current.sourceLocation.file && currentErrors.current.sourceLocation.file === file) return
}
// if current file is changed while debugging and one of the files imported in test file are opened
// do not clear the test results in SUT plugin
if ((isDebugging.current && testTab.allFilesInvolved.includes(file)) || currentTestFiles.current.includes(file)) return
allTests.current = []
updateTestFileList()
clearResults()
try {
const tests = await testTabLogic.getTests()
allTests.current = tests
selectedTests.current = [...allTests.current]
updateTestFileList()
if (!areTestsRunning.current) await updateRunAction(file)
} catch (e: any) { // eslint-disable-line @typescript-eslint/no-explicit-any
console.log(e)
setToasterMsg(e)
}
}
/**
* Changes the current path of Unit Testing Plugin
* @param path - the path from where UT plugin takes _test.sol files to run
*/
const setCurrentPath = async (path: string) => {
testTabLogic.setCurrentPath(path)
setInputPathValue(path)
updateDirList(path)
await updateForNewCurrent()
}
useEffect(() => {
if (initialPath) setCurrentPath(initialPath)
}, [initialPath]) // eslint-disable-line react-hooks/exhaustive-deps
useEffect(() => {
testTab.on('filePanel', 'newTestFileCreated', async (file: string) => {
try {
const tests = await testTabLogic.getTests()
allTests.current = tests
selectedTests.current = [...allTests.current]
updateTestFileList()
} catch (e) {
console.log(e)
allTests.current.push(file)
selectedTests.current.push(file)
}
})
testTab.on('filePanel', 'setWorkspace', async () => {
await setCurrentPath(defaultPath)
})
testTab.fileManager.events.on('noFileSelected', async () => { await updateForNewCurrent() })
testTab.fileManager.events.on('currentFileChanged', async (file: string) => await updateForNewCurrent(file))
}, []) // eslint-disable-line
const updateDirList = (path: string) => {
testTabLogic.dirList(path).then((options: string[]) => {
setPathOptions(options)
})
}
const handleTestDirInput = async (e: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any
let testDirInput = trimTestDirInput(e.target.value)
testDirInput = helper.removeMultipleSlashes(testDirInput)
setInputPathValue(testDirInput)
if (testDirInput) {
if (testDirInput.endsWith('/') && testDirInput !== '/') {
testDirInput = helper.removeTrailingSlashes(testDirInput)
if (testTabLogic.currentPath === testDirInput.substr(0, testDirInput.length - 1)) {
setDisableCreateButton(true)
setDisableGenerateButton(true)
}
updateDirList(testDirInput)
} else {
// If there is no matching folder in the workspace with entered text, enable Create button
if (await testTabLogic.pathExists(testDirInput)) {
setDisableCreateButton(true)
setDisableGenerateButton(false)
} else {
// Enable Create button
setDisableCreateButton(false)
// Disable Generate button because dir does not exist
setDisableGenerateButton(true)
}
await setCurrentPath(testDirInput)
}
} else {
await setCurrentPath('/')
setDisableCreateButton(true)
setDisableGenerateButton(false)
}
}
const handleCreateFolder = async () => {
let inputPath = trimTestDirInput(inputPathValue)
let path = helper.removeMultipleSlashes(inputPath)
if (path !== '/') path = helper.removeTrailingSlashes(path)
if (inputPath === '') inputPath = defaultPath
setInputPathValue(path)
await testTabLogic.generateTestFolder(inputPath)
setToasterMsg('Folder created successfully')
setDisableCreateButton(true)
setDisableGenerateButton(false)
testTabLogic.setCurrentPath(inputPath)
await updateRunAction()
await updateForNewCurrent()
pathOptions.push(inputPath)
setPathOptions(pathOptions)
}
const cleanFileName = (fileName: string, testSuite: string) => {
return fileName ? fileName.replace(/\//g, '_').replace(/\./g, '_') + testSuite : fileName
}
const startDebug = async (txHash: string, web3: Web3) => {
isDebugging.current = true
if (!await testTab.appManager.isActive('debugger')) await testTab.appManager.activatePlugin('debugger')
testTab.call('menuicons', 'select', 'debugger')
testTab.call('debugger', 'debug', txHash, web3)
}
const printHHLogs = (logsArr: Record<string, any>[], testName: string) => { // eslint-disable-line @typescript-eslint/no-explicit-any
let finalLogs = `<b>${testName}:</b>\n`
for (const log of logsArr) {
let formattedLog
// Hardhat implements the same formatting options that can be found in Node.js' console.log,
// which in turn uses util.format: https://nodejs.org/dist/latest-v12.x/docs/api/util.html#util_util_format_format_args
// For example: console.log("Name: %s, Age: %d", remix, 6) will log 'Name: remix, Age: 6'
// We check first arg to determine if 'util.format' is needed
if (typeof log[0] === 'string' && (log[0].includes('%s') || log[0].includes('%d'))) {
formattedLog = format(log[0], ...log.slice(1))
} else {
formattedLog = log.join(' ')
}
finalLogs = finalLogs + ' ' + formattedLog + '\n'
}
_paq.push(['trackEvent', 'solidityUnitTesting', 'hardhat', 'console.log'])
testTab.call('terminal', 'log', { type: 'info', value: finalLogs })
}
const discardHighlight = async () => {
await testTab.call('editor', 'discardHighlight')
}
const highlightLocation = async (location: string, fileName: string) => {
if (location) {
const split = location.split(':')
const file = split[2]
const parsedLocation = {
start: parseInt(split[0]),
length: parseInt(split[1])
}
const locationToHighlight = testTab.offsetToLineColumnConverter.offsetToLineColumnWithContent(
parsedLocation,
parseInt(file),
filesContent[fileName].content
)
await testTab.call('editor', 'discardHighlight')
await testTab.call('editor', 'highlight', locationToHighlight, fileName, '', { focus: true })
}
}
const renderContract = (filename: string, contract: string|null, index: number, withoutLabel = false) => {
if (withoutLabel) {
const contractCard: ReactElement = (
<div id={runningTestFileName} data-id="testTabSolidityUnitTestsOutputheader" className="pt-1">
<span className="font-weight-bold">{contract ? contract : ''} ({filename})</span>
</div>
)
setTestsOutput(prevCards => ([...prevCards, contractCard]))
return
}
let label
if (index > -1) {
const className = "alert-danger d-inline-block mb-1 mr-1 p-1 failed_" + runningTestFileName
label = (<div
className={className}
title="At least one contract test failed"
>
FAIL
</div>)
} else {
const className = "alert-success d-inline-block mb-1 mr-1 p-1 passed_" + runningTestFileName
label = (<div
className={className}
title="All contract tests passed"
>
PASS
</div>)
}
// show contract and file name with label
const ContractCard: ReactElement = (
<div id={runningTestFileName} data-id="testTabSolidityUnitTestsOutputheader" className="pt-1">
{label}<span className="font-weight-bold">{contract} ({filename})</span>
</div>
)
setTestsOutput(prevCards => {
const index = prevCards.findIndex((card: ReactElement) => card.props.id === runningTestFileName)
prevCards[index] = ContractCard
return prevCards
})
}
const renderTests = (tests: TestResultInterface[], contract: string, filename: string) => {
const index = tests.findIndex((test: TestResultInterface) => test.type === 'testFailure')
// show filename and contract
renderContract(filename, contract, index)
// show tests
for (const test of tests) {
if (!test.rendered) {
let debugBtn
if (test.debugTxHash) {
const { web3, debugTxHash } = test
debugBtn = (
<div id={test.value.replaceAll(' ', '_')} className="btn border btn btn-sm ml-1" style={{ cursor: 'pointer' }} title="Start debugging" onClick={() => startDebug(debugTxHash, web3)}>
<i className="fas fa-bug"></i>
</div>
)
}
if (test.type === 'testPass') {
if (test.hhLogs && test.hhLogs.length) printHHLogs(test.hhLogs, test.value)
const testPassCard: ReactElement = (
<div
id={runningTestFileName}
data-id="testTabSolidityUnitTestsOutputheader"
className="testPass testLog bg-light mb-2 px-2 text-success border-0"
onClick={() => discardHighlight()}
>
<div className="d-flex my-1 align-items-start justify-content-between">
<span > ✓ {test.value}</span>
{debugBtn}
</div>
</div>
)
setTestsOutput(prevCards => ([...prevCards, testPassCard]))
test.rendered = true
} else if (test.type === 'testFailure') {
if (test.hhLogs && test.hhLogs.length) printHHLogs(test.hhLogs, test.value)
if (!test.assertMethod) {
const testFailCard1: ReactElement = (<div
className="bg-light mb-2 px-2 testLog d-flex flex-column text-danger border-0"
id={"UTContext" + test.context}
onClick={() => { if(test.location) highlightLocation(test.location, test.filename)}}
>
<div className="d-flex my-1 align-items-start justify-content-between">
<span> ✘ {test.value}</span>
{debugBtn}
</div>
<span className="text-dark">Error Message:</span>
<span className="pb-2 text-break">"{test.errMsg}"</span>
</div>)
setTestsOutput(prevCards => ([...prevCards, testFailCard1]))
} else {
const preposition = test.assertMethod === 'equal' || test.assertMethod === 'notEqual' ? 'to' : ''
const method = test.assertMethod === 'ok' ? '' : test.assertMethod
const expected = test.assertMethod === 'ok' ? '\'true\'' : test.expected
const testFailCard2: ReactElement = (<div
className="bg-light mb-2 px-2 testLog d-flex flex-column text-danger border-0"
id={"UTContext" + test.context}
onClick={() => { if(test.location) highlightLocation(test.location, test.filename)}}
>
<div className="d-flex my-1 align-items-start justify-content-between">
<span> ✘ {test.value}</span>
{debugBtn}
</div>
<span className="text-dark">Error Message:</span>
<span className="pb-2 text-break">"{test.errMsg}"</span>
<span className="text-dark">Assertion:</span>
<div className="d-flex flex-wrap">
<span>Expected value should be</span>
<div className="mx-1 font-weight-bold">{method}</div>
<div>{preposition} {expected}</div>
</div>
<span className="text-dark">Received value:</span>
<span>{test.returned}</span>
<span className="text-dark text-sm pb-2">Skipping the remaining tests of the function.</span>
</div>)
setTestsOutput(prevCards => ([...prevCards, testFailCard2]))
}
test.rendered = true
} else if (test.type === 'logOnly') {
if (test.hhLogs && test.hhLogs.length) printHHLogs(test.hhLogs, test.value)
test.rendered = true
}
}
}
}
const showTestsResult = () => {
const filenames = Object.keys(testsResultByFilename)
currentTestFiles.current = filenames
for (const filename of filenames) {
const fileTestsResult = testsResultByFilename[filename]
const contracts = Object.keys(fileTestsResult)
for (const contract of contracts) {
if (contract && contract !== 'summary' && contract !== 'errors') {
runningTestFileName = cleanFileName(filename, contract)
const tests = fileTestsResult[contract] as TestResultInterface[]
if (tests?.length) {
renderTests(tests, contract, filename)
} else {
// show only contract and file name
renderContract(filename, contract, -1, true)
}
} else if (contract === 'errors' && fileTestsResult['errors']) {
const errors = fileTestsResult['errors']
if (errors && errors.errors) {
errors.errors.forEach((err: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any
const errorCard: ReactElement = <Renderer message={err.formattedMessage || err.message} plugin={testTab} opt={{ type: err.severity, errorType: err.type }} />
setTestsOutput(prevCards => ([...prevCards, errorCard]))
})
} else if (errors && Array.isArray(errors) && (errors[0].message || errors[0].formattedMessage)) {
errors.forEach((err) => {
const errorCard: ReactElement = <Renderer message={err.formattedMessage || err.message} plugin={testTab} opt={{ type: err.severity, errorType: err.type }} />
setTestsOutput(prevCards => ([...prevCards, errorCard]))
})
} else if (errors && !errors.errors && !Array.isArray(errors)) {
// To track error like this: https://github.com/ethereum/remix/pull/1438
const errorCard: ReactElement = <Renderer message={errors.formattedMessage || errors.message} plugin={testTab} opt={{ type: 'error' }} />
setTestsOutput(prevCards => ([...prevCards, errorCard]))
}
}
}
// show summary
const testSummary = fileTestsResult['summary']
if (testSummary && testSummary.filename && !testSummary.rendered) {
const summaryCard: ReactElement = (<div className="d-flex alert-secondary mb-3 p-3 flex-column">
<span className="font-weight-bold">Result for {testSummary.filename}</span>
<span className="text-success">Passed: {testSummary.passed}</span>
<span className="text-danger">Failed: {testSummary.failed}</span>
<span>Time Taken: {testSummary.timeTaken}s</span>
</div>)
setTestsOutput(prevCards => ([...prevCards, summaryCard]))
fileTestsResult['summary']['rendered'] = true
}
}
}
const testCallback = (result: Record<string, any>) => { // eslint-disable-line @typescript-eslint/no-explicit-any
if (result.filename) {
if (!testsResultByFilename[result.filename]) {
testsResultByFilename[result.filename] = {}
testsResultByFilename[result.filename]['summary'] = {}
}
if (result.type === 'contract') {
testsResultByFilename[result.filename][result.value] = {}
testsResultByFilename[result.filename][result.value] = []
} else {
// Set that this test is not rendered on UI
result.rendered = false
testsResultByFilename[result.filename][result.context].push(result)
}
showTestsResult()
}
}
const resultsCallback = (_err: any, result: any, cb: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any
// total stats for the test
// result.passingNum
// result.failureNum
// result.timePassed
cb()
}
const updateFinalResult = (_errors: any, result: FinalResult|null, filename: string) => { // eslint-disable-line @typescript-eslint/no-explicit-any
++readyTestsNumber
setReadyTestsNumber(readyTestsNumber)
if (!result && (_errors && (_errors.errors || (Array.isArray(_errors) && (_errors[0].message || _errors[0].formattedMessage))))) {
// show only file name
renderContract(filename, null, -1, true)
currentErrors.current = _errors.errors
}
if (result) {
const totalTime = parseFloat(result.totalTime).toFixed(2)
const testsSummary = { filename, passed: result.totalPassing, failed: result.totalFailing, timeTaken: totalTime, rendered: false }
testsResultByFilename[filename]['summary'] = testsSummary
showTestsResult()
} else if (_errors) {
if (!testsResultByFilename[filename]) {
testsResultByFilename[filename] = {}
}
testsResultByFilename[filename]['errors'] = _errors
setTestsExecutionStoppedErrorHidden(false)
showTestsResult()
}
if (hasBeenStopped.current && (readyTestsNumber !== runningTestsNumber)) {
// if all tests has been through before stopping no need to print this.
setTestsExecutionStoppedHidden(false)
}
if (_errors || hasBeenStopped.current || readyTestsNumber === runningTestsNumber) {
// All tests are ready or the operation has been canceled or there was a compilation error in one of the test files.
setDisableStopButton(true)
setStopButtonLabel('Stop')
if (selectedTests.current?.length !== 0) {
setDisableRunButton(false)
}
areTestsRunning.current = false
}
}
const runTest = (testFilePath: string, callback: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any
isDebugging.current = false
if (hasBeenStopped.current) {
updateFinalResult(null, null, testFilePath)
return
}
testTab.fileManager.readFile(testFilePath).then((content: string) => {
const runningTests: Record<string, Record<string, string>> = {}
runningTests[testFilePath] = { content }
filesContent[testFilePath] = { content }
const { currentVersion, evmVersion, optimize, runs, isUrl } = testTab.compileTab.getCurrentCompilerConfig()
const currentCompilerUrl = isUrl ? currentVersion : urlFromVersion(currentVersion)
const compilerConfig = {
currentCompilerUrl,
evmVersion,
optimize,
usingWorker: canUseWorker(currentVersion),
runs
}
const deployCb = async (file: string, contractAddress: string) => {
const compilerData = await testTab.call('compilerArtefacts', 'getCompilerAbstract', file)
await testTab.call('compilerArtefacts', 'addResolvedContract', contractAddress, compilerData)
}
testTab.testRunner.runTestSources(
runningTests,
compilerConfig,
(result: Record<string, any>) => testCallback(result), // eslint-disable-line @typescript-eslint/no-explicit-any
(_err: any, result: any, cb: any) => resultsCallback(_err, result, cb), // eslint-disable-line @typescript-eslint/no-explicit-any
deployCb,
(error: any, result: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any
updateFinalResult(error, result, testFilePath)
callback(error)
}, (url: string, cb: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any
return testTab.contentImport.resolveAndSave(url).then((result: any) => cb(null, result)).catch((error: Error) => cb(error.message)) // eslint-disable-line @typescript-eslint/no-explicit-any
}, { testFilePath }
)
}).catch((error: Error) => {
console.log(error)
if (error) return // eslint-disable-line
})
}
const runTests = () => {
areTestsRunning.current = true
hasBeenStopped.current = false
readyTestsNumber = 0
setReadyTestsNumber(readyTestsNumber)
runningTestsNumber = selectedTests.current.length
setRunningTestsNumber(runningTestsNumber)
setDisableStopButton(false)
clearResults()
setProgressBarHidden(false)
const tests: string[] = selectedTests.current
if (!tests || !tests.length) return
else setProgressBarHidden(false)
_paq.push(['trackEvent', 'solidityUnitTesting', 'runTests'])
eachOfSeries(tests, (value: string, key: string, callback: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any
if (hasBeenStopped.current) return
runTest(value, callback)
})
}
const updateRunAction = async (currentFile: any = null) => { // eslint-disable-line @typescript-eslint/no-explicit-any
const isSolidityActive = await testTab.appManager.isActive('solidity')
if (!isSolidityActive || !selectedTests.current.length) {
setDisableRunButton(true)
if (!currentFile || (currentFile && currentFile.split('.').pop().toLowerCase() !== 'sol')) {
setRunButtonTitle('No solidity file selected')
} else {
setRunButtonTitle('The "Solidity Plugin" should be activated')
}
} else setDisableRunButton(false)
}
const stopTests = () => {
hasBeenStopped.current = true
setStopButtonLabel('Stopping')
setDisableStopButton(true)
setDisableRunButton(true)
}
const getCurrentSelectedTests = () => {
const selectedTestsList: TestObject[] = testFiles.filter(testFileObj => testFileObj.checked)
return selectedTestsList.map(testFileObj => testFileObj.fileName)
}
const toggleCheckbox = (eChecked: boolean, index: number) => {
testFiles[index].checked = eChecked
setTestFiles([...testFiles])
selectedTests.current = getCurrentSelectedTests()
if (eChecked) {
setCheckSelectAll(true)
setDisableRunButton(false)
if ((readyTestsNumber === runningTestsNumber || hasBeenStopped.current) && stopButtonLabel.trim() === 'Stop') {
setRunButtonTitle('Run tests')
}
} else if (!selectedTests.current.length) {
setCheckSelectAll(false)
setDisableRunButton(true)
setRunButtonTitle('No test file selected')
} else setCheckSelectAll(false)
}
const checkAll = (event: any) => { // eslint-disable-line @typescript-eslint/no-explicit-any
testFiles.forEach((testFileObj) => testFileObj.checked = event.target.checked)
setTestFiles([...testFiles])
setCheckSelectAll(event.target.checked)
if (event.target.checked) {
selectedTests.current = getCurrentSelectedTests()
setDisableRunButton(false)
} else {
selectedTests.current = []
setDisableRunButton(true)
}
}
const updateTestFileList = () => {
if (allTests.current?.length) {
testFiles = allTests.current.map((testFile: string) => { return { 'fileName': testFile, 'checked': true } })
setCheckSelectAll(true)
}
else
testFiles = []
setTestFiles([...testFiles])
}
return (
<div className="px-2" id="testView">
<Toaster message={toasterMsg} />
<div className="infoBox">
<p className="text-lg"> Test your smart contract in Solidity.</p>
<p> Select directory to load and generate test files.</p>
<label>Test directory:</label>
<div>
<div className="d-flex p-2">
<datalist id="utPathList">{
pathOptions.map(function (path) {
return <option key={path}>{path}</option>
})
}
</datalist>
<input
list="utPathList"
className="inputFolder custom-select"
id="utPath"
data-id="uiPathInput"
name="utPath"
value={inputPathValue}
title="Press 'Enter' to change the path for test files."
style={{ backgroundImage: "var(--primary)" }}
onKeyDown={() => { if (inputPathValue === '/') setInputPathValue('')} }
onChange={handleTestDirInput}
onClick = {() => { if (inputPathValue === '/') setInputPathValue('')} }
/>
<button
className="btn border ml-2"
data-id="testTabGenerateTestFolder"
title="Create a test folder"
disabled={disableCreateButton}
onClick={handleCreateFolder}
>
Create
</button>
</div>
</div>
</div>
<div>
<div className="d-flex p-2">
<button
className="btn border w-50"
data-id="testTabGenerateTestFile"
title="Generate sample test file."
disabled={disableGenerateButton}
onClick={async () => {
await testTabLogic.generateTestFile((err:any) => { if (err) setToasterMsg(err)}) // eslint-disable-line @typescript-eslint/no-explicit-any
await updateForNewCurrent()
}}
>
Generate
</button>
<a className="btn border text-decoration-none pr-0 d-flex w-50 ml-2" title="Check out documentation." target="__blank" href="https://remix-ide.readthedocs.io/en/latest/unittesting.html#test-directory">
<label className="btn p-1 ml-2 m-0">How to use...</label>
</a>
</div>
<div className="d-flex p-2">
<button id="runTestsTabRunAction" title={runButtonTitle} data-id="testTabRunTestsTabRunAction" className="w-50 btn btn-primary" disabled={disableRunButton} onClick={runTests}>
<span className="fas fa-play ml-2"></span>
<label className="labelOnBtn btn btn-primary p-1 ml-2 m-0">Run</label>
</button>
<button id="runTestsTabStopAction" data-id="testTabRunTestsTabStopAction" className="w-50 pl-2 ml-2 btn btn-secondary" disabled={disableStopButton} title="Stop running tests" onClick={stopTests}>
<span className="fas fa-stop ml-2"></span>
<label className="labelOnBtn btn btn-secondary p-1 ml-2 m-0" id="runTestsTabStopActionLabel">{stopButtonLabel}</label>
</button>
</div>
<div className="d-flex align-items-center mx-3 pb-2 mt-2 border-bottom">
<input id="checkAllTests"
type="checkbox"
data-id="testTabCheckAllTests"
onClick={checkAll}
checked={checkSelectAll}
onChange={() => { }} // eslint-disable-line
/>
<label className="text-nowrap pl-2 mb-0" htmlFor="checkAllTests"> Select all </label>
</div>
<div className="testList py-2 mt-0 border-bottom">{testFiles.length ? testFiles.map((testFileObj: TestObject, index) => {
const elemId = `singleTest${testFileObj.fileName}`
return (
<div className="d-flex align-items-center py-1" key={index}>
<input className="singleTest" id={elemId} onChange={(e) => toggleCheckbox(e.target.checked, index)} type="checkbox" checked={testFileObj.checked} />
<label className="singleTestLabel text-nowrap pl-2 mb-0" htmlFor={elemId}>{testFileObj.fileName}</label>
</div>
)
})
: "No test file available"} </div>
<div className="align-items-start flex-column mt-2 mx-3 mb-0">
<span className='text-info h6' hidden={progressBarHidden}>Progress: {readyTestsNumber} finished (of {runningTestsNumber})</span>
<label className="text-warning h6" data-id="testTabTestsExecutionStopped" hidden={testsExecutionStoppedHidden}>The test execution has been stopped</label>
<label className="text-danger h6" data-id="testTabTestsExecutionStoppedError" hidden={testsExecutionStoppedErrorHidden}>The test execution has been stopped because of error(s) in your test file</label>
</div>
<div className="mx-3 mb-2 pb-4 border-primary" id="solidityUnittestsOutput" data-id="testTabSolidityUnitTestsOutput">{testsOutput}</div>
</div>
</div>
)
}