diff --git a/app/static/js/nopaque.js b/app/static/js/nopaque.js
index bde7cb625475c63c923d26cd7f53988013cb3fcf..89afcea031c4d03b7dc472ec72dffb8cbb2b90da 100644
--- a/app/static/js/nopaque.js
+++ b/app/static/js/nopaque.js
@@ -16,6 +16,29 @@ nopaque["foreignJobsSubscribers"] = [];
 
 
 // nopaque functions
+nopaque["forms"] = {};
+nopaque["forms"]["init"] = function() {
+  for (let form of document.querySelectorAll(".nopaque-form")) {
+    form.addEventListener("submit", function(event) {
+      event.preventDefault();
+      if (form.dataset.hasOwnProperty('loadingModal')) {
+        let loadingModalElement = document.getElementById(form.dataset.loadingModal);
+        M.Modal.getInstance(loadingModalElement).open();
+      }
+      let data = {};
+      for (let input of form.querySelectorAll("input")) {
+        if (input.type === "file") {
+          file = input.files[0];
+          data[`${input.name}-wrapper`] = {"bytes": file, "name": file.name};
+        } else {
+          data[input.name] = input.value;
+        }
+      }
+      nopaque.socket.emit(`submit-${form.id}`, data);
+    });
+  }
+}
+
 nopaque["navigation"] = {};
 nopaque["navigation"]["init"] = function() {
   for (let entry of document.querySelectorAll("#slide-out a:not(.subheader)")) {
@@ -112,6 +135,7 @@ document.addEventListener("DOMContentLoaded", function() {
                   {"alignment": "right", "constrainWidth": false, "coverTrigger": false});
   M.Dropdown.init(document.getElementById("nav-account"),
                   {"alignment": "right", "constrainWidth": false, "coverTrigger": false});
+  nopaque.forms.init();
   nopaque.navigation.init();
   nopaque.socket.emit("subscribe_user_ressources");
 });
diff --git a/app/templates/test/index.html.j2 b/app/templates/test/index.html.j2
index f0ec41f1807c2ff9959415d2b6e31f47d739b316..3fb77913e30fa6ec3dc1371e61162845e3c43790 100644
--- a/app/templates/test/index.html.j2
+++ b/app/templates/test/index.html.j2
@@ -7,7 +7,7 @@
 
 <div class="col s12">
   <div class="card">
-    <form id="test-form">
+    <form class="nopaque-form" data-loading-modal="test-progress-modal" id="test-form">
       {{ test_form.hidden_tag() }}
       <div class="card-content">
         <div class="row">
@@ -45,32 +45,27 @@
   </div>
 </div>
 
+<div class="modal" id="test-progress-modal">
+  <div class="modal-content">
+    <h4>Waiting for data transfer</h4>
+    <div class="progress">
+      <div class="indeterminate"></div>
+    </div>
+  </div>
+</div>
+
 <script>
 var testFormElement = document.forms.namedItem("test-form");
 
-testFormElement.addEventListener("submit", function(event) {
-  event.preventDefault();
-  let data = {};
-  for (let input of event.target.querySelectorAll("input")) {
-    if (input.type === "file") {
-      file = input.files[0];
-      data[input.name] = {"bytes": file, "name": file.name};
-    } else {
-      data[input.name] = input.value;
-    }
-  }
-  nopaque.socket.emit("submit-test-form", data);
-});
-
 nopaque.socket.on("submit-test-form", function(response) {
-  console.log(response);
-  if (response.status === "success") {
-     testFormElement.reset();
-     nopaque.toast("Success!");
-     for (let helperText of testFormElement.querySelectorAll(".helper-text")) {
-       helperText.remove();
-     }
-  } else if (response.status === "error") {
+  let loadingModalElement = document.getElementById(testFormElement.dataset.loadingModal);
+  if (response.status === 201) {
+    testFormElement.reset();
+    for (let helperText of testFormElement.querySelectorAll(".helper-text")) {
+      helperText.remove();
+    }
+    nopaque.toast("Success!");
+  } else if (response.status === 400) {
     let errorElement;
     for (let [field, error] of Object.entries(response.msg)) {
       errorElement = document.createElement("span");
@@ -79,6 +74,7 @@ nopaque.socket.on("submit-test-form", function(response) {
       testFormElement.querySelector(`input[name="${field}"]`).closest(".input-field").appendChild(errorElement);
     }
   }
+  M.Modal.getInstance(loadingModalElement).close();
 });
 </script>
 {% endblock %}
diff --git a/app/test/events.py b/app/test/events.py
index 3400cd4f21218b0224690b3e336b0392c3939479..c57b57b27f500cf79bbceb55a6fedb26ef7d24cd 100644
--- a/app/test/events.py
+++ b/app/test/events.py
@@ -9,16 +9,15 @@ import io
 @socketio.on('submit-test-form')
 @login_required
 def recv_test_form(data):
-    filename = secure_filename(data['file']['name'])
-    stream = io.BytesIO(data['file']['bytes'])
-    file = FileStorage(stream=stream, filename=filename)
+    logger.warning("data_received")
+    filename = secure_filename(data['file-wrapper']['name'])
+    stream = io.BytesIO(data['file-wrapper']['bytes'])
+    file = FileStorage(filename=filename, stream=stream)
     data['file'] = file
     test_form = TestForm(data=data)
     if test_form.validate():
-        logger.warning('test_form is ok!')
-        socketio.emit('submit-test-form', {'status': 'success',
-                                           'msg': 'test_form is ok!'})
+        socketio.emit('submit-test-form', {'msg': {},
+                                           'status': 201})
     else:
-        logger.warning('test_form is not ok!')
-        socketio.emit('submit-test-form', {'status': 'error',
-                                           'msg': test_form.errors})
+        socketio.emit('submit-test-form', {'msg': test_form.errors,
+                                           'status': 400})