Skip to content

Commit

Permalink
fix: truncate screenshot filenames using byteLength
Browse files Browse the repository at this point in the history
  • Loading branch information
flotwig committed Aug 4, 2020
1 parent 996fe97 commit 6cdec97
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 13 deletions.
27 changes: 15 additions & 12 deletions packages/server/lib/screenshots.js
Expand Up @@ -289,12 +289,25 @@ const getDimensions = function (details) {
}

const ensureUniquePath = function (withoutExt, extension, num = 0) {
const fullPath = num ? `${withoutExt} (${num}).${extension}` : `${withoutExt}.${extension}`
let pathWithoutExt = num ? `${withoutExt} (${num})` : `${withoutExt}`
const withoutExtBuf = Buffer.from(pathWithoutExt)

// many filesystems limit filename length to 255 bytes/characters, so truncate the filename to
// the smallest common denominator of safe filenames, which is 255 bytes
// @see https://github.com/cypress-io/cypress/issues/2403
// @see https://en.wikipedia.org/wiki/Comparison_of_file_systems#Limits
const maxSafeBytes = 254 - extension.length

if (withoutExtBuf.byteLength > maxSafeBytes) {
pathWithoutExt = withoutExtBuf.slice(0, maxSafeBytes).toString()
}

const fullPath = [pathWithoutExt, extension].join('.')

return fs.pathExists(fullPath)
.then((found) => {
if (found) {
return ensureUniquePath(withoutExt, extension, (num += 1))
return ensureUniquePath(withoutExt, extension, num + 1)
}

return fullPath
Expand Down Expand Up @@ -323,18 +336,8 @@ const getPath = function (data, ext, screenshotsFolder) {
.value()
}

// truncate file names to be less than 220 characters
// to accomodate filename size limits
const maxFileNameLength = 220
const index = names.length - 1

if (names[index].length > maxFileNameLength) {
names[index] = _.truncate(names[index], {
length: maxFileNameLength,
omission: '',
})
}

// append (failed) to the last name
if (data.testFailure) {
names[index] = `${names[index]} (failed)`
Expand Down
20 changes: 19 additions & 1 deletion packages/server/test/unit/screenshots_spec.js
Expand Up @@ -618,6 +618,24 @@ describe('lib/screenshots', () => {
})
})

// @see https://github.com/cypress-io/cypress/issues/2403
it('truncates long paths with unicode in them', async () => {
const fullPath = await screenshots.getPath({
titles: [
'WMED: [STORY] Тестовые сценарии для CI',
'Сценарии:',
'Сценарий 2: Создание обращения, создание медзаписи, привязка обращения к медзаписи',
'- Сценарий 2',
],
testFailure: true,
specName: 'WMED_UAT_Scenarios_For_CI_spec.js',
}, 'png', '/jenkins-slave/workspace/test-wmed/qa/cypress/wmed_ci/cypress/screenshots/')

const basename = path.basename(fullPath)

expect(Buffer.from(basename).byteLength).to.be.lessThan(255)
})

_.each([Infinity, 0 / 0, [], {}, 1, false], (value) => {
it(`doesn't err and stringifies non-string test title: ${value}`, () => {
return screenshots.getPath({
Expand All @@ -632,7 +650,7 @@ describe('lib/screenshots', () => {
})
})

return _.each([null, undefined], (value) => {
_.each([null, undefined], (value) => {
it(`doesn't err and removes null/undefined test title: ${value}`, () => {
return screenshots.getPath({
specName: 'examples$/user/list.js',
Expand Down

0 comments on commit 6cdec97

Please sign in to comment.