diff --git a/package.json b/package.json
index 36ec437e3eab1f0cec653116792a87b037d14d4d..ec1f0a82f15a6afb559ae9d4dfe11d1c352906a7 100644
--- a/package.json
+++ b/package.json
@@ -6,6 +6,7 @@
   "type": "module",
   "scripts": {
     "start": "node src/server/app.js",
+    "test": "node --test",
     "dev": "concurrently -n Client,Server -c '#325D79,#45ADA8' 'npm:dev:client' 'npm:dev:server'",
     "dev:client": "vite",
     "dev:server": "nodemon --use-strict src/server/app.js | pino-pretty -t 'yyyy-mm-dd HH:MM:ss'",
diff --git a/src/scripts/streams/ParseFastaStream.test.js b/src/scripts/streams/ParseFastaStream.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..e2b831bbcbaf6c9550e29101804ef1b0264bfe10
--- /dev/null
+++ b/src/scripts/streams/ParseFastaStream.test.js
@@ -0,0 +1,61 @@
+// ABSD
+// Copyright (C) 2025 Institut Pasteur
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import { describe, it } from "node:test"
+import { ParseFastaStream } from "./ParseFastaStream.js"
+import { PassThrough } from "node:stream"
+import assert from "node:assert"
+
+describe('ParseFastaStream', () => {
+  it('should be in object mode by default', () => {
+    const parser = new ParseFastaStream()
+    assert(
+      parser.readableObjectMode === true,
+      'The objectMode parameter should be true by default'
+    )
+  })
+
+  it('should transform a raw fasta entry into an object', (test, done) => {
+    const inputData = 'this is the header\nTHISISTHESEQUENCE'
+    const expected = {
+      header: 'this is the header',
+      sequence: 'THISISTHESEQUENCE'
+    }
+
+    // Setup a test pipeline with mock-up streams
+    const inputStream = new PassThrough({ objectMode: true })
+    const outputStream = new PassThrough({ objectMode: true })
+    const parser = new ParseFastaStream()
+
+    inputStream.pipe(parser).pipe(outputStream)
+
+    // Handle processed data on the output stream
+    let outputData = ''
+    outputStream.on('data', (chunk) => {
+      outputData = chunk
+    })
+
+    // Assert at the end of the stream
+    outputStream.on('end', () => {
+      assert.deepStrictEqual(outputData, expected)
+      done()
+    })
+
+    // Start the process
+    inputStream.write(inputData)
+    inputStream.end()
+  })
+})
diff --git a/src/scripts/streams/SanitizeFastaStream.test.js b/src/scripts/streams/SanitizeFastaStream.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..c3a647b9420bfe0bbe62ab68c33f402680a7cb0a
--- /dev/null
+++ b/src/scripts/streams/SanitizeFastaStream.test.js
@@ -0,0 +1,64 @@
+// ABSD
+// Copyright (C) 2025 Institut Pasteur
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import { describe, it } from "node:test"
+import { SanitizeFastaStream } from "./SanitizeFastaStream.js"
+import { PassThrough } from "node:stream"
+import assert from "node:assert"
+
+describe('SanitizeFastaStream', () => {
+  it('should be in object mode by default', () => {
+    const parser = new SanitizeFastaStream()
+    assert(
+      parser.readableObjectMode === true,
+      'The objectMode parameter should be true by default'
+    )
+  })
+
+  it('should remove extra spaces and tabs from a fasta object', (test, done) => {
+    const inputData = {
+      header: 'this  is \t  the header\t',
+      sequence: ' THISISTHESEQUENCE '
+    }
+    const expected = {
+      header: 'this is the header',
+      sequence: 'THISISTHESEQUENCE'
+    }
+
+    // Setup a test pipeline with mock-up streams
+    const inputStream = new PassThrough({ objectMode: true })
+    const outputStream = new PassThrough({ objectMode: true })
+    const parser = new SanitizeFastaStream()
+
+    inputStream.pipe(parser).pipe(outputStream)
+
+    // Handle processed data on the output stream
+    let outputData = ''
+    outputStream.on('data', (chunk) => {
+      outputData = chunk
+    })
+
+    // Assert at the end of the stream
+    outputStream.on('end', () => {
+      assert.deepStrictEqual(outputData, expected)
+      done()
+    })
+
+    // Start the process
+    inputStream.write(inputData)
+    inputStream.end()
+  })
+})
diff --git a/src/scripts/streams/SplitFastaStream.test.js b/src/scripts/streams/SplitFastaStream.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..f5ec9ebb54e6b1234b3f3c6a9ed9921a06b81d0d
--- /dev/null
+++ b/src/scripts/streams/SplitFastaStream.test.js
@@ -0,0 +1,83 @@
+// ABSD
+// Copyright (C) 2025 Institut Pasteur
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import { describe, it } from "node:test"
+import { SplitFastaStream } from "./SplitFastaStream.js"
+import { PassThrough } from "node:stream"
+import assert from "node:assert"
+
+describe('SplitFastaStream', () => {
+  it('should be in object mode by default', () => {
+    const splitFasta = new SplitFastaStream()
+    assert(
+      splitFasta.readableObjectMode === true,
+      'The objectMode parameter should be true by default'
+    )
+  })
+
+  it('should have a buffer property, intialized as an empty string', () => {
+    const splitFasta = new SplitFastaStream()
+    assert(
+      splitFasta.buffer === '',
+      'The buffer property needs to be set'
+    )
+  })
+
+  it('should have a firstLine property, intialized to true', () => {
+    const splitFasta = new SplitFastaStream()
+    assert(
+      splitFasta.firstLine === true,
+      'The firstLine property needs to be set'
+    )
+  })
+
+  it('should decode and split a buffer into a series of raw fasta, sent one by one', (test, done) => {
+    const inputData = new Buffer.from(
+      '>First header\nFIRSTSEQUENCE\n' +
+      '>Second header\nSECONDSEQUENCE\n' +
+      '>Third header\nTHIRDSEQUENCE\n'
+    )
+
+    const expected = [
+      'First header\nFIRSTSEQUENCE\n',
+      'Second header\nSECONDSEQUENCE\n',
+      'Third header\nTHIRDSEQUENCE\n'
+    ]
+
+    // Setup a test pipeline with mock-up streams
+    const inputStream = new PassThrough()
+    const outputStream = new PassThrough({ objectMode: true })
+    const splitFasta = new SplitFastaStream()
+
+    inputStream.pipe(splitFasta).pipe(outputStream)
+
+    // Handle processed data on the output stream
+    let outputData = []
+    outputStream.on('data', (chunk) => {
+      outputData.push(chunk)
+    })
+
+    // Assert at the end of the stream
+    outputStream.on('end', () => {
+      assert.deepStrictEqual(outputData, expected)
+      done()
+    })
+
+    // Start the process
+    inputStream.write(inputData)
+    inputStream.end()
+  })
+})