diff --git a/src/core/js/ext_qrcode.js b/src/core/js/ext_qrcode.js
index 7dcff42a51eea100489434a6eb0549efdfbe7550..56f49d44e94126942653eefee6a6e105769c20d3 100644
--- a/src/core/js/ext_qrcode.js
+++ b/src/core/js/ext_qrcode.js
@@ -27,50 +27,52 @@
  */
 var ext_qrcode = function ($, connection, getEntityVersion, getEntityID, QRCode, logger) {
 
-  const _buttons_list_class = "caosdb-v-entity-header-buttons-list";
-  const _qrcode_button_class = "caosdb-f-entity-qrcode-button";
-  const _qrcode_canvas_container = "caosdb-f-entity-qrcode";
-  const _qrcode_link_container = "caosdb-f-entity-qrcode-link";
-  const _qrcode_icon = `<i class="bi bi-upc"></i>`;
+    const _buttons_list_class = "caosdb-v-entity-header-buttons-list";
+    const _qrcode_button_class = "caosdb-f-entity-qrcode-button";
+    const _qrcode_canvas_container = "caosdb-f-entity-qrcode";
+    const _qrcode_link_container = "caosdb-f-entity-qrcode-link";
+    const _qrcode_icon = `<i class="bi bi-upc"></i>`;
 
-  /**
-   * Create a new QR Code and a caption with a link, either linking to the
-   * entity head or to the exact version of the entity, based on the selected
-   * radio buttons and insert it into the modal.
-   *
-   * @param {HTMLElement} modal
-   * @param {string} entity_id
-   * @param {string} entity_version
-   */
-  var update_qrcode = function(modal, entity_id, entity_version) {
-    modal = $(modal);
-    const uri = modal.find("input[name=entity-qrcode-versioned]:checked").val();
-    var display_version = "";
-    if(uri.indexOf("@") > -1) {
-      display_version = `@${entity_version.substring(0,8)}`;
+    /**
+     * Create a new QR Code and a caption with a link, either linking to the
+     * entity head or to the exact version of the entity, based on the selected
+     * radio buttons and insert it into the modal.
+     *
+     * @param {HTMLElement} modal
+     * @param {string} entity_id
+     * @param {string} entity_version
+     */
+    var update_qrcode = function (modal, entity_id, entity_version) {
+        modal = $(modal);
+        const uri = modal.find("input[name=entity-qrcode-versioned]:checked").val();
+        var display_version = "";
+        if (uri.indexOf("@") > -1) {
+            display_version = `@${entity_version.substring(0,8)}`;
+        }
+        const description = `Entity <a href="${uri}">${entity_id}${display_version}</a>`;
+        modal.find(`.${_qrcode_canvas_container}`).empty();
+        modal.find(`.${_qrcode_link_container}`).empty().append(description);
+        QRCode.toCanvas(uri, {
+            "scale": 6
+        }).then((canvas) => {
+            modal.find(`.${_qrcode_canvas_container}`).empty().append(canvas);
+        }).catch(logger.error);
     }
-    const description = `Entity <a href="${uri}">${entity_id}${display_version}</a>`;
-    modal.find(`.${_qrcode_canvas_container}`).empty();
-    modal.find(`.${_qrcode_link_container}`).empty().append(description);
-    QRCode.toCanvas(uri, {"scale": 6}).then((canvas) => {
-      modal.find(`.${_qrcode_canvas_container}`).empty().append(canvas);
-    }).catch(logger.error);
-  }
 
-  /**
-   * Create modal which shows the QR Code and a form where the user can choose
-   * whether the QR Code links to the entity head or the exact version of the
-   * entity.
-   *
-   * @param {string} modal_id - id of the resulting HTMLElement
-   * @param {string} entity_id
-   * @param {string} entity_version
-   * @return {HTMLElement} the resulting modal.
-   */
-  var create_qrcode_modal = function(modal_id, entity_id, entity_version) {
-    const uri = `${connection.getEntityUri([entity_id])}`;
-    const short_version = entity_version.substring(0,8);
-    const modal = $(`<div class="modal fade" id="${modal_id}" tabindex="-1" aria-labelledby="${modal_id}-label" aria-hidden="true">
+    /**
+     * Create modal which shows the QR Code and a form where the user can choose
+     * whether the QR Code links to the entity head or the exact version of the
+     * entity.
+     *
+     * @param {string} modal_id - id of the resulting HTMLElement
+     * @param {string} entity_id
+     * @param {string} entity_version
+     * @return {HTMLElement} the resulting modal.
+     */
+    var create_qrcode_modal = function (modal_id, entity_id, entity_version) {
+        const uri = `${connection.getEntityUri([entity_id])}`;
+        const short_version = entity_version.substring(0, 8);
+        const modal = $(`<div class="modal fade" id="${modal_id}" tabindex="-1" aria-labelledby="${modal_id}-label" aria-hidden="true">
       <div class="modal-dialog">
         <div class="modal-content">
           <div class="modal-header">
@@ -100,89 +102,93 @@ var ext_qrcode = function ($, connection, getEntityVersion, getEntityID, QRCode,
         </div>
       </div>
     </div>`);
-    modal.find("form").change(() => {update_qrcode(modal, entity_id, entity_version);});
-    return modal[0];
-  }
-
-  /**
-   * Click handler of the QR Code button. The click event opens a modal showing
-   * the QR Code and a form where the user can choose whether the QR Code links
-   * to the entity head or the exact version of the entity.
-   *
-   * @param {string} entity_id
-   * @param {string} entity_version
-   */
-  var qrcode_button_click_handler = function(entity_id, entity_version) {
-    const modal_id = `qrcode-modal-${entity_id}-${entity_version}`;
-    var modal_element = document.getElementById(modal_id);
-    if(modal_element) {
-      // toggle modal
-      const modal = bootstrap.Modal.getInstance(modal_element);
-      modal.toggle();
-    } else {
-      modal_element = create_qrcode_modal(modal_id, entity_id, entity_version);
-      update_qrcode(modal_element, entity_id, entity_version);
-      $("body").append(modal_element);
-      const options = {};
-      const modal = new bootstrap.Modal(modal_element, options);
-      modal.show();
+        modal.find("form").change(() => {
+            update_qrcode(modal, entity_id, entity_version);
+        });
+        return modal[0];
     }
-  }
 
-  /**
-   * Create a button which opens the QR Code modal on click.
-   *
-   * @param {string} entity_id
-   * @param {string} entity_version
-   * @return {HTMLElement} the newly created button.
-   */
-  var create_qrcode_button = function (entity_id, entity_version) {
-    const button = $(`<button title="Create QR Code" type="button" class="${_qrcode_button_class} caosdb-v-entity-qrcode-button btn">${_qrcode_icon}</button>`);
-    button.click(() => {qrcode_button_click_handler(entity_id, entity_version);});
-    return button[0];
-  }
+    /**
+     * Click handler of the QR Code button. The click event opens a modal showing
+     * the QR Code and a form where the user can choose whether the QR Code links
+     * to the entity head or the exact version of the entity.
+     *
+     * @param {string} entity_id
+     * @param {string} entity_version
+     */
+    var qrcode_button_click_handler = function (entity_id, entity_version) {
+        const modal_id = `qrcode-modal-${entity_id}-${entity_version}`;
+        var modal_element = document.getElementById(modal_id);
+        if (modal_element) {
+            // toggle modal
+            const modal = bootstrap.Modal.getInstance(modal_element);
+            modal.toggle();
+        } else {
+            modal_element = create_qrcode_modal(modal_id, entity_id, entity_version);
+            update_qrcode(modal_element, entity_id, entity_version);
+            $("body").append(modal_element);
+            const options = {};
+            const modal = new bootstrap.Modal(modal_element, options);
+            modal.show();
+        }
+    }
 
-  /**
-   * Add a qrcode button to a given entity.
-   * @param {HTMLElement} entity
-   */
-  var add_qrcode_to_entity = function (entity) {
-    const entity_id = getEntityID(entity);
-    const entity_version = getEntityVersion(entity);
+    /**
+     * Create a button which opens the QR Code modal on click.
+     *
+     * @param {string} entity_id
+     * @param {string} entity_version
+     * @return {HTMLElement} the newly created button.
+     */
+    var create_qrcode_button = function (entity_id, entity_version) {
+        const button = $(`<button title="Create QR Code" type="button" class="${_qrcode_button_class} caosdb-v-entity-qrcode-button btn">${_qrcode_icon}</button>`);
+        button.click(() => {
+            qrcode_button_click_handler(entity_id, entity_version);
+        });
+        return button[0];
+    }
 
-    $(entity).find(`.${_buttons_list_class}`).append(create_qrcode_button(entity_id, entity_version));
-  }
+    /**
+     * Add a qrcode button to a given entity.
+     * @param {HTMLElement} entity
+     */
+    var add_qrcode_to_entity = function (entity) {
+        const entity_id = getEntityID(entity);
+        const entity_version = getEntityVersion(entity);
 
-  var remove_qrcode_button = function (entity) {
-    $(entity).find(`.${_buttons_list_class} .${_qrcode_button_class}`).remove();
-  }
+        $(entity).find(`.${_buttons_list_class}`).append(create_qrcode_button(entity_id, entity_version));
+    }
 
-  /**
-   * Initialize this module and append a QR Code button to all entities panels on the page.
-   *
-   * Removes all respective buttons if present before adding a new one.
-   */
-  var init = function () {
-    for(let entity of $(".caosdb-entity-panel")) {
-      remove_qrcode_button(entity);
-      add_qrcode_to_entity(entity);
+    var remove_qrcode_button = function (entity) {
+        $(entity).find(`.${_buttons_list_class} .${_qrcode_button_class}`).remove();
     }
-  };
 
-  return {
-    update_qrcode: update_qrcode,
-    add_qrcode_to_entity: add_qrcode_to_entity,
-    remove_qrcode_button: remove_qrcode_button,
-    create_qrcode_button: create_qrcode_button,
-    create_qrcode_modal: create_qrcode_modal,
-    qrcode_button_click_handler: qrcode_button_click_handler,
-    init: init
-  };
+    /**
+     * Initialize this module and append a QR Code button to all entities panels on the page.
+     *
+     * Removes all respective buttons if present before adding a new one.
+     */
+    var init = function () {
+        for (let entity of $(".caosdb-entity-panel")) {
+            remove_qrcode_button(entity);
+            add_qrcode_to_entity(entity);
+        }
+    };
+
+    return {
+        update_qrcode: update_qrcode,
+        add_qrcode_to_entity: add_qrcode_to_entity,
+        remove_qrcode_button: remove_qrcode_button,
+        create_qrcode_button: create_qrcode_button,
+        create_qrcode_modal: create_qrcode_modal,
+        qrcode_button_click_handler: qrcode_button_click_handler,
+        init: init
+    };
 
 }($, connection, getEntityVersion, getEntityID, QRCode, console);
 
 $(document).ready(function () {
-  if("${BUILD_MODULE_EXT_QRCODE}"=="ENABLED") {
-    caosdb_modules.register(ext_qrcode);
-  }
-});
+    if ("${BUILD_MODULE_EXT_QRCODE}" == "ENABLED") {
+        caosdb_modules.register(ext_qrcode);
+    }
+});
\ No newline at end of file
diff --git a/test/core/js/modules/ext_qrcode.js.js b/test/core/js/modules/ext_qrcode.js.js
index 35707cc83c9c46a4f235ed2e3a8dfd429e6db33e..d4d505913035d17d14cb7b110e8dc67b0a018a44 100644
--- a/test/core/js/modules/ext_qrcode.js.js
+++ b/test/core/js/modules/ext_qrcode.js.js
@@ -31,7 +31,7 @@ QUnit.module("ext_qrcode.js", {
     afterEach: function (assert) {
         // teardown after each test
         const modal = bootstrap.Modal.getInstance($(".modal")[0]);
-        if(modal) modal.dispose();
+        if (modal) modal.dispose();
         $("#ext-qrcode-test-entity").remove();
         $(".modal").remove();
     },
@@ -45,31 +45,57 @@ QUnit.test("init", function (assert) {
     assert.equal($(".caosdb-f-entity-qrcode-button").length, 0, "no button before.");
     ext_qrcode.init();
     assert.equal($(".caosdb-f-entity-qrcode-button").length, 1, "button has been added.");
+    ext_qrcode.init();
+    assert.equal($(".caosdb-f-entity-qrcode-button").length, 1, "still only one button.");
+
+    ext_qrcode.remove_qrcode_button($("#ext-qrcode-test-entity")[0]);
+    assert.equal($(".caosdb-f-entity-qrcode-button").length, 0, "no button after removal.");
 });
 
-QUnit.test("create_qrcode_button", function(assert) {
-  assert.equal(ext_qrcode.create_qrcode_button("entityid", "versionid").tagName, "BUTTON", "create_qrcode_button creates a button");
+QUnit.test("create_qrcode_button", function (assert) {
+    assert.equal(ext_qrcode.create_qrcode_button("entityid", "versionid").tagName, "BUTTON", "create_qrcode_button creates a button");
 });
 
 
-QUnit.test("qrcode_button_click_handler", function(assert) {
-  var done = assert.async();
-  assert.equal($("#qrcode-modal-entityid-versionid").length, 0, "no modal before first click");
-  ext_qrcode.qrcode_button_click_handler("entityid", "versionid")
-  $("#qrcode-modal-entityid-versionid").on("shown.bs.modal", done);
-  assert.equal($("#qrcode-modal-entityid-versionid").length, 1, "first click added the modal");
+QUnit.test("qrcode_button_click_handler", function (assert) {
+    var done = assert.async();
+    assert.equal($("#qrcode-modal-entityid-versionid").length, 0, "no modal before first click");
+    ext_qrcode.qrcode_button_click_handler("entityid", "versionid")
+    $("#qrcode-modal-entityid-versionid").on("shown.bs.modal", done);
+    assert.equal($("#qrcode-modal-entityid-versionid").length, 1, "first click added the modal");
 });
 
-QUnit.test("update_qrcode", function(assert) {
-  // create modal
-  const entity_id = "eid456";
-  const entity_version = "vid3564";
-  const modal_id = `qrcode-modal-${entity_id}-${entity_version}`;
-  const modal_element = ext_qrcode.create_qrcode_modal(modal_id, entity_id, entity_version);
-  $(document.body).append(modal_element);
+QUnit.test("update_qrcode", async function (assert) {
+    // create modal
+    const entity_id = "eid456";
+    const entity_version = "vid3564";
+    const modal_id = `qrcode-modal-${entity_id}-${entity_version}`;
+    const modal_element = ext_qrcode.create_qrcode_modal(modal_id, entity_id, entity_version);
+    $(document.body).append(modal_element);
 
-  assert.equal($("#" + modal_id).find(".caosdb-f-entity-qrcode *").length, 0);
-  assert.equal($("#" + modal_id).find(".caosdb-f-entity-qrcode-link *").length, 0);
+    assert.equal($("#" + modal_id).find(".caosdb-f-entity-qrcode *").length, 0, "no qrcode.");
+    assert.equal($("#" + modal_id).find(".caosdb-f-entity-qrcode-link *").length, 0, "no link.");
 
-  // TODO call update_qrcode
-});
+    // update adds qrcode
+    ext_qrcode.update_qrcode(modal_element, entity_id, entity_version);
+
+    assert.equal($("#" + modal_id).find(".caosdb-f-entity-qrcode-link a")[0].href, connection.getEntityUri([entity_id]), "link points to entity head.");
+    // wait until qrcode is ready
+    await sleep(500);
+    assert.equal($("#" + modal_id).find(".caosdb-f-entity-qrcode canvas").length, 1, "qrcode is there.");
+
+    $("#" + modal_id).find("canvas").remove();
+    assert.equal($("#" + modal_id).find(".caosdb-f-entity-qrcode canvas").length, 0, "removed qrcode canvas for next test.");
+    // select radio button for link to exact version: check both...
+    $("#" + modal_id).find("input[name=entity-qrcode-versioned]").prop("checked", true);
+    // ...then uncheck first
+    $("#" + modal_id).find("input[name=entity-qrcode-versioned]").first().prop("checked", false);
+    $("#" + modal_id).find("form").trigger("change");
+
+    // check: uri has changed
+    assert.equal($("#" + modal_id).find(".caosdb-f-entity-qrcode-link a")[0].href, connection.getEntityUri([entity_id]) + "@" + entity_version, "link changed to versioned entity.");
+    // wait until qrcode is ready
+    await sleep(500);
+    assert.equal($("#" + modal_id).find(".caosdb-f-entity-qrcode canvas").length, 1, "qrcode there again.");
+
+});
\ No newline at end of file