-
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 9 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,94 @@ | ||||||
const fs = require("fs").promises; | ||||||
const path = require("path"); | ||||||
const mkdirp = require("mkdirp"); | ||||||
|
||||||
const defaultPath = "./karma-ui5-reports"; | ||||||
|
||||||
async function getUniqueFileName(fileName) { | ||||||
async function fileExists(path) { | ||||||
try { | ||||||
await fs.access(path); | ||||||
return true; | ||||||
} catch (err) { | ||||||
if (err.code === "ENOENT") { | ||||||
return false; | ||||||
} | ||||||
throw err; | ||||||
} | ||||||
} | ||||||
|
||||||
const fileExtension = path.extname(fileName); | ||||||
const fileNameWithoutExtension = fileName.slice(0, fileName.lastIndexOf(fileExtension)); | ||||||
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. Alternative:
Suggested change
See https://nodejs.org/api/path.html#pathbasenamepath-ext But I wouldn't mind the current solution as well 🤷 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. Good idea but not an alternative because path.basename would trim the starting directory path |
||||||
for (let index = 1; await fileExists(fileName); index++) { | ||||||
fileName = `${fileNameWithoutExtension}_${index}${fileExtension}`; | ||||||
} | ||||||
|
||||||
return fileName; | ||||||
} | ||||||
|
||||||
const FileExportReporter = function(baseReporterDecorator, config, logger, helper) { | ||||||
let reporterInProcess = true; | ||||||
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 = helper.normalizeWinPath(path.resolve(config.basePath, outputDir)); | ||||||
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. Not sure, but I think normalization should happen before any platform specific
We need to normalize the configuration since it can be POSIX or Windows or both. Later when we Maybe:
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. As discussed, a simple path.join should be sufficient since we already expect in browser.js the basePath to be in posix format. |
||||||
|
||||||
log.debug("outputDir is: " + outputDir); | ||||||
|
||||||
baseReporterDecorator(this); | ||||||
|
||||||
async function writeSingleFile(outputFile, content) { | ||||||
log.info(`Writing file: ${outputFile}`); | ||||||
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. This doesn't output the final path, as getUniqueFileName is called after. 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. Done |
||||||
await mkdirp(path.dirname(outputFile)); | ||||||
outputFile = await getUniqueFileName(outputFile); | ||||||
try { | ||||||
await fs.writeFile(outputFile, content); | ||||||
log.info(`Saved file '${outputFile}'`); | ||||||
} catch (err) { | ||||||
log.warn("Failed to write file\n\t" + err.message); | ||||||
} | ||||||
} | ||||||
|
||||||
this.onBrowserComplete = async function(browser, result) { | ||||||
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; | ||||||
} | ||||||
|
||||||
for (const file of result.exportFiles) { | ||||||
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. Do we want to add some error handling here? 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. You might check out the Java implementation. Just search for 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. Done |
||||||
const pathSegments = [outputDir, file.name]; | ||||||
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
"sanitize" file name to ensure it is really only a file name and not a path. 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. Done |
||||||
if (multiBrowsers) { | ||||||
pathSegments.splice(1, 0, browser.name); | ||||||
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
Same for browser name I guess 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. Done |
||||||
} | ||||||
|
||||||
await writeSingleFile(path.join.apply(null, pathSegments), file.content); | ||||||
} | ||||||
reporterInProcess = false; | ||||||
reporterCompleted(); | ||||||
}; | ||||||
|
||||||
this.onExit = function(done) { | ||||||
if (reporterInProcess) { | ||||||
reporterCompleted = done; | ||||||
} else { | ||||||
done(); | ||||||
} | ||||||
}; | ||||||
}; | ||||||
|
||||||
FileExportReporter.$inject = ["baseReporterDecorator", "config", "logger", "helper"]; | ||||||
|
||||||
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