-
Notifications
You must be signed in to change notification settings - Fork 26
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
[FEATURE] Add fileExport capability #352
Changes from all commits
d650d71
dafe9ff
adf2211
2a00155
4979c3c
c909a51
67be8b5
176e950
0fbc83b
109448f
603a4fa
a1b96f1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,3 +56,4 @@ deploy_key | |
|
||
# Custom directories | ||
dist/ | ||
test/integration/*/karma-ui5-reports* |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,18 @@ | ||
(function(window) { | ||
const config = window.__karma__.config; | ||
const karma = window.__karma__; | ||
const config = karma.config; | ||
const ui5config = (config && config.ui5) || {}; | ||
const bootstrapConfig = ui5config.config || {}; | ||
|
||
window["sap-ui-config"] = bootstrapConfig; | ||
|
||
if (ui5config.fileExport) { | ||
const originalKarmaComplete = karma.complete.bind(karma); | ||
karma.complete = function(result) { | ||
if (window._$files) { | ||
result.exportFiles = window._$files; | ||
} | ||
return originalKarmaComplete(result); | ||
}; | ||
} | ||
})(window); |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -267,6 +267,35 @@ module.exports = function(config) { | |||||
}); | ||||||
};`, | ||||||
|
||||||
invalidFileExportReporterUsage: () => `error 21: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did not take over this suggestion to be consistent to the existing error messages There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fine, but could we have a central resources file (like i18n) where all error messages are stored and can be easily modified? Then we could easily fix such things without having to sacrifice consistency. |
||||||
The reporter "ui5--fileExport" should not be manually enabled as a karma reporter. | ||||||
You can enable the FileExportReporter in the karma-ui5 settings. | ||||||
|
||||||
module.exports = function(config) { | ||||||
config.set({ | ||||||
|
||||||
ui5: { | ||||||
fileExport: true | ||||||
} | ||||||
|
||||||
}); | ||||||
}; | ||||||
|
||||||
Optionally, an output directory can be set to specify the export path. | ||||||
|
||||||
module.exports = function(config) { | ||||||
config.set({ | ||||||
|
||||||
ui5: { | ||||||
fileExport: { | ||||||
outputDir: "directory/to/export/files" | ||||||
} | ||||||
} | ||||||
|
||||||
}); | ||||||
}; | ||||||
`, | ||||||
|
||||||
failure: () => "ui5.framework failed. See error message above" | ||||||
|
||||||
} | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
const fs = require("fs").promises; | ||
const path = require("path"); | ||
const mkdirp = require("mkdirp"); | ||
|
||
const defaultPath = "./karma-ui5-reports"; | ||
|
||
function escapeFileName(fileName) { | ||
fileName = fileName.replace(/[:*?"<>|]/g, ""); | ||
fileName = fileName.replace(/[\\/]/g, "."); | ||
return fileName; | ||
} | ||
|
||
async function getUniqueFileName(exportDir, fileName) { | ||
async function fileExists(_fileName) { | ||
try { | ||
await fs.access(path.join(exportDir, _fileName)); | ||
return true; | ||
} catch (err) { | ||
if (err.code === "ENOENT") { | ||
return false; | ||
} | ||
throw err; | ||
} | ||
} | ||
|
||
const fileExtension = path.extname(fileName); | ||
const fileNameWithoutExtension = path.basename(fileName, fileExtension); | ||
for (let index = 1; await fileExists(fileName); index++) { | ||
fileName = `${fileNameWithoutExtension}_${index}${fileExtension}`; | ||
} | ||
|
||
return fileName; | ||
} | ||
|
||
const FileExportReporter = function(baseReporterDecorator, config, logger) { | ||
let reporterInProcess = true; | ||
let exitCode = 0; | ||
let reporterCompleted = function() {}; | ||
const log = logger.create("reporter.ui5--fileExport"); | ||
const reporterConfig = config.ui5.fileExport; | ||
const multiBrowsers = config.browsers && config.browsers.length > 1; | ||
let outputDir = reporterConfig.outputDir; | ||
|
||
if (!outputDir || typeof outputDir !== "string") { | ||
outputDir = defaultPath; | ||
} | ||
|
||
outputDir = path.join(config.basePath, outputDir); | ||
|
||
log.debug("outputDir is: " + outputDir); | ||
|
||
baseReporterDecorator(this); | ||
|
||
async function writeSingleFile(fileDir, fileName, content) { | ||
await mkdirp(fileDir); | ||
const uniqueFileName = await getUniqueFileName(fileDir, fileName); | ||
const pathToWrite = path.join(fileDir, uniqueFileName); | ||
if (!pathToWrite.startsWith(fileDir)) { | ||
log.warn(`Invalid export file path: ${pathToWrite}\n\tMake sure the file path is in directory: ${fileDir}`); | ||
return; | ||
} | ||
log.debug(`Writing file: ${pathToWrite}`); | ||
try { | ||
await fs.writeFile(pathToWrite, content); | ||
log.info(`Saved file '${pathToWrite}'`); | ||
} catch (err) { | ||
log.warn("Failed to write file " + pathToWrite + "\n\t" + err.message); | ||
} | ||
} | ||
|
||
this.onBrowserComplete = async function(browser, result) { | ||
try { | ||
log.debug("onBrowserComplete triggered."); | ||
if (!result || result.error || result.disconnected) { | ||
log.debug("skipped due to incomplete test run."); | ||
return; | ||
} | ||
|
||
if (!result.exportFiles) { | ||
log.debug("No export files provided"); | ||
return; | ||
} | ||
|
||
if (!Array.isArray(result.exportFiles)) { | ||
log.warn("Export files must be given as an array"); | ||
return; | ||
} | ||
|
||
let exportPath = outputDir; | ||
if (multiBrowsers) { | ||
exportPath = path.join(exportPath, escapeFileName(browser.name)); | ||
} | ||
for (const file of result.exportFiles) { | ||
if (typeof file.name !== "string" || typeof file.content !== "string") { | ||
log.warn("Invalid file object. \"name\" and \"content\" must be strings"); | ||
continue; | ||
} | ||
|
||
await writeSingleFile(exportPath, escapeFileName(file.name), file.content); | ||
} | ||
} catch (err) { | ||
log.error("An unexpected error occured while exporting files\n\t" + err.message); | ||
exitCode = 1; | ||
} | ||
reporterInProcess = false; | ||
reporterCompleted(); | ||
}; | ||
|
||
this.onExit = function(done) { | ||
if (reporterInProcess) { | ||
reporterCompleted = () => done(exitCode); | ||
} else { | ||
done(exitCode); | ||
} | ||
}; | ||
}; | ||
|
||
FileExportReporter.$inject = ["baseReporterDecorator", "config", "logger"]; | ||
|
||
module.exports = FileExportReporter; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this how it was done in Selenium? I.e. with the strings "TEST" and "FILE"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this format is taken from the java implementation