diff --git a/.gitattributes b/.gitattributes
index 9eaaa7202149d0cd48c583589f5e87d99107c6c4..6b71fc789360605b77f8f82161887ac88953f392 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,15 +1,12 @@
-test export-ignore
-vendor export-ignore
+.git/ export-ignore
+tests/ export-ignore
+vendor/ export-ignore
 .editorconfig export-ignore
 .gitattributes export-ignore
 .gitignore export-ignore
-.git export-ignore
 .gitlab-ci.yml export-ignore
 .idea export-ignore
 apigen.neon export-ignore
-build-coverage export-ignore
-docs export-ignore
-LICENSE.md export-ignore
 phpcs.xml.dist export-ignore
 phpunit-integration.xml export-ignore
 phpunit-unit.xml export-ignore
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index a260ae08084e00ef2e6b55e208f55548f6e92340..6a60442002ef5b5a52af41c871dc78d3a9ccfa59 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,270 +1,6 @@
 variables:
-  WPDESK_CI_VERSION: 1.10.19
-  MYSQL_ROOT_PASSWORD: mysql
-  MYSQL_DATABASE: wptest
-  MYSQL_USER: mysql
-  MYSQL_PASSWORD: mysql
-  MYSQL_INNODB_LOG_BUFFER_SIZE: 32M
-  PHP_ERROR_REPORTING: E_ALL
-  COMPOSER_ALLOW_SUPERUSER: 1
-  GIT_STRATEGY: fetch
-  ACCEPTANCE_ERROR_PATH: ${CI_PROJECT_DIR}/acceptance
+  DISABLE_FUNCTIONAL: 1
+  DISABLE_ACCEPTANCE: 1
 
-stages:
-  - tools
-  - tests
-  - pre-deploy
-  - deploy
+include: 'https://gitlab.com/wpdesk/gitlab-ci/raw/master/gitlab-ci-1.2.yml'
 
