Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions app/tests/test-file-ops-unification.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
const { describe, it } = require('node:test');
const assert = require('node:assert');
const fs = require('node:fs');
const path = require('node:path');

const indexHtml = path.join(__dirname, '..', 'index.html');

describe('file-ops public entry points', () => {
it('built index.html declares doStuff as a top-level function', () => {
const html = fs.readFileSync(indexHtml, 'utf8');
assert.ok(
/function\s+doStuff\s*\(/.test(html),
'must contain function doStuff(...)'
);
});

it('built index.html declares undoStuff as a top-level function', () => {
const html = fs.readFileSync(indexHtml, 'utf8');
assert.ok(
/function\s+undoStuff\s*\(/.test(html),
'must contain function undoStuff(...)'
);
});
});

describe('FILE_OPS config table (source-level)', () => {
const fileOpsSrc = fs.readFileSync(
path.join(__dirname, '..', '..', 'src', 'js', 'ui', 'file-ops.js'),
'utf8'
);

it('defines FILE_OPS with enc and dec entries', () => {
assert.ok(
/const\s+FILE_OPS\s*=/.test(fileOpsSrc),
'must declare FILE_OPS'
);
assert.ok(fileOpsSrc.includes("enc:"), 'FILE_OPS must have enc entry');
assert.ok(fileOpsSrc.includes("dec:"), 'FILE_OPS must have dec entry');
});

it('enc entry uses encNewMsg and .filekey suffix', () => {
assert.ok(fileOpsSrc.includes('work: encNewMsg'));
assert.ok(fileOpsSrc.includes("'.filekey'") || fileOpsSrc.includes('".filekey"'));
});

it('dec entry uses decMsg and .filekey replacement', () => {
assert.ok(fileOpsSrc.includes('work: decMsg'));
assert.ok(/replace\s*\(\s*['"]\.filekey['"]/.test(fileOpsSrc));
});

it('defines processFileBatch driver', () => {
assert.ok(
/function\s+processFileBatch\s*\(/.test(fileOpsSrc),
'must declare processFileBatch'
);
});
});

describe('FILE_OPS filename transforms (extracted behavior)', () => {
const encSuffix = (name) => name + '.filekey';
const decSuffix = (name) => name.replace('.filekey', '');

it('enc then dec restores original filename', () => {
assert.strictEqual(decSuffix(encSuffix('foo.txt')), 'foo.txt');
assert.strictEqual(decSuffix(encSuffix('report.pdf')), 'report.pdf');
assert.strictEqual(decSuffix(encSuffix('no-extension')), 'no-extension');
});

it('dec is a no-op on names without .filekey', () => {
assert.strictEqual(decSuffix('plain.txt'), 'plain.txt');
});
});
114 changes: 49 additions & 65 deletions src/js/ui/file-ops.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,40 +248,58 @@ function handleSharedFile(file_obj) {
)(file_array[fc++]);
}
}
function undoStuff() {
var file_array = current_active_file_array;
if (file_array.length > 0) {
let fc = 0;
let encrypt_status = false;
let status_obj;
status_obj = setStatusMsg(encrypt_status);
status_obj.animator = new set3dotStatusAnimation(status_obj);
(function nextFile(file) {
getFlatFile(file, function(file_contents, filename) {
decMsg(file_contents, function(ret) {
if (ret === null) {
status_obj.animator.clearStatus();
var params = getErrorParams();
var html_string = "<span>Failed to unlock file with this key. Please try again.</span>";
htmlWriter(params, html_string, main_inner);
} else {
var new_filename = filename.replace(".filekey", "");
newDownloadObj(new_filename, ret.decrypted_buff, {
encrypt_status
}, function(ret) {
scrollForFirstFile(fc);
if (fc < file_array.length)
nextFile(file_array[fc++]);
else
status_obj.animator.triggerStatusFinish(status_obj);
});
}
const FILE_OPS = {
enc: {
work: encNewMsg,
transform: function(ret) { return combineArrayBuffers(ret.salt, ret.encrypted_buff); },
filename: function(name) { return name + '.filekey'; },
errorMsg: 'Failed to encrypt file. Please try again.',
encrypt_status: true,
},
dec: {
work: decMsg,
transform: function(ret) { return ret.decrypted_buff; },
filename: function(name) { return name.replace('.filekey', ''); },
errorMsg: 'Failed to unlock file with this key. Please try again.',
encrypt_status: false,
},
};

function processFileBatch(direction) {
const config = FILE_OPS[direction];
const file_array = current_active_file_array;
if (file_array.length === 0) return;
let fc = 0;
let status_obj = setStatusMsg(config.encrypt_status);
status_obj.animator = new set3dotStatusAnimation(status_obj);
(function nextFile(file) {
getFlatFile(file, function(file_contents, filename) {
config.work(file_contents, function(ret) {
if (ret === null) {
status_obj.animator.clearStatus();
var html_string = '<span>' + config.errorMsg + '</span>';
htmlWriter(getErrorParams(), html_string, main_inner);
return;
}
var out_buff = config.transform(ret);
var out_name = config.filename(filename);
newDownloadObj(out_name, out_buff, {
encrypt_status: config.encrypt_status
}, function(ret) {
scrollForFirstFile(fc);
if (fc < file_array.length)
nextFile(file_array[fc++]);
else
status_obj.animator.triggerStatusFinish(status_obj);
});
});
}
)(file_array[fc++]);
}
});
})(file_array[fc++]);
}

function undoStuff() { processFileBatch('dec'); }

function doStuff() { processFileBatch('enc'); }
function getWarningParams() {
return {
char_speed: 2,
Expand Down Expand Up @@ -339,37 +357,3 @@ function set3dotStatusAnimation(status_obj) {
}
}
}
function doStuff() {
var file_array = current_active_file_array;
if (file_array.length > 0) {
let fc = 0;
let encrypt_status = true;
let status_obj;
status_obj = setStatusMsg(encrypt_status);
status_obj.animator = new set3dotStatusAnimation(status_obj);
(function nextFile(file) {
getFlatFile(file, function(file_contents, filename) {
encNewMsg(file_contents, function(ret) {
if (ret === null) {
status_obj.animator.clearStatus();
var html_string = "<span>Failed to encrypt file. Please try again.</span>";
htmlWriter(getErrorParams(), html_string, main_inner);
return;
}
var combined_buff = combineArrayBuffers(ret.salt, ret.encrypted_buff);
var new_filename = filename + ".filekey";
newDownloadObj(new_filename, combined_buff, {
encrypt_status
}, function(ret) {
scrollForFirstFile(fc);
if (fc < file_array.length)
nextFile(file_array[fc++]);
else
status_obj.animator.triggerStatusFinish(status_obj);
});
});
});
}
)(file_array[fc++]);
}
}
Loading