diff --git a/__tests__/fixtures/config/export.example.json b/__tests__/fixtures/config/export.example.json
new file mode 100644
index 0000000000000000000000000000000000000000..4e7c31dcb9eada7c456c37f77d021c497ca730c6
--- /dev/null
+++ b/__tests__/fixtures/config/export.example.json
@@ -0,0 +1,148 @@
+{
+  "config": {
+    "canvasNavigation": {
+      "height": 50,
+      "width": 50
+    },
+    "theme": {
+      "palette": {
+        "type": "light",
+        "primary": {
+          "main": "#f5f5f5",
+          "light": "#ffffff",
+          "dark": "#eeeeee",
+          "contrastText": "rgba(0, 0, 0, 0.87)"
+        },
+        "secondary": {
+          "main": "#1967d2",
+          "light": "#64b5f6",
+          "dark": "#0d47a1",
+          "contrastText": "#fff"
+        },
+        "error": {
+          "main": "#b00020",
+          "light": "rgb(191, 51, 76)",
+          "dark": "rgb(123, 0, 22)",
+          "contrastText": "#fff"
+        }
+      },
+      "typography": {
+        "useNextVariants": true
+      },
+      "overrides": {
+        "MuiInput": {
+          "input": {
+            "backgroundColor": "LightGray"
+          }
+        }
+      }
+    },
+    "language": "en",
+    "availableLanguages": {
+      "de": "Deutsch",
+      "en": "English"
+    },
+    "translations": {},
+    "window": {
+      "defaultView": "single"
+    },
+    "windows": [
+      {
+        "loadedManifest": "https://iiif.harvardartmuseums.org/manifests/object/299843",
+        "canvasIndex": 2
+      },
+      {
+        "loadedManifest": "https://iiif.bodleian.ox.ac.uk/iiif/manifest/e32a277e-91e2-4a6d-8ba6-cc4bad230410.json",
+        "thumbnailNavigationPosition": "off"
+      }
+    ],
+    "thumbnailNavigation": {
+      "defaultPosition": "bottom",
+      "height": 150,
+      "width": 100
+    },
+    "workspace": {
+      "type": "mosaic"
+    },
+    "workspaceControlPanel": {
+      "enabled": true
+    },
+    "id": "mirador",
+    "manifests": {
+      "https://media.nga.gov/public/manifests/nga_highlights.json": {
+        "provider": "National Gallery of Art"
+      },
+      "https://data.ucd.ie/api/img/manifests/ucdlib:33064": {
+        "provider": "Irish Architectural Archive"
+      },
+      "https://wellcomelibrary.org/iiif/b18035723/manifest": {
+        "provider": "Wellcome Library"
+      },
+      "https://demos.biblissima.fr/iiif/metadata/florus-dispersus/manifest.json": {
+        "provider": "Biblissima"
+      },
+      "https://www.e-codices.unifr.ch/metadata/iiif/gau-Fragment/manifest.json": {
+        "provider": "e-codices - Virtual Manuscript Library of Switzerland"
+      },
+      "https://wellcomelibrary.org/iiif/collection/b18031511": {
+        "provider": "Wellcome Library"
+      },
+      "https://gallica.bnf.fr/iiif/ark:/12148/btv1b10022508f/manifest.json": {
+        "provider": "Bibliothèque nationale de France"
+      },
+      "https://manifests.britishart.yale.edu/Osbornfa1": {
+        "provider": "Beinecke Rare Book and Manuscript Library, Yale University"
+      },
+      "https://iiif.biblissima.fr/chateauroux/B360446201_MS0005/manifest.json": {
+        "provider": "Biblissima"
+      },
+      "https://iiif.durham.ac.uk/manifests/trifle/32150/t1/m4/q7/t1m4q77fr328/manifest": {
+        "provider": "Durham University Library"
+      }
+    }
+  },
+  "viewers": {
+    "window-32450374-dd2c-455e-83f6-ce0e70d21c5c": {
+      "x": 2696,
+      "y": 4079,
+      "zoom": 0.0001107429053115508
+    },
+    "window-65138dce-d192-484d-8445-b579f5ee14d6": {
+      "x": 1129.5,
+      "y": 1275,
+      "zoom": 0.0002890035037322365
+    }
+  },
+  "windows": {
+    "window-65138dce-d192-484d-8445-b579f5ee14d6": {
+      "id": "window-65138dce-d192-484d-8445-b579f5ee14d6",
+      "canvasIndex": 2,
+      "collectionIndex": 0,
+      "manifestId": "https://iiif.harvardartmuseums.org/manifests/object/299843",
+      "rangeId": null,
+      "thumbnailNavigationPosition": "bottom",
+      "width": 400,
+      "height": 400,
+      "x": 2700,
+      "y": 2700,
+      "companionWindowIds": [],
+      "rotation": null,
+      "view": "single"
+    },
+    "window-32450374-dd2c-455e-83f6-ce0e70d21c5c": {
+      "id": "window-32450374-dd2c-455e-83f6-ce0e70d21c5c",
+      "canvasIndex": 0,
+      "collectionIndex": 0,
+      "manifestId": "https://iiif.bodleian.ox.ac.uk/iiif/manifest/e32a277e-91e2-4a6d-8ba6-cc4bad230410.json",
+      "rangeId": null,
+      "thumbnailNavigationPosition": "off",
+      "width": 400,
+      "height": 400,
+      "x": 2700,
+      "y": 2700,
+      "companionWindowIds": [],
+      "rotation": null,
+      "view": "single"
+    }
+  }
+}
\ No newline at end of file
diff --git a/__tests__/src/actions/erros.test.js b/__tests__/src/actions/erros.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..8fcc5faa80e27a764d61edbceef694cf3ccfb556
--- /dev/null
+++ b/__tests__/src/actions/erros.test.js
@@ -0,0 +1,27 @@
+import * as actions from '../../../src/state/actions';
+import ActionTypes from '../../../src/state/actions/action-types';
+
+describe('errors actions', () => {
+  describe('addError', () => {
+    it('adds an error', () => {
+      const errorMessage = 'errorMessage';
+      const createdAction = actions.addError(errorMessage);
+
+      expect(createdAction).toHaveProperty('message', errorMessage);
+      expect(createdAction).toHaveProperty('id');
+      expect(createdAction.id).toBeDefined();
+    });
+  });
+
+  describe('removeError', () => {
+    it('removes an existing error', () => {
+      const errorId = 'testId123';
+      const expectedAction = {
+        type: ActionTypes.REMOVE_ERROR,
+        id: errorId,
+      };
+
+      expect(actions.removeError(errorId)).toEqual(expectedAction);
+    });
+  });
+});
diff --git a/__tests__/src/components/ErrorDialog.test.js b/__tests__/src/components/ErrorDialog.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..109187269e2245289d63b30b19d512771e01e86d
--- /dev/null
+++ b/__tests__/src/components/ErrorDialog.test.js
@@ -0,0 +1,43 @@
+import React from 'react';
+import { shallow } from 'enzyme';
+import { ErrorDialog } from '../../../src/components/ErrorDialog';
+
+/**
+ * Helper function to create a shallow wrapper around ErrorDialog
+ */
+function createWrapper(props) {
+  return shallow(
+    <ErrorDialog
+      t={key => key}
+      {...props}
+    />,
+  );
+}
+
+describe('ErrorDialog', () => {
+  let wrapper;
+
+  it('renders properly', () => {
+    const errors = { testid123: { id: 'testid123', message: '' } };
+
+    wrapper = createWrapper({ errors });
+    expect(wrapper.find('WithStyles(Dialog)').length).toBe(1);
+  });
+
+  it('shows up error message correctly', () => {
+    const errorMessage = 'error testMessage 123';
+    const errors = { testid123: { id: 'testid123', message: errorMessage } };
+
+    wrapper = createWrapper({ errors });
+    expect(wrapper.find('WithStyles(Typography)[variant="body2"]').render().text()).toBe(errorMessage);
+  });
+
+  it('triggers the handleClick prop when clicking the ok button', () => {
+    const errors = { testid123: { id: 'testid123', message: '' } };
+    const mockHandleClick = jest.fn();
+
+    wrapper = createWrapper({ errors, removeError: mockHandleClick });
+    wrapper.find('WithStyles(Button)').simulate('click');
+    expect(mockHandleClick).toHaveBeenCalledTimes(1);
+  });
+});
diff --git a/__tests__/src/reducers/config.test.js b/__tests__/src/reducers/config.test.js
index 9c53c62eea778dfa844f1c393d0c4fd8533ed18a..36d4cc2bcf76a91b6d9da3b891274bfb9078b4b0 100644
--- a/__tests__/src/reducers/config.test.js
+++ b/__tests__/src/reducers/config.test.js
@@ -1,5 +1,6 @@
 import { configReducer } from '../../../src/state/reducers/config';
 import ActionTypes from '../../../src/state/actions/action-types';