-.template: &job-test-template
-  stage: tests
-  coverage: '/^\s*Lines:\s*\d+.\d+\%/'
-
-.template: &job-test-integration-template
-  <<: *job-test-template
-  services:
-    - mysql:5.6
-  script:
-    - echo ${WPDESK_CI_VERSION}
-    - ls -l
-    - php --version
-    - cat /tmp/wordpress-develop/src/wp-includes/version.php
-    - cat /tmp/woocommerce/woocommerce.php
-    - composer update --no-progress
-    - if [[ -f tests/integration/prepare.sh ]]; then sh tests/integration/prepare.sh; fi
-    - vendor/bin/phpunit --configuration phpunit-integration.xml --coverage-text --colors=never
-  only:
-    - tags
-    - master
-
-.template: &job-test-integration-template-fast
-  <<: *job-test-integration-template
-  script:
-    - echo ${WPDESK_CI_VERSION}
-    - ls -l
-    - php --version
-    - cat /tmp/wordpress-develop/src/wp-includes/version.php
-    - cat /tmp/woocommerce/woocommerce.php
-    - composer update --no-progress
-    - if [[ -f tests/integration/prepare.sh ]]; then sh tests/integration/prepare.sh; fi
-    - vendor/bin/phpunit --configuration phpunit-integration.xml --no-coverage
-  except:
-    - tags
-  only:
-
-.template: &job-test-unit-template
-  <<: *job-test-template
-  script:
-    - echo ${WPDESK_CI_VERSION}
-    - ls -l
-    - php --version
-    - cat /tmp/wordpress-develop/src/wp-includes/version.php
-    - cat /tmp/woocommerce/woocommerce.php
-    - composer update --no-progress
-    - vendor/bin/phpunit --configuration phpunit-unit.xml --coverage-text --colors=never
-  only:
-    - tags
-
-.template: &job-test-unit-template-fast
-  <<: *job-test-unit-template
-  script:
-    - echo ${WPDESK_CI_VERSION}
-    - ls -l
-    - php --version
-    - cat /tmp/wordpress-develop/src/wp-includes/version.php
-    - cat /tmp/woocommerce/woocommerce.php
-    - composer update --no-progress
-    - vendor/bin/phpunit --configuration phpunit-unit.xml --no-coverage
-  except:
-    - tags
-  only:
-
-.template: &job-deploy-template
-  image: wpdesknet/amazon-svn-deploy
-  stage: deploy
-  dependencies:
-    - build to deploy
-    - unit test lastest coverage
-    - integration test lastest coverage
-  retry: 2
-  when: manual
-  only:
-    - tags
-
-before_script:
-  - cd ${CI_PROJECT_DIR}
-
-phpmetric metrics:
-  stage: tools
-  image: wpdesknet/phpunit-woocommerce:0-0
-  allow_failure: true
-  when: manual
-  artifacts:
-    when: always
-    expire_in: 1 month
-    name: "metrics"
-    paths:
-      - ${CI_PROJECT_DIR}/phpmetric
-  script:
-    - echo ${WPDESK_CI_VERSION}
-    - composer require phpmetrics/phpmetrics
-    - composer update --no-progress
-    - php ./vendor/bin/phpmetrics --report-html=phpmetric .
-
-churn metrics:
-  stage: tools
-  image: wpdesknet/phpunit-woocommerce:0-0
-  allow_failure: true
-  when: manual
-  script:
-    - echo ${WPDESK_CI_VERSION}
-    - composer require bmitch/churn-php
-    - composer update --no-progress
-    - vendor/bin/churn run classes inc
-
-#code style test:
-# stage: tests
-#  image: wpdesknet/phpunit-woocommerce:0-0
-#  allow_failure: true
-#  script:
-#    - echo ${WPDESK_CI_VERSION}
-#    - composer update --no-progress
-#    - vendor/bin/phpcs
-
-unit test lastest:
-  <<: *job-test-unit-template-fast
-  image: wpdesknet/phpunit-woocommerce:0-0
-
-integration test lastest:
-  <<: *job-test-integration-template-fast
-  image: wpdesknet/phpunit-woocommerce:0-0
-
-unit test lastest coverage:
-  <<: *job-test-unit-template
-  image: wpdesknet/phpunit-woocommerce:0-0
-
-integration test lastest coverage:
-  <<: *job-test-integration-template
-  image: wpdesknet/phpunit-woocommerce:0-0
-
-integration test php7-1 wc-1:
-  <<: *job-test-integration-template-fast
-  image: wpdesknet/phpunit-woocommerce:1-1
-
-integration test php7 wc-2:
-  <<: *job-test-integration-template-fast
-  image: wpdesknet/phpunit-woocommerce:2-2
-
-integration test php-7 wc-3:
-  <<: *job-test-integration-template-fast
-  image: wpdesknet/phpunit-woocommerce:2-3
-
-integration test php5-6:
-  <<: *job-test-integration-template-fast
-  image: wpdesknet/phpunit-woocommerce:3-0
-
-integration test php5-5:
-  <<: *job-test-integration-template-fast
-  image: wpdesknet/phpunit-woocommerce:4-0
-
-integration test current woocommerce:
-  <<: *job-test-integration-template-fast
-  image: wpdesknet/phpunit-woocommerce:0-0
-  allow_failure: true
-  before_script:
-    - cd /tmp
-    - rm -rf woocommerce
-    - git clone https://github.com/woocommerce/woocommerce.git
-    - cd ${CI_PROJECT_DIR}
-
-apigen docs:
-  image:
-    name: wpdesknet/apigen
-  stage: pre-deploy
-  artifacts:
-    expire_in: 1 day
-    name: "docs"
-    paths:
-      - docs/
-  script:
-    - echo ${WPDESK_CI_VERSION}
-    - ls -l
-    - /app/vendor/bin/apigen generate
-    - php /app/hooks-docs.php ${CI_PROJECT_DIR}
-  only:
-    - tags
-
-pages:
-  stage: deploy
-  dependencies:
-    - apigen docs
-  script:
-    - rm -rf public
-    - mv docs/ public/
-    - 'curl -X POST --data-urlencode "payload={\"text\": \"Dokumentacja projektu ${CI_PROJECT_NAME} w wersji ${CI_COMMIT_REF_NAME} umieszczona w <https://gitlab.com/wpdesk/${CI_PROJECT_NAME}/pages|pages> \", }" https://hooks.slack.com/services/${SLACK_AUTH}'
-  artifacts:
-    expire_in: 1 day
-    paths:
-      - public
-  only:
-    - tags
-
-build to deploy:
-  image: wpdesknet/phpunit-woocommerce:4-0
-  stage: pre-deploy
-  artifacts:
-    expire_in: 1 month
-    name: "production release"
-    paths:
-      - release
-      - release.zip
-  script:
-    - echo ${WPDESK_CI_VERSION}
-    - php --version
-    - ls -l
-    - /tmp/set_version.sh ${CI_COMMIT_REF_NAME}
-    - rm -rf ${CI_PROJECT_DIR}/release ${CI_PROJECT_DIR}/release.zip /tmp/release
-    - mkdir /tmp/release
-    - mkdir -p ${CI_PROJECT_DIR}/release/${CI_PROJECT_NAME}
-    - cp -rf ${CI_PROJECT_DIR}/* /tmp/release
-    - cp -rf /tmp/release/* ${CI_PROJECT_DIR}/release/${CI_PROJECT_NAME}
-    - cd ${CI_PROJECT_DIR}/release/${CI_PROJECT_NAME}
-    - composer install --no-dev --no-progress --optimize-autoloader
-    - rm -rf build-coverage release tests docs .git .editorconfig .gitignore .gitlab-ci.yml apigen.neon phpunit.xml acceptance test_soap.php .gitlab
-    - rm -rf composer.json composer.lock phpcs.xml.dist phpunit-integration.xml phpunit-unit.xml composer.phar wp-cli.phar
-    - cd ../
-    - zip -r -q ../release.zip ./
-  only:
-    - tags
-
-deploy to shop:
-  <<: *job-deploy-template
-  script:
-    - echo ${WPDESK_CI_VERSION}
-    - /tmp/deploy_shop.sh ${CI_PROJECT_NAME} release.zip ${CI_PROJECT_NAME}.zip
-    - 'curl -X POST --data-urlencode "payload={\"text\": \"Projekt <https://gitlab.com/wpdesk/${CI_PROJECT_NAME}|${CI_PROJECT_NAME}> zdeployowany do sklepu w wersji ${CI_COMMIT_REF_NAME}\", }" https://hooks.slack.com/services/${SLACK_AUTH}'
-  environment:
-    name: wpdesk shop
-    url: https://wpdeskplugin.s3.amazonaws.com/${CI_PROJECT_NAME}.zip
-
-deploy to demo:
-  <<: *job-deploy-template
-  script:
-    - echo ${WPDESK_CI_VERSION}
-    - /tmp/deploy_demo.sh release/${CI_PROJECT_NAME} ${CI_PROJECT_NAME}
-    - 'curl -X POST --data-urlencode "payload={\"text\": \"Projekt <https://gitlab.com/wpdesk/${CI_PROJECT_NAME}|${CI_PROJECT_NAME}> zdeployowany do demo w wersji ${CI_COMMIT_REF_NAME}\", }" https://hooks.slack.com/services/${SLACK_AUTH}'
-  environment:
-    name: wpdesk demo
-    url: https://demo.wpdesk.org
-
-deploy to repository:
-  <<: *job-deploy-template
-  script:
-    - echo ${WPDESK_CI_VERSION}
-    - rm -rf /tmp/svn-repository
-    - mkdir /tmp/svn-repository
-    - /tmp/deploy_repository.sh ${CI_PROJECT_NAME} ${CI_PROJECT_DIR}/release/${CI_PROJECT_NAME} /tmp/svn-repository
-    - 'curl -X POST --data-urlencode "payload={\"text\": \"Projekt <https://gitlab.com/wpdesk/${CI_PROJECT_NAME}|${CI_PROJECT_NAME}> zdeployowany do repozytorium WP w wersji ${CI_COMMIT_REF_NAME}\", }" https://hooks.slack.com/services/${SLACK_AUTH}'
-  environment:
-    name: wordpress repository
-    url: https://downloads.wordpress.org/plugin/${CI_PROJECT_NAME}.${CI_COMMIT_REF_NAME}.zip
diff --git a/README.md b/README.md
index 2aa5ce9200517d084333f258b5b1612196884c6a..39e6e79a35e5c5baadd409b0dc44313b59f0dcc0 100644
--- a/README.md
+++ b/README.md
@@ -37,7 +37,7 @@ require_once 'vendor/autoload.php';
 If you do not wish to use Composer, you can download the latest release. Then, to use the Notices, include the init.php file.
 
 ```php
-require_once('/path/to/notice/src/init.php');
+require_once('/path/to/notice/src/notice-init.php');
 ```
 
 ## Getting Started
diff --git a/composer.json b/composer.json
index 2634b4c83c5ea73948616fa9bee5c2ebd485ab5a..5a06be61f84861dfe5ee623b9e8049c034446e67 100644
--- a/composer.json
+++ b/composer.json
@@ -13,7 +13,6 @@
     ],
     "require": {
         "php": ">=5.5",
-        "wpdesk/wp-basic-requirements": "^2.0",
 	    "wpdesk/wp-builder": "^1.0"
 	},
     "require-dev": {
@@ -26,7 +25,7 @@
     },
     "autoload": {
 		"psr-4": {"WPDesk\\Notice\\": "src/WPDesk/Notice/"},
-        "files": ["src/WPDesk/functions.php"]
+        "files": ["src/WPDesk/notice-functions.php"]
     },
     "autoload-dev": {
     },
diff --git a/phpunit-integration.xml b/phpunit-integration.xml
index 4ab26660b6b026743711f94b76a0f2866493ed5f..634b884c1c32948885c7e1ff159b3531e235d298 100644
--- a/phpunit-integration.xml
+++ b/phpunit-integration.xml
@@ -12,6 +12,7 @@
             <directory suffix=".php">src</directory>
             <exclude>
                 <file>src/init.php</file>
+                <directory>src/assets</directory>
                 <directory suffix=".php">tests</directory>
                 <directory suffix=".php">vendor</directory>
             </exclude>
diff --git a/src/WPDesk/Notice/Factory.php b/src/WPDesk/Notice/Factory.php
index 2deacf115b81f7bbdf10c8940767bf9c66fca306..b342aa06405a4480615d57b572990ea1b9020b94 100644
--- a/src/WPDesk/Notice/Factory.php
+++ b/src/WPDesk/Notice/Factory.php
@@ -23,7 +23,7 @@ class Factory
      */
     public static function notice($noticeContent = '', $noticeType = 'info', $isDismissible = false, $priority = 10)
     {
-        return new Notice($noticeType, $noticeContent, $isDismissible, $priority);
+        return new Notice($noticeContent, $noticeType, $isDismissible, $priority);
     }
 
     /**
@@ -38,11 +38,11 @@ class Factory
      */
     public static function permanentDismissibleNotice(
         $noticeContent = '',
-        $noticeType = '',
         $noticeName = '',
+        $noticeType = '',
         $priority = 10
     ) {
-        return new PermanentDismissibleNotice($noticeType, $noticeContent, $noticeName, $priority);
+        return new PermanentDismissibleNotice($noticeContent, $noticeName, $noticeType, $priority);
     }
 
 }
