diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b7f54c5f1..28d3c1b32 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -19,9 +19,9 @@ jobs: matrix: node-version: [14, 16] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - name: Install Dependencies diff --git a/packages/node_modules/@node-red/nodes/core/storage/10-file.js b/packages/node_modules/@node-red/nodes/core/storage/10-file.js index d0db89d01..d3b8a0765 100644 --- a/packages/node_modules/@node-red/nodes/core/storage/10-file.js +++ b/packages/node_modules/@node-red/nodes/core/storage/10-file.js @@ -117,7 +117,9 @@ module.exports = function(RED) { } if (typeof data === "boolean") { data = data.toString(); } if (typeof data === "number") { data = data.toString(); } - if ((node.appendNewline) && (!Buffer.isBuffer(data))) { data += os.EOL; } + var aflg = true; + if (msg.hasOwnProperty("parts") && msg.parts.type === "string" && (msg.parts.count === msg.parts.index + 1)) { aflg = false; } + if ((node.appendNewline) && (!Buffer.isBuffer(data)) && aflg) { data += os.EOL; } var buf; if (node.encoding === "setbymsg") { buf = encode(data, msg.encoding || "none"); @@ -314,7 +316,6 @@ module.exports = function(RED) { }); filename = filename || ""; var fullFilename = filename; - var filePath = ""; if (filename && RED.settings.fileWorkingDirectory && !path.isAbsolute(filename)) { fullFilename = path.resolve(path.join(RED.settings.fileWorkingDirectory,filename)); } diff --git a/test/nodes/core/storage/10-file_spec.js b/test/nodes/core/storage/10-file_spec.js index 9d5aa033f..19026d457 100644 --- a/test/nodes/core/storage/10-file_spec.js +++ b/test/nodes/core/storage/10-file_spec.js @@ -194,6 +194,55 @@ describe('file Nodes', function() { }); }); + it('should append to a file and add newline, except last line of multipart input', function(done) { + var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":true, "overwriteFile":false, wires: [["helperNode1"]]}, + {id:"helperNode1", type:"helper"}]; + try { + fs.unlinkSync(fileToTest); + } catch(err) { + } + helper.load(fileNode, flow, function() { + var n1 = helper.getNode("fileNode1"); + var n2 = helper.getNode("helperNode1"); + var count = 0; + //var data = ["Line1", "Line2"]; + + n2.on("input", function (msg) { + try { + msg.should.have.property("payload"); + //data.should.containDeep([msg.payload]); + if (count === 3) { + var f = fs.readFileSync(fileToTest).toString(); + if (os.type() !== "Windows_NT") { + f.should.have.length(23); + f.should.equal("Line1\nLine2\nLine3\nLine4"); + } + else { + f.should.have.length(23); + f.should.equal("Line1\r\nLine2\r\nLine3\r\nLine4"); + } + done(); + } + count++; + } + catch (e) { + done(e); + } + }); + + n1.receive({payload:"Line1",parts:{index:0,type:"string"}}); // string + setTimeout(function() { + n1.receive({payload:"Line2",parts:{index:1,type:"string"}}); // string + },30); + setTimeout(function() { + n1.receive({payload:"Line3",parts:{index:2,type:"string"}}); // string + },60); + setTimeout(function() { + n1.receive({payload:"Line4",parts:{index:3,type:"string",count:4}}); // string + },90); + }); + }); + it('should append to a file after it has been deleted ', function(done) { var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":false, wires: [["helperNode1"]]}, {id:"helperNode1", type:"helper"}];