+import configFixture from '../../fixtures/config/export.example.json';
 
 describe('config reducer', () => {
   describe('SET_CONFIG', () => {
@@ -42,4 +43,12 @@ describe('config reducer', () => {
       });
     });
   });
+  describe('IMPORT_CONFIG', () => {
+    it('should handle IMPORT_CONFIG', () => {
+      expect(configReducer([], {
+        type: ActionTypes.IMPORT_CONFIG,
+        config: configFixture,
+      })).toEqual(configFixture);
+    });
+  });
 });
diff --git a/__tests__/src/reducers/errors.test.js b/__tests__/src/reducers/errors.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..1bef0d93ccbaca7976f5bff131eb1c2a1ce221a7
--- /dev/null
+++ b/__tests__/src/reducers/errors.test.js
@@ -0,0 +1,42 @@
+
+import { errorsReducer } from '../../../src/state/reducers/errors';
+import ActionTypes from '../../../src/state/actions/action-types';
+
+describe('ADD_ERROR', () => {
+  const errorMessage = 'testErrorMessage';
+  const errorId = 'errorId123';
+
+  it('should handle ADD_ERROR', () => {
+    const error = {
+      id: errorId,
+      message: errorMessage,
+    };
+    const ret = errorsReducer(undefined, {
+      type: ActionTypes.ADD_ERROR,
+      ...error,
+
+    });
+    expect(ret.items).toEqual([error.id]);
+    expect(ret).toHaveProperty(error.id);
+    expect(ret[error.id]).toEqual(error);
+  });
+
+  it('should handle REMOVE_ERROR', () => {
+    const stateBefore = {
+      items: [errorId],
+      errorId: {
+        id: errorId,
+        message: errorMessage,
+      },
+    };
+
+    /*
+      Only the id is removed from the 'items' array. The error itself remains part of the state,
+      so we are able to provide an error history or some kind of logs later on
+    */
+    expect(errorsReducer(stateBefore, {
+      type: ActionTypes.REMOVE_ERROR,
+      id: errorId,
+    })).toHaveProperty('items', []);
+  });
+});
diff --git a/src/components/ErrorDialog.js b/src/components/ErrorDialog.js
index 9b819ef9d60e8bd2cc480a0f0abcbac916ebd151..40032c0bb6a8cfd98d599868085c02cbdbafdff5 100644
--- a/src/components/ErrorDialog.js
+++ b/src/components/ErrorDialog.js
@@ -27,7 +27,6 @@ export class ErrorDialog extends Component {
     /* extract 'items' value and get first key-value-pair (an error) */
     const error = first(values(omit(errors, 'items')));
     const hasError = !isUndefined(error);
-    
     return (
       <div>
         { hasError && (
diff --git a/src/containers/ErrorDialog.js b/src/containers/ErrorDialog.js
index 2d1fc27cfae474e4f16e7c7d50bfd1501b8c99e9..c491690dd6cf034888c1e5c87df7f7524b2e33d9 100644
--- a/src/containers/ErrorDialog.js
+++ b/src/containers/ErrorDialog.js
@@ -20,7 +20,6 @@ const mapStateToProps = state => ({
  * @private
  */
 const mapDispatchToProps = {
-  addError: actions.addError,
   removeError: actions.removeError,
 };