diff --git a/src/WPDesk/Notice/Notice.php b/src/WPDesk/Notice/Notice.php
index d3ea070240edc36155885d45e8ee166bd3d700ed..b3e69cb13cc23c3b8514647bf103f124d59d0d0f 100644
--- a/src/WPDesk/Notice/Notice.php
+++ b/src/WPDesk/Notice/Notice.php
@@ -16,6 +16,8 @@ class Notice
     const NOTICE_TYPE_SUCCESS = 'success';
     const NOTICE_TYPE_INFO = 'info';
 
+    const ADMIN_FOOTER_BASE_PRIORITY = 9999999;
+
     /**
      * Notice type.
      *
@@ -156,18 +158,42 @@ class Notice
     {
         if (!$this->actionAdded) {
             add_action('admin_notices', [$this, 'showNotice'], $this->priority);
+            add_action(
+                'admin_footer',
+                [$this, 'showNotice'],
+                self::ADMIN_FOOTER_BASE_PRIORITY + intval($this->priority)
+            );
             $this->actionAdded = true;
         }
     }
 
+    /**
+     * Remove action.
+     */
     protected function removeAction()
     {
         if ($this->actionAdded) {
             remove_action('admin_notices', [$this, 'showNotice'], $this->priority);
+            remove_action(
+                'admin_footer',
+                [$this, 'showNotice'],
+                self::ADMIN_FOOTER_BASE_PRIORITY + intval($this->priority)
+            );
             $this->actionAdded = false;
         }
     }
 
