diff --git a/.gitmodules b/.gitmodules
index 33629ff4e086fcdec5aebc53e1921d7ec6f43fba..00c9ab7233aec51314acd18e80da4bb7fe4ede6c 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,3 @@
 [submodule "library/storm"]
 	path = library/storm
-	url = http://git.afi-sa.fr/afi/storm.git
+	url = git@git.afi-sa.fr:afi/storm.git
diff --git a/library/Class/Profil/Skin.php b/library/Class/Profil/Skin.php
index 062514bb461a2791c12b9d3b00326eb2176f7fd2..5d0dff816f4a42aac33ec3a5b4d8bd5db8b9aeb2 100644
--- a/library/Class/Profil/Skin.php
+++ b/library/Class/Profil/Skin.php
@@ -45,10 +45,15 @@ class Class_Profil_Skin {
 
 
 	public function getPath() {
+		$path = self::EXTRA_PATH . $this->_name . '/';
+		if ($this->fileExists('.' . $path))
+			return $path;
+
 		$path = self::DEFAULT_PATH . $this->_name . '/';
-		if (!$this->fileExists('.' . $path))
-			$path = self::DEFAULT_PATH . self::DEFAULT_SKIN . '/';
-		return $path;
+		if ($this->fileExists('.' . $path))
+			return $path;
+			
+		return self::DEFAULT_PATH . self::DEFAULT_SKIN . '/';
 	}
 
 
@@ -104,20 +109,12 @@ class Class_Profil_Skin {
 
 
 	protected function getAvailablesIn($path) {
-		$file_system = $this->getFileSystem();
-		if (false === ($dirs = @$file_system->scandir($path)))
-			return [];
-
-		$skins = [];
-		foreach ($dirs as $dir)
-			if ($file_system->is_dir($path . $dir) and $dir[0] != '.')
-				$skins[$dir] = $dir;
-		return $skins;
+		return $this->getFileSystem()->directoryNamesAt($path);
 	}
 
 
 	protected function fileExists($path) {
-		return $this->getFileSystem()->file_exists($path);
+		return $this->getFileSystem()->fileExists($path);
 	}
 
 
@@ -130,7 +127,7 @@ class Class_Profil_Skin {
 	protected function getFileSystem() {
 		if (null !== self::$_file_system)
 			return self::$_file_system;
-		return new Class_Testing_FileSystem();
+		return new Storm_FileSystem_Disk();
 	}
 }
 ?>
\ No newline at end of file
diff --git a/library/storm b/library/storm
index e8c97bd32462ece3fa87dc6d828bd77875fc5187..ce4ba4ba1adcae6c4c8c647a7cc6ff4991f5d86d 160000
--- a/library/storm
+++ b/library/storm
@@ -1 +1 @@
-Subproject commit e8c97bd32462ece3fa87dc6d828bd77875fc5187
+Subproject commit ce4ba4ba1adcae6c4c8c647a7cc6ff4991f5d86d
diff --git a/tests/application/modules/admin/controllers/ProfilControllerTest.php b/tests/application/modules/admin/controllers/ProfilControllerTest.php
index 57a4582937b9213a05a2d592818fa4a2acef8b4b..5cbffae450ccb56984e5796067173a4c17fb21c2 100644
--- a/tests/application/modules/admin/controllers/ProfilControllerTest.php
+++ b/tests/application/modules/admin/controllers/ProfilControllerTest.php
@@ -24,34 +24,34 @@ require_once 'AdminAbstractControllerTestCase.php';
 abstract class Admin_ProfilControllerProfilJeunesseTestCase extends Admin_AbstractControllerTestCase {
 	public function setUp() {
 		parent::setUp();
-		$cfg_site = array('header_img' => "/public/jeunesse.png",
-											'header_img_cycle' => true,
-											'liens_sortants_off' => true,
-											'accessibilite_on' => 0,
-											'couleur_texte_bandeau' => '#222',
-											'couleur_lien_bandeau' => '#55F',
-											'access_level' => 3,
-											'favicon' => '/userfiles/favicon.ico',
-											'logo_gauche_img' => '/userfiles/mabib.png',
-											'logo_gauche_link' => 'http://mabib.fr',
-											'logo_droite_img' => '/userfiles/macommune.png',
-											'logo_droite_link' => 'http://macommune.fr',
-											'header_social_network' => true,
-											'division_three_always_visible' => true,
-											'header_css' => '/userfiles/css/my.css',
-											'header_js' => '/userfiles/js/my.js',
-											'ordre_divisions' => 1);
-
-		$cfg_notice = array('exemplaires' => array('grouper' => 1,
-																							 'section' => 1,
-																							 'emplacement' => 0,
-																							 'bib' => 1,
-																							 'annexe' => 0,
-																							 'dispo' => 1,
-																							 'date_retour' => 0,
-																							 'localisation' => 0,
-																							 'plan' => 0,
-																							 'resa' => 2));
+		$cfg_site = ['header_img' => "/public/jeunesse.png",
+								 'header_img_cycle' => true,
+								 'liens_sortants_off' => true,
+								 'accessibilite_on' => 0,
+								 'couleur_texte_bandeau' => '#222',
+								 'couleur_lien_bandeau' => '#55F',
+								 'access_level' => 3,
+								 'favicon' => '/userfiles/favicon.ico',
+								 'logo_gauche_img' => '/userfiles/mabib.png',
+								 'logo_gauche_link' => 'http://mabib.fr',
+								 'logo_droite_img' => '/userfiles/macommune.png',
+								 'logo_droite_link' => 'http://macommune.fr',
+								 'header_social_network' => true,
+								 'division_three_always_visible' => true,
+								 'header_css' => '/userfiles/css/my.css',
+								 'header_js' => '/userfiles/js/my.js',
+								 'ordre_divisions' => 1];
+
+		$cfg_notice = ['exemplaires' => ['grouper' => 1,
+																		 'section' => 1,
+																		 'emplacement' => 0,
+																		 'bib' => 1,
+																		 'annexe' => 0,
+																		 'dispo' => 1,
+																		 'date_retour' => 0,
+																		 'localisation' => 0,
+																		 'plan' => 0,
+																		 'resa' => 2]];
 
 
 		$this->profil_jeunesse = Class_Profil::getLoader()
@@ -83,11 +83,25 @@ class Admin_ProfilControllerEditProfilJeunesseTest extends Admin_ProfilControlle
 	public function setUp() {
 		parent::setUp();
 
-		Class_Profil::setFileWriter(Storm_Test_ObjectWrapper::mock()->whenCalled('fileExists')->answers(true));
+		Class_Profil::setFileWriter(Storm_Test_ObjectWrapper::mock()
+																->whenCalled('fileExists')->answers(true));
+
+		Class_Profil_Skin::setFileSystem(
+			(new Storm_FileSystem_Volatile())
+			->mkdir(Class_Profil_Skin::DEFAULT_PATH . 'original')
+			->mkdir(Class_Profil_Skin::DEFAULT_PATH . 'modele')
+			->mkdir(Class_Profil_Skin::EXTRA_PATH));
+
 		$this->dispatch('/admin/profil/edit/id_profil/5');
 	}
 
 
+	public function tearDown() {
+		Class_Profil_Skin::setFileSystem(null);
+		parent::tearDown();
+	}
+
+
 	/**
 	 * @test
 	 */
diff --git a/tests/application/modules/telephone/controllers/IndexControllerTest.php b/tests/application/modules/telephone/controllers/IndexControllerTest.php
index 658c9bc836af3202a1f0fe9fa296a7afba804800..744205c169059a307e66fa02f07ed4ac0a859c6e 100644
--- a/tests/application/modules/telephone/controllers/IndexControllerTest.php
+++ b/tests/application/modules/telephone/controllers/IndexControllerTest.php
@@ -33,7 +33,6 @@ abstract class AbstractIndexControllerTelephoneWithModulesTest extends Telephone
 	public function setUp() {
 		parent::setUp();
 
-
 		Storm_Test_ObjectWrapper::onLoaderOfModel('Class_Article')
 			->whenCalled('getArticlesByPreferences')
 			->answers([
@@ -43,35 +42,35 @@ abstract class AbstractIndexControllerTelephoneWithModulesTest extends Telephone
 									]);
 
 		$cfg_accueil =
-			array('modules' => array('1' => array('division' => '1',
-																						'type_module' => 'RECH_SIMPLE',
-																						'preferences' => array()),
-
-															 '2' => array('division' => '1',
-																						'type_module' => 'NEWS',
-																						'preferences' => array('titre' => 'Concerts',
-																																	 'rss_avis' => 0)),
-
-															 '3' => array('division' => '1',
-																						'type_module' => 'LOGIN',
-																						'preferences' => array('titre' => 'Se connecter',
-																																	 'identifiant' => 'identifiant',
-																																	 'identifiant_exemple' => 'numero carte',
-																																	 'mot_de_passe' => 'mot de passe',
-																																	 'mot_de_passe_exemple' => 'zork',
-																																	 'lien_connexion' => 'go')),
-															 '4' => array('division' => '1',
-																						'type_module' => 'BIB_NUMERIQUE',
-																						'preferences' => array('titre' => 'Mes albums')),
-
-															 '5' => array('division' => '1',
-																						'type_module' => 'CALENDAR',
-																						'preferences' => array('titre' => 'Agenda')),
-
-															 '6' => array('division' => '1',
-																						'type_module' => 'CRITIQUES',
-																						'preferences' => array('titre' => 'Critiques'))
-															 )); 
+			['modules' => ['1' => ['division' => '1',
+														 'type_module' => 'RECH_SIMPLE',
+														 'preferences' => []],
+										 
+										 '2' => ['division' => '1',
+														 'type_module' => 'NEWS',
+														 'preferences' => ['titre' => 'Concerts',
+																							 'rss_avis' => 0]],
+
+										 '3' => ['division' => '1',
+														 'type_module' => 'LOGIN',
+														 'preferences' => ['titre' => 'Se connecter',
+																							 'identifiant' => 'identifiant',
+																							 'identifiant_exemple' => 'numero carte',
+																							 'mot_de_passe' => 'mot de passe',
+																							 'mot_de_passe_exemple' => 'zork',
+																							 'lien_connexion' => 'go']],
+										 '4' => ['division' => '1',
+														 'type_module' => 'BIB_NUMERIQUE',
+														 'preferences' => ['titre' => 'Mes albums']],
+										 
+										 '5' => ['division' => '1',
+														 'type_module' => 'CALENDAR',
+														 'preferences' => ['titre' => 'Agenda']],
+										 
+										 '6' => ['division' => '1',
+														 'type_module' => 'CRITIQUES',
+														 'preferences' => ['titre' => 'Critiques']]
+					]]; 
 
 		$this->profil_adulte = Class_Profil::getCurrentProfil()
 			->setTitreSite('Smartphone')
@@ -83,12 +82,12 @@ abstract class AbstractIndexControllerTelephoneWithModulesTest extends Telephone
 
 		Storm_Test_ObjectWrapper::onLoaderOfModel("Class_Profil")
 			->whenCalled('findFirstBy')
-			->with(array('BROWSER' => 'telephone'))
+			->with(['BROWSER' => 'telephone'])
 			->answers($this->profil_adulte);
 
-		Class_Profil_Skin::setFileSystem($this->mock()
-																		 ->whenCalled('file_exists')
-																		 ->answers(true));
+		Class_Profil_Skin::setFileSystem((new Storm_FileSystem_Volatile())
+																		 ->mkdir('/public/opac/skins/vide/css/')
+																		 ->touch('/public/opac/skins/vide/css/mobile.css'));
 
 		Class_Profil::setFileWriter(Storm_Test_ObjectWrapper::mock()->whenCalled('fileExists')->answers(true));
 	}
diff --git a/tests/library/Class/Profil/SkinTest.php b/tests/library/Class/Profil/SkinTest.php
index fda99192841194078fe672c936261d124d472e9d..53428720a8f366401adeb009acdafbfc06395c9d 100644
--- a/tests/library/Class/Profil/SkinTest.php
+++ b/tests/library/Class/Profil/SkinTest.php
@@ -22,15 +22,32 @@
 abstract class Class_Profil_SkinTestCase extends Storm_Test_ModelTestCase {
 	protected $_skin;
 	protected $_file_system;
+	protected $_skin_name = 'testing';
 
 	public function setUp() {
 		parent::setUp();
-		$this->_file_system = $this->mock();
+		$this->_file_system = (new Storm_FileSystem_Volatile())
+			->mkdir(Class_Profil_Skin::DEFAULT_PATH)
+			->cd(Class_Profil_Skin::DEFAULT_PATH)
+			->mkdir('afi')
+			->mkdir('original')
+			->mkdir('testing/images')
+			->touch('testing/images/test.png')
+			->mkdir('testing/css')
+			->touch('testing/css/testing.css')
+
+			->mkdir('/public/opac/images')
+			->touch('/public/opac/images/test.png')
+
+			->mkdir(Class_Profil_Skin::EXTRA_PATH . 'my-skin')
+			->cd('/');
+
+
 		Class_Profil_Skin::setFileSystem($this->_file_system);
 
 		$this->_skin = Class_Profil_Skin::newFor($this->fixture('Class_Profil', 
 																														['id' => 3,
-																														 'skin' => 'testing']));
+																														 'skin' => $this->_skin_name]));
 	}
 
 
@@ -41,26 +58,18 @@ abstract class Class_Profil_SkinTestCase extends Storm_Test_ModelTestCase {
 }
 
 
+class Class_Profil_SkinExtraTest extends Class_Profil_SkinTestCase {
+	protected $_skin_name = 'my-skin';
 
-class Class_Profil_SkinExistTest extends Class_Profil_SkinTestCase {
-	public function setUp() {
-		parent::setUp();
-		$this->_file_system
-			->whenCalled('file_exists')
-			->answers(true)
-
-			->whenCalled('scandir')
-			->with('.' . Class_Profil_Skin::DEFAULT_PATH)
-			->answers(['.', '..', 'afi', 'original', 'testing'])
-
-			->whenCalled('scandir')
-			->with('.' . Class_Profil_Skin::EXTRA_PATH)
-			->answers(['.', '..', 'my-skin'])
-
-			->whenCalled('is_dir')->answers(true);
+	/** @test */
+	public function pathShouldContainsMySkin() {
+		$this->assertContains($this->_skin_name, $this->_skin->getPath());
 	}
+}
 
 
+
+class Class_Profil_SkinExistTest extends Class_Profil_SkinTestCase {
 	/** @test */
 	public function pathShouldContainsTesting() {
 		$this->assertContains('testing/', $this->_skin->getPath());
@@ -90,11 +99,7 @@ class Class_Profil_SkinExistTest extends Class_Profil_SkinTestCase {
 
 	/** @test */
 	public function imageUrlNotExistingShouldContainsShared() {
-		$this->_file_system
-			->whenCalled('file_exists')
-			->with('./public/opac/skins/testing/images/test.png')
-			->answers(false);
-
+		$this->_file_system->rm(Class_Profil_Skin::DEFAULT_PATH.'testing/images/test.png');
 		$this->assertContains('public/opac/images/test.png', 
 													$this->_skin->getImageUrl('test.png'));
 	}
@@ -133,12 +138,7 @@ class Class_Profil_SkinTelephoneTest extends Class_Profil_SkinTestCase {
 
 
 class Class_Profil_SkinNotExistsTest extends Class_Profil_SkinTestCase {
-	public function setUp() {
-		parent::setUp();
-		$this->_file_system
-			->whenCalled('file_exists')
-			->answers(false);
-	}
+	protected $_skin_name = 'unknown';
 
 
 	/** @test */