From fc263eaadd49ea0135c4c34adbf7adaedf9e0f26 Mon Sep 17 00:00:00 2001
From: Bastien DUMONT <bdumont@grandlyon.com>
Date: Tue, 3 Jan 2023 10:57:23 +0100
Subject: [PATCH] fix: improve tolerance of insee code

---
 __tests__/requests/insee.spec.js | 60 +++++++++++++++++++++++++++++---
 src/requests/insee.js            | 36 ++++++++++++++++++-
 2 files changed, 90 insertions(+), 6 deletions(-)

diff --git a/__tests__/requests/insee.spec.js b/__tests__/requests/insee.spec.js
index c8154a3..bc133d1 100644
--- a/__tests__/requests/insee.spec.js
+++ b/__tests__/requests/insee.spec.js
@@ -1,5 +1,6 @@
 const { errors } = require('cozy-konnector-libs')
 const { getInseeCode } = require('../../src/requests/insee')
+
 describe('getInseeCode', () => {
   it('should return a valid insee code for Lyon 7', async () => {
     expect(await getInseeCode(69007)).toEqual('69387')
@@ -21,11 +22,60 @@ describe('getInseeCode', () => {
     }
   })
 
-  it('should return Craponne insee code for post code 69290', async () => {
-    expect(await getInseeCode(69290, 'CRAPONNE')).toEqual('69069')
-  })
+  describe('should handle communes with multiple insee code', () => {
+    it('should return Craponne insee code for post code 69290', async () => {
+      expect(await getInseeCode(69290, 'CRAPONNE')).toEqual('69069')
+    })
+
+    it('should return Pollionnay insee code for post code 69290', async () => {
+      expect(await getInseeCode(69290, 'POLLIONNAY')).toEqual('69154')
+    })
+
+    it('should return insee code for: Saint-bernard', async () => {
+      expect(await getInseeCode('01600', 'SAINT-BERNARD')).toEqual('01339')
+    })
+
+    it('should return insee code for: Neuville sur Saône', async () => {
+      expect(await getInseeCode(69250, 'Neuville sur Saône')).toEqual('69143')
+    })
+    it("should return insee code for: L'isle d'abeau", async () => {
+      expect(await getInseeCode(38080, "L'isle d'abeau")).toEqual('38193')
+    })
+
+    describe("should return correct insee code for Couzon-au-Mont-d'Or", () => {
+      it("should return insee code for: Couzon au mont d'or", async () => {
+        expect(await getInseeCode(69270, "Couzon au mont d'or")).toEqual(
+          '69068'
+        )
+      })
+      it('should return insee code for: Couzon au mont dʼor', async () => {
+        expect(await getInseeCode(69270, 'Couzon au mont dʼor')).toEqual(
+          '69068'
+        )
+      })
+      it("should return insee code for: Couzon-au-mont-d'or", async () => {
+        expect(await getInseeCode(69270, "Couzon-au-mont-d'or")).toEqual(
+          '69068'
+        )
+      })
+      it('should return insee code for: Couzon au mont d or', async () => {
+        expect(await getInseeCode(69270, 'Couzon au mont d or')).toEqual(
+          '69068'
+        )
+      })
+    })
 
-  it('should return Pollionnay insee code for post code 69290', async () => {
-    expect(await getInseeCode(69290, 'POLLIONNAY')).toEqual('69154')
+    describe('should return correct insee code for Fontaines-sur-Saône', () => {
+      it('should return insee code for: Fontaines-sur-Saône', async () => {
+        expect(await getInseeCode(69270, 'Fontaines-sur-Saône')).toEqual(
+          '69088'
+        )
+      })
+      it('should return insee code for: Fontaines-sur-Saone', async () => {
+        expect(await getInseeCode(69270, 'Fontaines-sur-Saone')).toEqual(
+          '69088'
+        )
+      })
+    })
   })
 })
diff --git a/src/requests/insee.js b/src/requests/insee.js
index 442e87f..1652331 100644
--- a/src/requests/insee.js
+++ b/src/requests/insee.js
@@ -21,8 +21,10 @@ async function getInseeCode(postalCode, city) {
     } else {
       if (!city) throw new Error('No city')
 
+      const parsedCity = sanitizeCity(city)
+
       const filteredResponse = response.data.filter(
-        town => town.nomCommune.toLowerCase() === city.toLowerCase()
+        town => sanitizeCity(town.nomCommune) === parsedCity
       )
       return filteredResponse[0].codeCommune
     }
@@ -34,6 +36,38 @@ async function getInseeCode(postalCode, city) {
   }
 }
 
+/**
+ * Clean city input and remove all characters such as (^, ¨, ʼ, ', -, é, è)
+ * @param {string} city
+ * @return {string} parsedCity
+ */
+function sanitizeCity(city) {
+  return city
+    .toLowerCase()
+    .replace(/[âêîôûäëïü-\sʼ'éèç]/g, match => REPLACE_CHARS[match])
+    .trim()
+}
+
+const REPLACE_CHARS = {
+  â: 'a',
+  ê: 'e',
+  î: 'i',
+  ô: 'o',
+  û: 'u',
+  ä: 'a',
+  ë: 'e',
+  ï: 'i',
+  ö: 'o',
+  ü: 'u',
+  '-': '',
+  ' ': '',
+  ʼ: '',
+  "'": '',
+  é: 'e',
+  è: 'e',
+  ç: 'c',
+}
+
 module.exports = {
   getInseeCode,
 }
-- 
GitLab