+    /**
+     * Add attribute.
+     *
+     * @param string $name Name
+     * @param string $value Value.
+     */
+    public function addAttribute($name, $value)
+    {
+        $this->attributes[ $name ] = $value;
+    }
+
     /**
      * Get notice class.
      *
@@ -221,6 +247,7 @@ class Notice
      */
     public function showNotice()
     {
+        $this->removeAction();
         $noticeFormat = '<div %1$s>%2$s</div>';
         if ($this->addParagraphToContent()) {
             $noticeFormat = '<div %1$s><p>%2$s</p></div>';
diff --git a/src/WPDesk/Notice/PermanentDismissibleNotice.php b/src/WPDesk/Notice/PermanentDismissibleNotice.php
index 00d0336ec88ea86433ddb17ae164d811b2a6f09b..210176f9e8620401e9995c6bace4c8a1f89e2f36 100644
--- a/src/WPDesk/Notice/PermanentDismissibleNotice.php
+++ b/src/WPDesk/Notice/PermanentDismissibleNotice.php
@@ -28,13 +28,18 @@ class PermanentDismissibleNotice extends Notice
      * WPDesk_Flexible_Shipping_Notice constructor.
      *
      * @param string $noticeContent Notice content.
-     * @param string $noticeType Notice type.
      * @param string $noticeName Notice dismiss option name.
+     * @param string $noticeType Notice type.
      * @param int    $priority Priority
      * @param array $attributes Attributes.
      */
-    public function __construct($noticeContent, $noticeType, $noticeName, $priority = 10, $attributes = array())
-    {
+    public function __construct(
+        $noticeContent,
+        $noticeName,
+        $noticeType = 'info',
+        $priority = 10,
+        $attributes = array()
+    ) {
         parent::__construct($noticeContent, $noticeType, true, $priority, $attributes);
         $this->noticeName = $noticeName;
         $this->noticeDismissOptionName = static::OPTION_NAME_PREFIX . $noticeName;
@@ -60,7 +65,8 @@ class PermanentDismissibleNotice extends Notice
     protected function getAttributesAsString()
     {
         $attributesAsString = parent::getAttributesAsString();
-        $attributesAsString .= sprintf('data-notice-name="%1$s"', esc_attr($this->noticeName));
+        $attributesAsString .= sprintf(' data-notice-name="%1$s"', esc_attr($this->noticeName));
+        $attributesAsString .= sprintf(' id="wpdesk-notice-%1$s"', esc_attr($this->noticeName));
         return $attributesAsString;
     }
 
diff --git a/src/WPDesk/functions.php b/src/WPDesk/functions.php
deleted file mode 100644
index c7f6dd261e99c9f8f334bcb8c407bb9542e7ccf0..0000000000000000000000000000000000000000
--- a/src/WPDesk/functions.php
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-
-/**
- * Creates Notice.
- *
- * @param string $noticeContent Notice content.
- * @param string $noticeType Notice type.
- * @param bool   $dismissible Dismissible notice.
- * @param int    $priority Notice priority,
- *
- * @return \WPDesk\Notice\Notice
- */
-function WPDeskNotice($noticeContent, $noticeType = 'info', $dismissible = false, $priority = 10)
-{
-    return \WPDesk\Notice\Factory::notice($noticeContent, $noticeType, $dismissible, $priority);
-}
-
-/**
- * Creates Notice.
- *
- * Alias for {@see WPDeskNotice()} function.
- *
- * @param string $noticeContent Notice content.
- * @param string $noticeType Notice type.
- * @param bool   $dismissible Dismissible notice.
- * @param int    $priority Notice priority,
- *
- * @return \WPDesk\Notice\Notice
- */
-function wpdesk_notice($noticeContent, $noticeType = 'info', $dismissible = false, $priority = 10)
-{
-    return WPDeskNotice($noticeContent, $noticeType, $dismissible, $priority);
-}
-
-/**
- * Creates Permanent Dismissible Notice.
- *
- * @param string $noticeContent Notice content.
- * @param string $noticeType Notice type.
- * @param int    $priority Notice priority.
- *
- * @return \WPDesk\Notice\Notice
- */
-function WPDeskPermanentDismissibleNotice($noticeContent, $noticeType = 'info', $priority = 10)
-{
-    return \WPDesk\Notice\Factory::permanentDismissibleNotice($noticeContent, $noticeType, $priority);
-}
-
-/**
- * Creates Permanent Dismissible Notice.
- *
- * Alias for {@see WPDeskPermanentDismissibleNotice()} function.
- *
- * @param string $noticeContent Notice content.
- * @param string $noticeType Notice type.
- * @param int    $priority Notice priority.
- *
- * @return \WPDesk\Notice\Notice
- */
-function wpdesk_permanent_dismissible_notice($noticeContent, $noticeType = 'info', $priority = 10)
-{
-    return WPDeskPermanentDismissibleNotice($noticeContent, $noticeType, $priority);
-}
diff --git a/src/WPDesk/notice-functions.php b/src/WPDesk/notice-functions.php
new file mode 100644
index 0000000000000000000000000000000000000000..ca810c57f33136f6394a40908a0182155784a04e
--- /dev/null
+++ b/src/WPDesk/notice-functions.php
@@ -0,0 +1,234 @@
+<?php
+
+if (!function_exists('WPDeskNotice')) {
+    /**
+     * Creates Notice.
+     *
+     * @param string $noticeContent Notice content.
+     * @param string $noticeType Notice type.
+     * @param bool $dismissible Dismissible notice.
+     * @param int $priority Notice priority,
+     *
+     * @return \WPDesk\Notice\Notice
+     */
+    function WPDeskNotice($noticeContent, $noticeType = 'info', $dismissible = false, $priority = 10)
+    {
+        return \WPDesk\Notice\Factory::notice($noticeContent, $noticeType, $dismissible, $priority);
+    }
+}
+
+if (!function_exists('wpdesk_notice')) {
+    /**
+     * Creates Notice.
+     *
+     * Alias for {@see WPDeskNotice()} function.
+     *
+     * @param string $noticeContent Notice content.
+     * @param string $noticeType Notice type.
+     * @param bool $dismissible Dismissible notice.
+     * @param int $priority Notice priority,
+     *
+     * @return \WPDesk\Notice\Notice
+     */
+    function wpdesk_notice($noticeContent, $noticeType = 'info', $dismissible = false, $priority = 10)
+    {
+        return WPDeskNotice($noticeContent, $noticeType, $dismissible, $priority);
+    }
+}
+
+if (!function_exists('WPDeskNoticeInfo')) {
+    /**
+     * Creates Notice Info.
+     *
+     * @param string $noticeContent Notice content.
+     * @param bool $dismissible Dismissible notice.
+     * @param int $priority Notice priority,
+     *
+     * @return \WPDesk\Notice\Notice
+     */
+    function WPDeskNoticeInfo($noticeContent, $dismissible = false, $priority = 10)
+    {
+        return \WPDesk\Notice\Factory::notice(
+            $noticeContent,
+            \WPDesk\Notice\Notice::NOTICE_TYPE_INFO,
+            $dismissible,
+            $priority
+        );
+    }
+}
+
+if (!function_exists('wpdesk_notice_info')) {
+    /**
+     * Creates Notice Info.
+     *
+     * Alias for {@see WPDeskNoticeInfo()} function.
+     *
+     * @param string $noticeContent Notice content.
+     * @param bool $dismissible Dismissible notice.
+     * @param int $priority Notice priority,
+     *
+     * @return \WPDesk\Notice\Notice
+     */
+    function wpdesk_notice_info($noticeContent, $dismissible = false, $priority = 10)
+    {
+        return WPDeskNoticeInfo($noticeContent, $dismissible, $priority);
+    }
+}
+
+if (!function_exists('WPDeskNoticeError')) {
+    /**
+     * Creates Notice Error.
+     *
+     * @param string $noticeContent Notice content.
+     * @param bool $dismissible Dismissible notice.
+     * @param int $priority Notice priority,
+     *
+     * @return \WPDesk\Notice\Notice
+     */
+    function WPDeskNoticeError($noticeContent, $dismissible = false, $priority = 10)
+    {
+        return \WPDesk\Notice\Factory::notice(
+            $noticeContent,
+            \WPDesk\Notice\Notice::NOTICE_TYPE_ERROR,
+            $dismissible,
+            $priority
+        );
+    }
+}
+
+if (!function_exists('wpdesk_notice_error')) {
+    /**
+     * Creates Notice Error.
+     *
+     * Alias for {@see WPDeskNoticeError()} function.
+     *
+     * @param string $noticeContent Notice content.
+     * @param bool $dismissible Dismissible notice.
+     * @param int $priority Notice priority,
+     *
+     * @return \WPDesk\Notice\Notice
+     */
+    function wpdesk_notice_error($noticeContent, $dismissible = false, $priority = 10)
+    {
+        return WPDeskNoticeError($noticeContent, $dismissible, $priority);
+    }
+}
+
+if (!function_exists('WPDeskNoticeWarning')) {
+    /**
+     * Creates Notice Warning.
+     *
+     * @param string $noticeContent Notice content.
+     * @param bool $dismissible Dismissible notice.
+     * @param int $priority Notice priority,
+     *
+     * @return \WPDesk\Notice\Notice
+     */
+    function WPDeskNoticeWarning($noticeContent, $dismissible = false, $priority = 10)
+    {
+        return \WPDesk\Notice\Factory::notice(
+            $noticeContent,
+            \WPDesk\Notice\Notice::NOTICE_TYPE_WARNING,
+            $dismissible,
+            $priority
+        );
+    }
+}
+
+if (!function_exists('wpdesk_notice_warning')) {
+    /**
+     * Creates Notice Warning.
+     *
+     * Alias for {@see WPDeskNoticeWarning()} function.
+     *
+     * @param string $noticeContent Notice content.
+     * @param bool $dismissible Dismissible notice.
+     * @param int $priority Notice priority,
+     *
+     * @return \WPDesk\Notice\Notice
+     */
+    function wpdesk_notice_warning($noticeContent, $dismissible = false, $priority = 10)
+    {
+        return WPDeskNoticeWarning($noticeContent, $dismissible, $priority);
+    }
+}
+
+if (!function_exists('WPDeskNoticeSuccess')) {
+    /**
+     * Creates Notice Success.
+     *
+     * @param string $noticeContent Notice content.
+     * @param bool $dismissible Dismissible notice.
+     * @param int $priority Notice priority,
+     *
+     * @return \WPDesk\Notice\Notice
+     */
+    function WPDeskNoticeSuccess($noticeContent, $dismissible = false, $priority = 10)
+    {
+        return \WPDesk\Notice\Factory::notice(
+            $noticeContent,
+            \WPDesk\Notice\Notice::NOTICE_TYPE_SUCCESS,
+            $dismissible,
+            $priority
+        );
+    }
+}
+
+if (!function_exists('wpdesk_notice_success')) {
+    /**
+     * Creates Notice Success.
+     *
+     * Alias for {@see WPDeskNoticeSuccess()} function.
+     *
+     * @param string $noticeContent Notice content.
+     * @param bool $dismissible Dismissible notice.
+     * @param int $priority Notice priority,
+     *
+     * @return \WPDesk\Notice\Notice
+     */
+    function wpdesk_notice_success($noticeContent, $dismissible = false, $priority = 10)
+    {
+        return WPDeskNoticeSuccess($noticeContent, $dismissible, $priority);
+    }
+}
+
+if (!function_exists('WPDeskPermanentDismissibleNotice')) {
+    /**
+     * Creates Permanent Dismissible Notice.
+     *
+     * @param string $noticeContent Notice content.
+     * @param string $noticeType Notice type.
+     * @param string $noticeName Notice name.
+     * @param int $priority Notice priority.
+     *
+     * @return \WPDesk\Notice\Notice
+     */
+    function WPDeskPermanentDismissibleNotice($noticeContent, $noticeName, $noticeType = 'info', $priority = 10)
+    {
+        return \WPDesk\Notice\Factory::permanentDismissibleNotice(
+            $noticeContent,
+            $noticeName,
+            $noticeType,
+            $priority
+        );
+    }
+}
+
+if (!function_exists('wpdesk_permanent_dismissible_notice')) {
+    /**
+     * Creates Permanent Dismissible Notice.
+     *
+     * Alias for {@see WPDeskPermanentDismissibleNotice()} function.
+     *
+     * @param string $noticeContent Notice content.
+     * @param string $noticeName Notice name.
+     * @param string $noticeType Notice type.
+     * @param int $priority Notice priority.
+     *
+     * @return \WPDesk\Notice\Notice
+     */
+    function wpdesk_permanent_dismissible_notice($noticeContent, $noticeName, $noticeType = 'info', $priority = 10)
+    {
+        return WPDeskPermanentDismissibleNotice($noticeContent, $noticeName, $noticeType, $priority);
+    }
+}
diff --git a/src/assets/js/notice.js b/src/assets/js/notice.js
new file mode 100644
index 0000000000000000000000000000000000000000..c084824e5a10ead47df75b94addabc5d44300f42
--- /dev/null
+++ b/src/assets/js/notice.js
@@ -0,0 +1,16 @@
+jQuery( document ).on( 'click', '.notice-dismiss', function() {
+    var notice_name = jQuery(this).closest('div.notice').data('notice-name');
+    console.log(notice_name);
+    if ('' !== notice_name) {
+        jQuery.ajax({
+            url: ajaxurl,
+            type: 'post',
+            data: {
+                action: 'wpdesk_notice_dismiss',
+                notice_name: notice_name
+            },
+            success: function (response) {
+            }
+        });
+    }
+});
diff --git a/src/assets/js/notice.min.js b/src/assets/js/notice.min.js
new file mode 100644
index 0000000000000000000000000000000000000000..5126caa317ddbfd5c0a4181663bde6cab677cecc
--- /dev/null
+++ b/src/assets/js/notice.min.js
@@ -0,0 +1 @@
+jQuery(document).on("click",".notice-dismiss",function(){var a=jQuery(this).closest("div.notice").data("notice-name");console.log(a);if(""!==a){jQuery.ajax({url:ajaxurl,type:"post",data:{action:"wpdesk_notice_dismiss",notice_name:a},success:function(b){}})}});
\ No newline at end of file
diff --git a/src/init.php b/src/init.php
deleted file mode 100644
index e5bfb47ce1f2b3bf98b4848ef1e734ce9c0266ab..0000000000000000000000000000000000000000
--- a/src/init.php
+++ /dev/null
@@ -1,5 +0,0 @@
-<?php
-
-include './WPDesk/Notice/AjaxHandler.php';
-include './WPDesk/Notice/Notice.php';
-include './WPDesk/Notice/PermanentDismissibleNotice.php';
diff --git a/src/notice-init.php b/src/notice-init.php
new file mode 100644
index 0000000000000000000000000000000000000000..edd7c1b6cba1b040f1f9ddb825af5d16cf492451
--- /dev/null
+++ b/src/notice-init.php
@@ -0,0 +1,7 @@
+<?php
+
+require_once './WPDesk/Notice/AjaxHandler.php';
+require_once './WPDesk/Notice/Notice.php';
+require_once './WPDesk/Notice/PermanentDismissibleNotice.php';
+require_once './WPDesk/Notice/Factory.php';
+require_once './WPDesk/Notice/functions.php';
diff --git a/tests/docker-compose.yaml b/tests/docker-compose.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..fda36347282e33896979c3a0bcc59dd3451393f7
--- /dev/null
+++ b/tests/docker-compose.yaml
@@ -0,0 +1,182 @@
+version: '2.0'
+
+services:
+
+  wordpress:
+    image: wpdesknet/phpunit-woocommerce:0-0
+    volumes:
+    - .././:/opt/project
+    - ../.././:/tmp/plugins
+    depends_on:
+    - mysql0
+    environment:
+      WORDPRESS_DB_NAME: wptest
+      WORDPRESS_DB_USER: mysql
+      WORDPRESS_DB_PASSWORD: mysql
+      WORDPRESS_DB_HOST: mysql0
+
+  wordpress-0-1:
+    image: wpdesknet/phpunit-woocommerce:0-1
+    volumes:
+    - .././:/opt/project
+    - ../.././:/tmp/plugins
+    depends_on:
+    - mysql1
+    environment:
+      WORDPRESS_DB_NAME: wptest
+      WORDPRESS_DB_USER: mysql
+      WORDPRESS_DB_PASSWORD: mysql
+      WORDPRESS_DB_HOST: mysql1
+
+  wordpress-0-2:
+    image: wpdesknet/phpunit-woocommerce:0-2
+    volumes:
+    - .././:/opt/project
+    - ../.././:/tmp/plugins
+    depends_on:
+    - mysql2
+    environment:
+      WORDPRESS_DB_NAME: wptest
+      WORDPRESS_DB_USER: mysql
+      WORDPRESS_DB_PASSWORD: mysql
+      WORDPRESS_DB_HOST: mysql2
+
+  wordpress-0-3:
+    image: wpdesknet/phpunit-woocommerce:0-3
+    volumes:
+    - .././:/opt/project
+    - ../.././:/tmp/plugins
+    depends_on:
+    - mysql3
+    environment:
+      WORDPRESS_DB_NAME: wptest
+      WORDPRESS_DB_USER: mysql
+      WORDPRESS_DB_PASSWORD: mysql
+      WORDPRESS_DB_HOST: mysql3
+
+  wordpress-0-4:
+    image: wpdesknet/phpunit-woocommerce:0-4
+    volumes:
+    - .././:/opt/project
+    - ../.././:/tmp/plugins
+    depends_on:
+    - mysql4
+    environment:
+      WORDPRESS_DB_NAME: wptest
+      WORDPRESS_DB_USER: mysql
+      WORDPRESS_DB_PASSWORD: mysql
+      WORDPRESS_DB_HOST: mysql4
+
+  wordpress-0-5:
+    image: wpdesknet/phpunit-woocommerce:0-5
+    volumes:
+    - .././:/opt/project
+    - ../.././:/tmp/plugins
+    depends_on:
+    - mysql5
+    environment:
+      WORDPRESS_DB_NAME: wptest
+      WORDPRESS_DB_USER: mysql
+      WORDPRESS_DB_PASSWORD: mysql
+      WORDPRESS_DB_HOST: mysql5
+
+  wordpress-1-0:
+    image: wpdesknet/phpunit-woocommerce:1-0
+    volumes:
+    - .././:/opt/project
+    - ../.././:/tmp/plugins
+    depends_on:
+    - mysql0
+    environment:
+      WORDPRESS_DB_NAME: wptest
+      WORDPRESS_DB_USER: mysql
+      WORDPRESS_DB_PASSWORD: mysql
+      WORDPRESS_DB_HOST: mysql0
+
+  wordpress-2-0:
+    image: wpdesknet/phpunit-woocommerce:2-0
+    volumes:
+    - .././:/opt/project
+    - ../.././:/tmp/plugins
+    depends_on:
+    - mysql0
+    environment:
+      WORDPRESS_DB_NAME: wptest
+      WORDPRESS_DB_USER: mysql
+      WORDPRESS_DB_PASSWORD: mysql
+      WORDPRESS_DB_HOST: mysql0
+
+  wordpress-3-0:
+    image: wpdesknet/phpunit-woocommerce:3-0
+    volumes:
+    - .././:/opt/project
+    - ../.././:/tmp/plugins
+    depends_on:
+    - mysql0
+    environment:
+      WORDPRESS_DB_NAME: wptest
+      WORDPRESS_DB_USER: mysql
+      WORDPRESS_DB_PASSWORD: mysql
+      WORDPRESS_DB_HOST: mysql0
+
+  wordpress-4-0:
+    image: wpdesknet/phpunit-woocommerce:4-0
+    volumes:
+    - .././:/opt/project
+    - ../.././:/tmp/plugins
+    depends_on:
+    - mysql0
+    environment:
+      WORDPRESS_DB_NAME: wptest
+      WORDPRESS_DB_USER: mysql
+      WORDPRESS_DB_PASSWORD: mysql
+      WORDPRESS_DB_HOST: mysql0
+
+  mysql0:
+    image: mysql:5.7
+    environment:
+      MYSQL_ROOT_PASSWORD: mysql
+      MYSQL_DATABASE: wptest
+      MYSQL_USER: mysql
+      MYSQL_PASSWORD: mysql
+
+  mysql1:
+    image: mysql:5.7
+    environment:
+      MYSQL_ROOT_PASSWORD: mysql
+      MYSQL_DATABASE: wptest
+      MYSQL_USER: mysql
+      MYSQL_PASSWORD: mysql
+
+  mysql2:
+    image: mysql:5.7
+    environment:
+      MYSQL_ROOT_PASSWORD: mysql
+      MYSQL_DATABASE: wptest
+      MYSQL_USER: mysql
+      MYSQL_PASSWORD: mysql
+
+  mysql3:
+    image: mysql:5.7
+    environment:
+      MYSQL_ROOT_PASSWORD: mysql
+      MYSQL_DATABASE: wptest
+      MYSQL_USER: mysql
+      MYSQL_PASSWORD: mysql
+
+  mysql4:
+    image: mysql:5.7
+    environment:
+      MYSQL_ROOT_PASSWORD: mysql
+      MYSQL_DATABASE: wptest
+      MYSQL_USER: mysql
+      MYSQL_PASSWORD: mysql
+
+  mysql5:
+    image: mysql:5.7
+    environment:
+      MYSQL_ROOT_PASSWORD: mysql
+      MYSQL_DATABASE: wptest
+      MYSQL_USER: mysql
+      MYSQL_PASSWORD: mysql
+
diff --git a/tests/integration/TestFunctions.php b/tests/integration/TestFunctions.php
index 2e054b2deee45de992486308439e2305e28d3939..056d1203539b188954f9e1a1252bf32a4bfda28a 100644
--- a/tests/integration/TestFunctions.php
+++ b/tests/integration/TestFunctions.php
@@ -14,9 +14,69 @@ class TestFunctions extends WP_UnitTestCase
      */
     public function testWPDeskNotice()
     {
-        $notice = wpdesk_notice('test');
+        $notice = wpdesk_notice('test function');
 
         $this->assertInstanceOf(Notice::class, $notice);
+
+        $this->expectOutputString('<div class="notice notice-info"><p>test function</p></div>');
+
+        $notice->showNotice();
+    }
+
+    /**
+     * Test WPDeskNoticeInfo function.
+     */
+    public function testWPDeskNoticeInfo()
+    {
+        $notice = wpdesk_notice_info('test function');
+
+        $this->assertInstanceOf(Notice::class, $notice);
+
+        $this->expectOutputString('<div class="notice notice-info"><p>test function</p></div>');
+
+        $notice->showNotice();
+    }
+
+    /**
+     * Test WPDeskNoticeError function.
+     */
+    public function testWPDeskNoticeError()
+    {
+        $notice = wpdesk_notice_error('test function');
+
+        $this->assertInstanceOf(Notice::class, $notice);
+
+        $this->expectOutputString('<div class="notice notice-error"><p>test function</p></div>');
+
+        $notice->showNotice();
+    }
+
+    /**
+     * Test WPDeskNoticeWarning function.
+     */
+    public function testWPDeskNoticeWarning()
+    {
+        $notice = wpdesk_notice_warning('test function');
+
+        $this->assertInstanceOf(Notice::class, $notice);
+
+        $this->expectOutputString('<div class="notice notice-warning"><p>test function</p></div>');
+
+        $notice->showNotice();
+    }
+
+    /**
+     * Test WPDeskNoticeSuccess function.
+     */
+    public function testWPDeskNoticeSuccess()
+    {
+        $notice = wpdesk_notice_success('test function');
+
+        $this->assertInstanceOf(Notice::class, $notice);
+
+        $this->expectOutputString('<div class="notice notice-success"><p>test function</p></div>');
+
+        $notice->showNotice();
     }
 
     /**
@@ -24,9 +84,19 @@ class TestFunctions extends WP_UnitTestCase
      */
     public function testWPDeskPermanentDismissibleNotice()
     {
-        $notice = wpdesk_permanent_dismissible_notice('test');
+        $notice = wpdesk_permanent_dismissible_notice(
+            'test function',
+            'test-notice',
+            Notice::NOTICE_TYPE_INFO
+        );
 
         $this->assertInstanceOf(PermanentDismissibleNotice::class, $notice);
+
+        $this->expectOutputString(
+            '<div class="notice notice-info is-dismissible" data-notice-name="test-notice" id="wpdesk-notice-test-notice"><p>test function</p></div>'
+        );
+
+        $notice->showNotice();
     }
 
 }
diff --git a/tests/integration/TestNotice.php b/tests/integration/TestNotice.php
index 3cdad40a27110414ffccb6e795931a33584a145d..d4ec8871869f3c340e2da4bdaf7a35aa31ddb318 100644
--- a/tests/integration/TestNotice.php
+++ b/tests/integration/TestNotice.php
@@ -12,6 +12,15 @@ class TestNotice extends WP_UnitTestCase
         $notice = new Notice(Notice::NOTICE_TYPE_INFO, 'test', false, $notice_priority);
 
         $this->assertEquals($notice_priority, has_action('admin_notices', [$notice, 'showNotice'], $notice_priority));
+
+        $this->assertEquals(
+            Notice::ADMIN_FOOTER_BASE_PRIORITY + intval($notice_priority),
+            has_action(
+                'admin_footer',
+                [$notice, 'showNotice'],
+                Notice::ADMIN_FOOTER_BASE_PRIORITY + intval($notice_priority)
+            )
+        );
     }
 
     public function testShowNotice()
@@ -21,6 +30,13 @@ class TestNotice extends WP_UnitTestCase
         $this->expectOutputString('<div class="notice notice-info"><p>test</p></div>');
 
         $notice->showNotice();
+
+        $this->assertFalse(
+            has_action('admin_notices', [$notice, 'showNotice'], 10)
+        );
+        $this->assertFalse(
+            has_action('admin_footer', [$notice, 'showNotice'], 10)
+        );
     }
 
     public function testShowNoticeError()
@@ -102,4 +118,26 @@ class TestNotice extends WP_UnitTestCase
         $this->assertEquals(20, $notice->getPriority());
     }
 
+    public function testAddAttribute()
+    {
+        $notice = new Notice('test', Notice::NOTICE_TYPE_WARNING);
+
+        $notice->addAttribute('id', 'test_id');
+
+        $this->expectOutputString('<div class="notice notice-warning" id="test_id"><p>test</p></div>');
+
+        $notice->showNotice();
+    }
+
+    public function testAddAttributeClass()
+    {
+        $notice = new Notice('test', Notice::NOTICE_TYPE_WARNING);
+
+        $notice->addAttribute('class', 'test-class');
+
+        $this->expectOutputString('<div class="notice notice-warning test-class"><p>test</p></div>');
+
+        $notice->showNotice();
+    }
+
 }
diff --git a/tests/integration/TestPermanentDismissinleNotice.php b/tests/integration/TestPermanentDismissinleNotice.php
index b250b3247070ac2febff20877391bf847639eb53..839352078ddea011ee5bde7cbd16dd556bcfa77a 100644
--- a/tests/integration/TestPermanentDismissinleNotice.php
+++ b/tests/integration/TestPermanentDismissinleNotice.php
@@ -12,9 +12,9 @@ class TestPermanentDismissinleNotice extends WP_UnitTestCase
         $notice_priority = 11;
 
         $notice = new PermanentDismissibleNotice(
-            PermanentDismissibleNotice::NOTICE_TYPE_INFO,
             'test',
             'test_name',
+            PermanentDismissibleNotice::NOTICE_TYPE_INFO,
             $notice_priority
         );
 
@@ -23,11 +23,13 @@ class TestPermanentDismissinleNotice extends WP_UnitTestCase
 
     public function testUndoDismiss()
     {
-        update_option(PermanentDismissibleNotice::OPTION_NAME_PREFIX . self::NOTICE_NAME, PermanentDismissibleNotice::OPTION_VALUE_DISMISSED);
+        update_option(
+            PermanentDismissibleNotice::OPTION_NAME_PREFIX . self::NOTICE_NAME,
+            PermanentDismissibleNotice::OPTION_VALUE_DISMISSED
+        );
 
         $notice = new PermanentDismissibleNotice(
             PermanentDismissibleNotice::NOTICE_TYPE_INFO,
-            'test',
             self::NOTICE_NAME
         );
         $notice->undoDismiss();
@@ -42,12 +44,12 @@ class TestPermanentDismissinleNotice extends WP_UnitTestCase
     {
         $notice = new PermanentDismissibleNotice(
             'test',
-            PermanentDismissibleNotice::NOTICE_TYPE_INFO,
-            'test_name'
+            'test_name',
+            PermanentDismissibleNotice::NOTICE_TYPE_INFO
         );
 
         $this->expectOutputString(
-            '<div class="notice notice-info is-dismissible"data-notice-name="test_name"><p>test</p></div>'
+            '<div class="notice notice-info is-dismissible" data-notice-name="test_name" id="wpdesk-notice-test_name"><p>test</p></div>'
         );
 
         $notice->showNotice();