mirror of
				https://gitlab.nic.cz/turris/reforis/foris-js.git
				synced 2025-11-03 23:00:31 +01:00 
			
		
		
		
	Merge branch 'dev' into 'master'
Release 3.1.0 See merge request turris/reforis/foris-js!72
This commit is contained in:
		
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@@ -46,6 +46,8 @@ publish-latest: collect-files
 | 
			
		||||
 | 
			
		||||
lint:
 | 
			
		||||
	npm run lint
 | 
			
		||||
lint-js-fix:
 | 
			
		||||
	npm run lint:fix
 | 
			
		||||
 | 
			
		||||
test:
 | 
			
		||||
	npm test
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ module.exports = {
 | 
			
		||||
    clearMocks: true,
 | 
			
		||||
    collectCoverageFrom: ["src/**/*.{js,jsx}"],
 | 
			
		||||
    coverageDirectory: "coverage",
 | 
			
		||||
    testPathIgnorePatterns: ["/node_modules/", "/__fixtures__/"],
 | 
			
		||||
    testPathIgnorePatterns: ["/node_modules/", "/__fixtures__/", "/dist/"],
 | 
			
		||||
    verbose: false,
 | 
			
		||||
    setupFilesAfterEnv: [
 | 
			
		||||
        "@testing-library/react/cleanup-after-each",
 | 
			
		||||
@@ -28,4 +28,7 @@ module.exports = {
 | 
			
		||||
        "^.+\\.js$": "babel-jest",
 | 
			
		||||
        "^.+\\.css$": "jest-transform-css",
 | 
			
		||||
    },
 | 
			
		||||
    transformIgnorePatterns: [
 | 
			
		||||
        "node_modules/(?!(react-datetime)/)",
 | 
			
		||||
    ],
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										704
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										704
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "foris",
 | 
			
		||||
  "version": "3.0.0",
 | 
			
		||||
  "version": "3.1.0",
 | 
			
		||||
  "lockfileVersion": 1,
 | 
			
		||||
  "requires": true,
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
@@ -1674,6 +1674,31 @@
 | 
			
		||||
      "integrity": "sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "acorn-node": {
 | 
			
		||||
      "version": "1.8.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz",
 | 
			
		||||
      "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "acorn": "^7.0.0",
 | 
			
		||||
        "acorn-walk": "^7.0.0",
 | 
			
		||||
        "xtend": "^4.0.2"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "acorn": {
 | 
			
		||||
          "version": "7.1.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz",
 | 
			
		||||
          "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==",
 | 
			
		||||
          "dev": true
 | 
			
		||||
        },
 | 
			
		||||
        "acorn-walk": {
 | 
			
		||||
          "version": "7.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.0.0.tgz",
 | 
			
		||||
          "integrity": "sha512-7Bv1We7ZGuU79zZbb6rRqcpxo3OY+zrdtloZWoyD8fmGX+FeXRjE+iuGkZjSXLVovLzrsvMGMy0EkwA0E0umxg==",
 | 
			
		||||
          "dev": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "acorn-walk": {
 | 
			
		||||
      "version": "6.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-6.2.0.tgz",
 | 
			
		||||
@@ -1720,6 +1745,13 @@
 | 
			
		||||
      "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "amdefine": {
 | 
			
		||||
      "version": "1.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
 | 
			
		||||
      "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "optional": true
 | 
			
		||||
    },
 | 
			
		||||
    "ansi-colors": {
 | 
			
		||||
      "version": "3.2.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz",
 | 
			
		||||
@@ -1827,6 +1859,12 @@
 | 
			
		||||
      "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "array-from": {
 | 
			
		||||
      "version": "2.1.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz",
 | 
			
		||||
      "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "array-includes": {
 | 
			
		||||
      "version": "3.0.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz",
 | 
			
		||||
@@ -1928,6 +1966,59 @@
 | 
			
		||||
      "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "ast-transform": {
 | 
			
		||||
      "version": "0.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/ast-transform/-/ast-transform-0.0.0.tgz",
 | 
			
		||||
      "integrity": "sha1-dJRAWIh9goPhidlUYAlHvJj+AGI=",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "escodegen": "~1.2.0",
 | 
			
		||||
        "esprima": "~1.0.4",
 | 
			
		||||
        "through": "~2.3.4"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "escodegen": {
 | 
			
		||||
          "version": "1.2.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.2.0.tgz",
 | 
			
		||||
          "integrity": "sha1-Cd55Z3kcyVi3+Jot220jRRrzJ+E=",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "esprima": "~1.0.4",
 | 
			
		||||
            "estraverse": "~1.5.0",
 | 
			
		||||
            "esutils": "~1.0.0",
 | 
			
		||||
            "source-map": "~0.1.30"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "esprima": {
 | 
			
		||||
          "version": "1.0.4",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz",
 | 
			
		||||
          "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=",
 | 
			
		||||
          "dev": true
 | 
			
		||||
        },
 | 
			
		||||
        "estraverse": {
 | 
			
		||||
          "version": "1.5.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.5.1.tgz",
 | 
			
		||||
          "integrity": "sha1-hno+jlip+EYYr7bC3bzZFrfLr3E=",
 | 
			
		||||
          "dev": true
 | 
			
		||||
        },
 | 
			
		||||
        "esutils": {
 | 
			
		||||
          "version": "1.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.0.0.tgz",
 | 
			
		||||
          "integrity": "sha1-gVHTWOIMisx/t0XnRywAJf5JZXA=",
 | 
			
		||||
          "dev": true
 | 
			
		||||
        },
 | 
			
		||||
        "source-map": {
 | 
			
		||||
          "version": "0.1.43",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz",
 | 
			
		||||
          "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "amdefine": ">=0.0.4"
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "ast-types": {
 | 
			
		||||
      "version": "0.13.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.2.tgz",
 | 
			
		||||
@@ -2440,12 +2531,33 @@
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "brfs": {
 | 
			
		||||
      "version": "2.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/brfs/-/brfs-2.0.2.tgz",
 | 
			
		||||
      "integrity": "sha512-IrFjVtwu4eTJZyu8w/V2gxU7iLTtcHih67sgEdzrhjLBMHp2uYefUBfdM4k2UvcuWMgV7PQDZHSLeNWnLFKWVQ==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "quote-stream": "^1.0.1",
 | 
			
		||||
        "resolve": "^1.1.5",
 | 
			
		||||
        "static-module": "^3.0.2",
 | 
			
		||||
        "through2": "^2.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "brorand": {
 | 
			
		||||
      "version": "1.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
 | 
			
		||||
      "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "brotli": {
 | 
			
		||||
      "version": "1.3.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.2.tgz",
 | 
			
		||||
      "integrity": "sha1-UlqcrU/LqWR119OI9q7LE+7VL0Y=",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "base64-js": "^1.1.2"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "browser-process-hrtime": {
 | 
			
		||||
      "version": "0.1.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz",
 | 
			
		||||
@@ -2506,6 +2618,25 @@
 | 
			
		||||
        "safe-buffer": "^5.1.2"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "browserify-optional": {
 | 
			
		||||
      "version": "1.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/browserify-optional/-/browserify-optional-1.0.1.tgz",
 | 
			
		||||
      "integrity": "sha1-HhNyLP3g2F8SFnbCpyztUzoBiGk=",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "ast-transform": "0.0.0",
 | 
			
		||||
        "ast-types": "^0.7.0",
 | 
			
		||||
        "browser-resolve": "^1.8.1"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "ast-types": {
 | 
			
		||||
          "version": "0.7.8",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.7.8.tgz",
 | 
			
		||||
          "integrity": "sha1-kC0uDWDQcb3NRtwRXhgJ7RHBOKk=",
 | 
			
		||||
          "dev": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "browserify-rsa": {
 | 
			
		||||
      "version": "4.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
 | 
			
		||||
@@ -2603,6 +2734,12 @@
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "buffer-equal": {
 | 
			
		||||
      "version": "0.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz",
 | 
			
		||||
      "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "buffer-from": {
 | 
			
		||||
      "version": "1.1.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
 | 
			
		||||
@@ -3313,6 +3450,12 @@
 | 
			
		||||
        "randomfill": "^1.0.3"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "crypto-js": {
 | 
			
		||||
      "version": "3.1.9-1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz",
 | 
			
		||||
      "integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg=",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "css-initials": {
 | 
			
		||||
      "version": "0.3.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/css-initials/-/css-initials-0.3.1.tgz",
 | 
			
		||||
@@ -3539,6 +3682,16 @@
 | 
			
		||||
      "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "d": {
 | 
			
		||||
      "version": "1.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
 | 
			
		||||
      "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "es5-ext": "^0.10.50",
 | 
			
		||||
        "type": "^1.0.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "damerau-levenshtein": {
 | 
			
		||||
      "version": "1.0.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.5.tgz",
 | 
			
		||||
@@ -3805,6 +3958,12 @@
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "dfa": {
 | 
			
		||||
      "version": "1.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz",
 | 
			
		||||
      "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "diff-sequences": {
 | 
			
		||||
      "version": "24.9.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz",
 | 
			
		||||
@@ -3886,6 +4045,15 @@
 | 
			
		||||
      "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "duplexer2": {
 | 
			
		||||
      "version": "0.1.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
 | 
			
		||||
      "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "readable-stream": "^2.0.2"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "duplexify": {
 | 
			
		||||
      "version": "3.7.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
 | 
			
		||||
@@ -4022,6 +4190,42 @@
 | 
			
		||||
        "is-symbol": "^1.0.2"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "es5-ext": {
 | 
			
		||||
      "version": "0.10.53",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz",
 | 
			
		||||
      "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "es6-iterator": "~2.0.3",
 | 
			
		||||
        "es6-symbol": "~3.1.3",
 | 
			
		||||
        "next-tick": "~1.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "es6-iterator": {
 | 
			
		||||
      "version": "2.0.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
 | 
			
		||||
      "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "d": "1",
 | 
			
		||||
        "es5-ext": "^0.10.35",
 | 
			
		||||
        "es6-symbol": "^3.1.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "es6-map": {
 | 
			
		||||
      "version": "0.1.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz",
 | 
			
		||||
      "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "d": "1",
 | 
			
		||||
        "es5-ext": "~0.10.14",
 | 
			
		||||
        "es6-iterator": "~2.0.1",
 | 
			
		||||
        "es6-set": "~0.1.5",
 | 
			
		||||
        "es6-symbol": "~3.1.1",
 | 
			
		||||
        "event-emitter": "~0.3.5"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "es6-object-assign": {
 | 
			
		||||
      "version": "1.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz",
 | 
			
		||||
@@ -4034,6 +4238,41 @@
 | 
			
		||||
      "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "es6-set": {
 | 
			
		||||
      "version": "0.1.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz",
 | 
			
		||||
      "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "d": "1",
 | 
			
		||||
        "es5-ext": "~0.10.14",
 | 
			
		||||
        "es6-iterator": "~2.0.1",
 | 
			
		||||
        "es6-symbol": "3.1.1",
 | 
			
		||||
        "event-emitter": "~0.3.5"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "es6-symbol": {
 | 
			
		||||
          "version": "3.1.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
 | 
			
		||||
          "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "d": "1",
 | 
			
		||||
            "es5-ext": "~0.10.14"
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "es6-symbol": {
 | 
			
		||||
      "version": "3.1.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
 | 
			
		||||
      "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "d": "^1.0.1",
 | 
			
		||||
        "ext": "^1.1.2"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "escape-html": {
 | 
			
		||||
      "version": "1.0.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
 | 
			
		||||
@@ -4569,6 +4808,12 @@
 | 
			
		||||
      "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "estree-is-function": {
 | 
			
		||||
      "version": "1.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/estree-is-function/-/estree-is-function-1.0.0.tgz",
 | 
			
		||||
      "integrity": "sha512-nSCWn1jkSq2QAtkaVLJZY2ezwcFO161HVc174zL1KPW3RJ+O6C3eJb8Nx7OXzvhoEv+nLgSR1g71oWUHUDTrJA==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "estree-walker": {
 | 
			
		||||
      "version": "0.9.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.9.0.tgz",
 | 
			
		||||
@@ -4587,6 +4832,16 @@
 | 
			
		||||
      "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "event-emitter": {
 | 
			
		||||
      "version": "0.3.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
 | 
			
		||||
      "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "d": "1",
 | 
			
		||||
        "es5-ext": "~0.10.14"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "eventemitter3": {
 | 
			
		||||
      "version": "4.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz",
 | 
			
		||||
@@ -4770,6 +5025,23 @@
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "ext": {
 | 
			
		||||
      "version": "1.4.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz",
 | 
			
		||||
      "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "type": "^2.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "type": {
 | 
			
		||||
          "version": "2.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz",
 | 
			
		||||
          "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==",
 | 
			
		||||
          "dev": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "extend": {
 | 
			
		||||
      "version": "3.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
 | 
			
		||||
@@ -4879,6 +5151,26 @@
 | 
			
		||||
      "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "falafel": {
 | 
			
		||||
      "version": "2.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.1.0.tgz",
 | 
			
		||||
      "integrity": "sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw=",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "acorn": "^5.0.0",
 | 
			
		||||
        "foreach": "^2.0.5",
 | 
			
		||||
        "isarray": "0.0.1",
 | 
			
		||||
        "object-keys": "^1.0.6"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "acorn": {
 | 
			
		||||
          "version": "5.7.3",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
 | 
			
		||||
          "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==",
 | 
			
		||||
          "dev": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "fast-deep-equal": {
 | 
			
		||||
      "version": "2.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
 | 
			
		||||
@@ -5140,12 +5432,130 @@
 | 
			
		||||
        "debug": "=3.1.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "fontkit": {
 | 
			
		||||
      "version": "1.8.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-1.8.0.tgz",
 | 
			
		||||
      "integrity": "sha512-EFDRCca7khfQWYu1iFhsqeABpi87f03MBdkT93ZE6YhqCdMzb5Eojb6c4dlJikGv5liuhByyzA7ikpIPTSBWbQ==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "babel-runtime": "^6.11.6",
 | 
			
		||||
        "brfs": "^1.4.0",
 | 
			
		||||
        "brotli": "^1.2.0",
 | 
			
		||||
        "browserify-optional": "^1.0.0",
 | 
			
		||||
        "clone": "^1.0.1",
 | 
			
		||||
        "deep-equal": "^1.0.0",
 | 
			
		||||
        "dfa": "^1.0.0",
 | 
			
		||||
        "restructure": "^0.5.3",
 | 
			
		||||
        "tiny-inflate": "^1.0.2",
 | 
			
		||||
        "unicode-properties": "^1.0.0",
 | 
			
		||||
        "unicode-trie": "^0.3.0"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "brfs": {
 | 
			
		||||
          "version": "1.6.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/brfs/-/brfs-1.6.1.tgz",
 | 
			
		||||
          "integrity": "sha512-OfZpABRQQf+Xsmju8XE9bDjs+uU4vLREGolP7bDgcpsI17QREyZ4Bl+2KLxxx1kCgA0fAIhKQBaBYh+PEcCqYQ==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "quote-stream": "^1.0.1",
 | 
			
		||||
            "resolve": "^1.1.5",
 | 
			
		||||
            "static-module": "^2.2.0",
 | 
			
		||||
            "through2": "^2.0.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "escodegen": {
 | 
			
		||||
          "version": "1.9.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.1.tgz",
 | 
			
		||||
          "integrity": "sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "esprima": "^3.1.3",
 | 
			
		||||
            "estraverse": "^4.2.0",
 | 
			
		||||
            "esutils": "^2.0.2",
 | 
			
		||||
            "optionator": "^0.8.1",
 | 
			
		||||
            "source-map": "~0.6.1"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "esprima": {
 | 
			
		||||
          "version": "3.1.3",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
 | 
			
		||||
          "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=",
 | 
			
		||||
          "dev": true
 | 
			
		||||
        },
 | 
			
		||||
        "magic-string": {
 | 
			
		||||
          "version": "0.22.5",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz",
 | 
			
		||||
          "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "vlq": "^0.2.2"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "object-inspect": {
 | 
			
		||||
          "version": "1.4.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.4.1.tgz",
 | 
			
		||||
          "integrity": "sha512-wqdhLpfCUbEsoEwl3FXwGyv8ief1k/1aUdIPCqVnupM6e8l63BEJdiF/0swtn04/8p05tG/T0FrpTlfwvljOdw==",
 | 
			
		||||
          "dev": true
 | 
			
		||||
        },
 | 
			
		||||
        "pako": {
 | 
			
		||||
          "version": "0.2.9",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
 | 
			
		||||
          "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=",
 | 
			
		||||
          "dev": true
 | 
			
		||||
        },
 | 
			
		||||
        "source-map": {
 | 
			
		||||
          "version": "0.6.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
 | 
			
		||||
          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "static-module": {
 | 
			
		||||
          "version": "2.2.5",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/static-module/-/static-module-2.2.5.tgz",
 | 
			
		||||
          "integrity": "sha512-D8vv82E/Kpmz3TXHKG8PPsCPg+RAX6cbCOyvjM6x04qZtQ47EtJFVwRsdov3n5d6/6ynrOY9XB4JkaZwB2xoRQ==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "concat-stream": "~1.6.0",
 | 
			
		||||
            "convert-source-map": "^1.5.1",
 | 
			
		||||
            "duplexer2": "~0.1.4",
 | 
			
		||||
            "escodegen": "~1.9.0",
 | 
			
		||||
            "falafel": "^2.1.0",
 | 
			
		||||
            "has": "^1.0.1",
 | 
			
		||||
            "magic-string": "^0.22.4",
 | 
			
		||||
            "merge-source-map": "1.0.4",
 | 
			
		||||
            "object-inspect": "~1.4.0",
 | 
			
		||||
            "quote-stream": "~1.0.2",
 | 
			
		||||
            "readable-stream": "~2.3.3",
 | 
			
		||||
            "shallow-copy": "~0.0.1",
 | 
			
		||||
            "static-eval": "^2.0.0",
 | 
			
		||||
            "through2": "~2.0.3"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "unicode-trie": {
 | 
			
		||||
          "version": "0.3.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-0.3.1.tgz",
 | 
			
		||||
          "integrity": "sha1-1nHd3YkQGgi6w3tqUWEBBgIFIIU=",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "pako": "^0.2.5",
 | 
			
		||||
            "tiny-inflate": "^1.0.0"
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "for-in": {
 | 
			
		||||
      "version": "1.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
 | 
			
		||||
      "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "foreach": {
 | 
			
		||||
      "version": "2.0.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
 | 
			
		||||
      "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "forever-agent": {
 | 
			
		||||
      "version": "0.6.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
 | 
			
		||||
@@ -5840,6 +6250,12 @@
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "get-assigned-identifiers": {
 | 
			
		||||
      "version": "1.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz",
 | 
			
		||||
      "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "get-caller-file": {
 | 
			
		||||
      "version": "2.0.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
 | 
			
		||||
@@ -7751,6 +8167,25 @@
 | 
			
		||||
        "type-check": "~0.3.2"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "linebreak": {
 | 
			
		||||
      "version": "1.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.0.2.tgz",
 | 
			
		||||
      "integrity": "sha512-bJwSRsJeAmaZYnkcwl5sCQNfSDAhBuXxb6L27tb+qkBRtUQSSTUa5bcgCPD6hFEkRNlpWHfK7nFMmcANU7ZP1w==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "base64-js": "0.0.8",
 | 
			
		||||
        "brfs": "^2.0.2",
 | 
			
		||||
        "unicode-trie": "^1.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "base64-js": {
 | 
			
		||||
          "version": "0.0.8",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
 | 
			
		||||
          "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=",
 | 
			
		||||
          "dev": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "listify": {
 | 
			
		||||
      "version": "1.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/listify/-/listify-1.0.0.tgz",
 | 
			
		||||
@@ -8034,6 +8469,15 @@
 | 
			
		||||
      "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "merge-source-map": {
 | 
			
		||||
      "version": "1.0.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.0.4.tgz",
 | 
			
		||||
      "integrity": "sha1-pd5GU42uhNQRTMXqArR3KmNGcB8=",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "source-map": "^0.5.6"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "merge-stream": {
 | 
			
		||||
      "version": "2.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
 | 
			
		||||
@@ -8358,6 +8802,12 @@
 | 
			
		||||
      "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "next-tick": {
 | 
			
		||||
      "version": "1.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
 | 
			
		||||
      "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "nice-try": {
 | 
			
		||||
      "version": "1.0.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
 | 
			
		||||
@@ -9146,6 +9596,41 @@
 | 
			
		||||
        "sha.js": "^2.4.8"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "pdfkit": {
 | 
			
		||||
      "version": "0.11.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/pdfkit/-/pdfkit-0.11.0.tgz",
 | 
			
		||||
      "integrity": "sha512-1s9gaumXkYxcVF1iRtSmLiISF2r4nHtsTgpwXiK8Swe+xwk/1pm8FJjYqN7L3x13NsWnGyUFntWcO8vfqq+wwA==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "crypto-js": "^3.1.9-1",
 | 
			
		||||
        "fontkit": "^1.8.0",
 | 
			
		||||
        "linebreak": "^1.0.2",
 | 
			
		||||
        "png-js": "^1.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "pdfmake": {
 | 
			
		||||
      "version": "0.1.63",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/pdfmake/-/pdfmake-0.1.63.tgz",
 | 
			
		||||
      "integrity": "sha512-TjchyLVDzaEmtaDNUrceNrm0QvNIFERYOeDwHwMUQ1twGy68Uhjd1MKsb9DGAh8SuB8MCWQXB7m4k7cUevLjoA==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "iconv-lite": "^0.5.0",
 | 
			
		||||
        "linebreak": "^1.0.2",
 | 
			
		||||
        "pdfkit": "^0.11.0",
 | 
			
		||||
        "svg-to-pdfkit": "^0.1.8"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "iconv-lite": {
 | 
			
		||||
          "version": "0.5.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.0.tgz",
 | 
			
		||||
          "integrity": "sha512-NnEhI9hIEKHOzJ4f697DMz9IQEXr/MMJ5w64vN2/4Ai+wRnvV7SBrL0KLoRlwaKVghOc7LQ5YkPLuX146b6Ydw==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "safer-buffer": ">= 2.1.2 < 3"
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "performance-now": {
 | 
			
		||||
      "version": "2.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
 | 
			
		||||
@@ -9251,6 +9736,12 @@
 | 
			
		||||
      "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "png-js": {
 | 
			
		||||
      "version": "1.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz",
 | 
			
		||||
      "integrity": "sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "portfinder": {
 | 
			
		||||
      "version": "1.0.25",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz",
 | 
			
		||||
@@ -9573,6 +10064,22 @@
 | 
			
		||||
        "stringify-object": "^3.2.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "qr.js": {
 | 
			
		||||
      "version": "0.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz",
 | 
			
		||||
      "integrity": "sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8=",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "qrcode.react": {
 | 
			
		||||
      "version": "0.9.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-0.9.3.tgz",
 | 
			
		||||
      "integrity": "sha512-gGd30Ez7cmrKxyN2M3nueaNLk/f9J7NDRgaD5fVgxGpPLsYGWMn9UQ+XnDpv95cfszTQTdaf4QGLNMf3xU0hmw==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "prop-types": "^15.6.0",
 | 
			
		||||
        "qr.js": "0.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "qs": {
 | 
			
		||||
      "version": "6.5.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
 | 
			
		||||
@@ -9603,6 +10110,25 @@
 | 
			
		||||
      "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "quote-stream": {
 | 
			
		||||
      "version": "1.0.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-1.0.2.tgz",
 | 
			
		||||
      "integrity": "sha1-hJY/jJwmuULhU/7rU6rnRlK34LI=",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "buffer-equal": "0.0.1",
 | 
			
		||||
        "minimist": "^1.1.3",
 | 
			
		||||
        "through2": "^2.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "minimist": {
 | 
			
		||||
          "version": "1.2.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
 | 
			
		||||
          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
 | 
			
		||||
          "dev": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "randombytes": {
 | 
			
		||||
      "version": "2.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
 | 
			
		||||
@@ -10700,6 +11226,15 @@
 | 
			
		||||
        "signal-exit": "^3.0.2"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "restructure": {
 | 
			
		||||
      "version": "0.5.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/restructure/-/restructure-0.5.4.tgz",
 | 
			
		||||
      "integrity": "sha1-9U591WNZD7NP1r9Vh2EJrsyyjeg=",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "browserify-optional": "^1.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "ret": {
 | 
			
		||||
      "version": "0.1.15",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
 | 
			
		||||
@@ -10836,6 +11371,20 @@
 | 
			
		||||
        "ajv-keywords": "^3.1.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "scope-analyzer": {
 | 
			
		||||
      "version": "2.0.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/scope-analyzer/-/scope-analyzer-2.0.5.tgz",
 | 
			
		||||
      "integrity": "sha512-+U5H0417mnTEstCD5VwOYO7V4vYuSqwqjFap40ythe67bhMFL5C3UgPwyBv7KDJsqUBIKafOD57xMlh1rN7eaw==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "array-from": "^2.1.1",
 | 
			
		||||
        "es6-map": "^0.1.5",
 | 
			
		||||
        "es6-set": "^0.1.5",
 | 
			
		||||
        "es6-symbol": "^3.1.1",
 | 
			
		||||
        "estree-is-function": "^1.0.0",
 | 
			
		||||
        "get-assigned-identifiers": "^1.1.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "select": {
 | 
			
		||||
      "version": "1.1.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
 | 
			
		||||
@@ -11027,6 +11576,12 @@
 | 
			
		||||
        "safe-buffer": "^5.0.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "shallow-copy": {
 | 
			
		||||
      "version": "0.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz",
 | 
			
		||||
      "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "shebang-command": {
 | 
			
		||||
      "version": "1.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
 | 
			
		||||
@@ -11494,6 +12049,15 @@
 | 
			
		||||
      "integrity": "sha512-8LpelPGR0qQM4PnfLiplOQNJcIN1/r2Gy0xKB2zKnIW2YzPMt2sR4I/+gtPjhN7Svh9kw+zqEg2SFwpBO9iNiw==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "static-eval": {
 | 
			
		||||
      "version": "2.0.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.3.tgz",
 | 
			
		||||
      "integrity": "sha512-zsxDGucfAh8T339sSKgpFbvg15Fms2IVaJGC+jqp0bVsxhcpM+iMeAI8weNo8dmf4OblgifTBUoyk1vGVtYw2w==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "escodegen": "^1.11.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "static-extend": {
 | 
			
		||||
      "version": "0.1.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
 | 
			
		||||
@@ -11515,6 +12079,71 @@
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "static-module": {
 | 
			
		||||
      "version": "3.0.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/static-module/-/static-module-3.0.3.tgz",
 | 
			
		||||
      "integrity": "sha512-RDaMYaI5o/ym0GkCqL/PlD1Pn216omp8fY81okxZ6f6JQxWW5tptOw9reXoZX85yt/scYvbWIt6uoszeyf+/MQ==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "acorn-node": "^1.3.0",
 | 
			
		||||
        "concat-stream": "~1.6.0",
 | 
			
		||||
        "convert-source-map": "^1.5.1",
 | 
			
		||||
        "duplexer2": "~0.1.4",
 | 
			
		||||
        "escodegen": "~1.9.0",
 | 
			
		||||
        "has": "^1.0.1",
 | 
			
		||||
        "magic-string": "^0.22.4",
 | 
			
		||||
        "merge-source-map": "1.0.4",
 | 
			
		||||
        "object-inspect": "~1.4.0",
 | 
			
		||||
        "readable-stream": "~2.3.3",
 | 
			
		||||
        "scope-analyzer": "^2.0.1",
 | 
			
		||||
        "shallow-copy": "~0.0.1",
 | 
			
		||||
        "static-eval": "^2.0.2",
 | 
			
		||||
        "through2": "~2.0.3"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "escodegen": {
 | 
			
		||||
          "version": "1.9.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.1.tgz",
 | 
			
		||||
          "integrity": "sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "esprima": "^3.1.3",
 | 
			
		||||
            "estraverse": "^4.2.0",
 | 
			
		||||
            "esutils": "^2.0.2",
 | 
			
		||||
            "optionator": "^0.8.1",
 | 
			
		||||
            "source-map": "~0.6.1"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "esprima": {
 | 
			
		||||
          "version": "3.1.3",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
 | 
			
		||||
          "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=",
 | 
			
		||||
          "dev": true
 | 
			
		||||
        },
 | 
			
		||||
        "magic-string": {
 | 
			
		||||
          "version": "0.22.5",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz",
 | 
			
		||||
          "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "vlq": "^0.2.2"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "object-inspect": {
 | 
			
		||||
          "version": "1.4.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.4.1.tgz",
 | 
			
		||||
          "integrity": "sha512-wqdhLpfCUbEsoEwl3FXwGyv8ief1k/1aUdIPCqVnupM6e8l63BEJdiF/0swtn04/8p05tG/T0FrpTlfwvljOdw==",
 | 
			
		||||
          "dev": true
 | 
			
		||||
        },
 | 
			
		||||
        "source-map": {
 | 
			
		||||
          "version": "0.6.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
 | 
			
		||||
          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "statuses": {
 | 
			
		||||
      "version": "1.5.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
 | 
			
		||||
@@ -11720,6 +12349,15 @@
 | 
			
		||||
        "has-flag": "^3.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "svg-to-pdfkit": {
 | 
			
		||||
      "version": "0.1.8",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/svg-to-pdfkit/-/svg-to-pdfkit-0.1.8.tgz",
 | 
			
		||||
      "integrity": "sha512-QItiGZBy5TstGy+q8mjQTMGRlDDOARXLxH+sgVm1n/LYeo0zFcQlcCh8m4zi8QxctrxB9Kue/lStc/RD5iLadQ==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "pdfkit": ">=0.8.1"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "symbol-tree": {
 | 
			
		||||
      "version": "3.2.4",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
 | 
			
		||||
@@ -11884,6 +12522,12 @@
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "optional": true
 | 
			
		||||
    },
 | 
			
		||||
    "tiny-inflate": {
 | 
			
		||||
      "version": "1.0.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
 | 
			
		||||
      "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "tiny-invariant": {
 | 
			
		||||
      "version": "1.0.6",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.0.6.tgz",
 | 
			
		||||
@@ -12069,6 +12713,12 @@
 | 
			
		||||
      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "type": {
 | 
			
		||||
      "version": "1.2.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
 | 
			
		||||
      "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "type-check": {
 | 
			
		||||
      "version": "0.3.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
 | 
			
		||||
@@ -12164,12 +12814,58 @@
 | 
			
		||||
      "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "unicode-properties": {
 | 
			
		||||
      "version": "1.3.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.3.1.tgz",
 | 
			
		||||
      "integrity": "sha512-nIV3Tf3LcUEZttY/2g4ZJtGXhWwSkuLL+rCu0DIAMbjyVPj+8j5gNVz4T/sVbnQybIsd5SFGkPKg/756OY6jlA==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "base64-js": "^1.3.0",
 | 
			
		||||
        "unicode-trie": "^2.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "pako": {
 | 
			
		||||
          "version": "0.2.9",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
 | 
			
		||||
          "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=",
 | 
			
		||||
          "dev": true
 | 
			
		||||
        },
 | 
			
		||||
        "unicode-trie": {
 | 
			
		||||
          "version": "2.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz",
 | 
			
		||||
          "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "pako": "^0.2.5",
 | 
			
		||||
            "tiny-inflate": "^1.0.0"
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "unicode-property-aliases-ecmascript": {
 | 
			
		||||
      "version": "1.0.5",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz",
 | 
			
		||||
      "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "unicode-trie": {
 | 
			
		||||
      "version": "1.0.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-1.0.0.tgz",
 | 
			
		||||
      "integrity": "sha512-v5raLKsobbFbWLMoX9+bChts/VhPPj3XpkNr/HbqkirXR1DPk8eo9IYKyvk0MQZFkaoRsFj2Rmaqgi2rfAZYtA==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "pako": "^0.2.5",
 | 
			
		||||
        "tiny-inflate": "^1.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "pako": {
 | 
			
		||||
          "version": "0.2.9",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
 | 
			
		||||
          "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=",
 | 
			
		||||
          "dev": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "unified": {
 | 
			
		||||
      "version": "8.4.2",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/unified/-/unified-8.4.2.tgz",
 | 
			
		||||
@@ -12525,6 +13221,12 @@
 | 
			
		||||
        "unist-util-stringify-position": "^2.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "vlq": {
 | 
			
		||||
      "version": "0.2.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz",
 | 
			
		||||
      "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==",
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "vm-browserify": {
 | 
			
		||||
      "version": "1.1.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "foris",
 | 
			
		||||
  "version": "3.0.0",
 | 
			
		||||
  "version": "3.1.0",
 | 
			
		||||
  "description": "Set of components and utils for Foris and its plugins.",
 | 
			
		||||
  "author": "CZ.NIC, z.s.p.o.",
 | 
			
		||||
  "repository": {
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
    "reforis"
 | 
			
		||||
  ],
 | 
			
		||||
  "license": "GPL-3.0",
 | 
			
		||||
  "main": "./index.js",
 | 
			
		||||
  "main": "./src/index.js",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "axios": "^0.19.0",
 | 
			
		||||
    "jest-transform-css": "^2.0.0",
 | 
			
		||||
@@ -25,6 +25,8 @@
 | 
			
		||||
  },
 | 
			
		||||
  "peerDependencies": {
 | 
			
		||||
    "immutability-helper": "3.0.1",
 | 
			
		||||
    "pdfmake": "^0.1.63",
 | 
			
		||||
    "qrcode.react": "^0.9.3",
 | 
			
		||||
    "react": "16.9.0",
 | 
			
		||||
    "react-dom": "16.9.0"
 | 
			
		||||
  },
 | 
			
		||||
@@ -54,6 +56,8 @@
 | 
			
		||||
    "jest-mock-axios": "^3.0.0",
 | 
			
		||||
    "moment": "^2.24.0",
 | 
			
		||||
    "moment-timezone": "^0.5.25",
 | 
			
		||||
    "pdfmake": "^0.1.63",
 | 
			
		||||
    "qrcode.react": "^0.9.3",
 | 
			
		||||
    "react": "16.9.0",
 | 
			
		||||
    "react-dom": "16.9.0",
 | 
			
		||||
    "react-styleguidist": "^10.3.2",
 | 
			
		||||
@@ -63,6 +67,7 @@
 | 
			
		||||
  },
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "lint": "eslint src",
 | 
			
		||||
    "lint:fix": "eslint --fix src",
 | 
			
		||||
    "test": "jest",
 | 
			
		||||
    "test:watch": "jest --watch",
 | 
			
		||||
    "test:coverage": "jest --coverage --colors",
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,10 @@
 | 
			
		||||
mkdir -p dist
 | 
			
		||||
cp -rf ./src/* dist
 | 
			
		||||
cp package.json package-lock.json README.md dist
 | 
			
		||||
sed -i 's/\/src//g' dist/package.json # remove ./src from main js file path
 | 
			
		||||
 | 
			
		||||
cp -rf translations dist
 | 
			
		||||
 | 
			
		||||
# Remove unwanted files
 | 
			
		||||
rm -rf dist/**/__tests__
 | 
			
		||||
find dist -type d -name __tests__ -exec rm -r {} +
 | 
			
		||||
rm -rf dist/__mocks__
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,9 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
import { render, getByText, queryByText, fireEvent } from "customTestRender";
 | 
			
		||||
import {
 | 
			
		||||
    render, getByText, queryByText, fireEvent,
 | 
			
		||||
} from "customTestRender";
 | 
			
		||||
 | 
			
		||||
import { useAlert, AlertContextProvider } from "../AlertContext";
 | 
			
		||||
 | 
			
		||||
@@ -20,7 +22,7 @@ function AlertTest() {
 | 
			
		||||
            <button onClick={dismissAlert}>Dismiss alert</button>
 | 
			
		||||
        </>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
describe("AlertContext", () => {
 | 
			
		||||
    let componentContainer;
 | 
			
		||||
@@ -29,7 +31,7 @@ describe("AlertContext", () => {
 | 
			
		||||
        const { container } = render(
 | 
			
		||||
            <AlertContextProvider>
 | 
			
		||||
                <AlertTest />
 | 
			
		||||
            </AlertContextProvider>
 | 
			
		||||
            </AlertContextProvider>,
 | 
			
		||||
        );
 | 
			
		||||
        componentContainer = container;
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ describe("<Button />", () => {
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("Render button with spinner", () => {
 | 
			
		||||
        const { container } = render(<Button loading={true}>Test Button</Button>);
 | 
			
		||||
        const { container } = render(<Button loading>Test Button</Button>);
 | 
			
		||||
        expect(container.firstChild)
 | 
			
		||||
            .toMatchSnapshot();
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ describe("<Checkbox/>", () => {
 | 
			
		||||
                helpText="Some help text"
 | 
			
		||||
                onChange={() => {
 | 
			
		||||
                }}
 | 
			
		||||
            />
 | 
			
		||||
            />,
 | 
			
		||||
        );
 | 
			
		||||
        expect(container.firstChild)
 | 
			
		||||
            .toMatchSnapshot();
 | 
			
		||||
@@ -31,7 +31,7 @@ describe("<Checkbox/>", () => {
 | 
			
		||||
            <CheckBox
 | 
			
		||||
                label="Test label"
 | 
			
		||||
                helpText="Some help text"
 | 
			
		||||
            />
 | 
			
		||||
            />,
 | 
			
		||||
        );
 | 
			
		||||
        expect(container.firstChild)
 | 
			
		||||
            .toMatchSnapshot();
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,9 @@
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
 | 
			
		||||
import { render, fireEvent, getByLabelText, wait } from "customTestRender";
 | 
			
		||||
import {
 | 
			
		||||
    render, fireEvent, getByLabelText, wait,
 | 
			
		||||
} from "customTestRender";
 | 
			
		||||
 | 
			
		||||
import { NumberInput } from "../NumberInput";
 | 
			
		||||
 | 
			
		||||
@@ -22,7 +24,7 @@ describe("<NumberInput/>", () => {
 | 
			
		||||
                helpText="Some help text"
 | 
			
		||||
                value={1}
 | 
			
		||||
                onChange={onChangeMock}
 | 
			
		||||
            />
 | 
			
		||||
            />,
 | 
			
		||||
        );
 | 
			
		||||
        componentContainer = container;
 | 
			
		||||
    });
 | 
			
		||||
@@ -34,12 +36,12 @@ describe("<NumberInput/>", () => {
 | 
			
		||||
    it("Increase number with button", async () => {
 | 
			
		||||
        const increaseButton = getByLabelText(componentContainer, "Increase");
 | 
			
		||||
        fireEvent.mouseDown(increaseButton);
 | 
			
		||||
        await wait(() => expect(onChangeMock).toHaveBeenCalledWith({"target": {"value": 2}}));
 | 
			
		||||
        await wait(() => expect(onChangeMock).toHaveBeenCalledWith({ target: { value: 2 } }));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("Decrease number with button", async () => {
 | 
			
		||||
        const decreaseButton = getByLabelText(componentContainer, "Decrease");
 | 
			
		||||
        fireEvent.mouseDown(decreaseButton);
 | 
			
		||||
        await wait(() => expect(onChangeMock).toHaveBeenCalledWith({"target": {"value": 0}}));
 | 
			
		||||
        await wait(() => expect(onChangeMock).toHaveBeenCalledWith({ target: { value: 0 } }));
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ describe("<PasswordInput/>", () => {
 | 
			
		||||
                value="Some password"
 | 
			
		||||
                onChange={() => {
 | 
			
		||||
                }}
 | 
			
		||||
            />
 | 
			
		||||
            />,
 | 
			
		||||
        );
 | 
			
		||||
        expect(container.firstChild)
 | 
			
		||||
            .toMatchSnapshot();
 | 
			
		||||
 
 | 
			
		||||
@@ -14,30 +14,30 @@ import { RadioSet } from "../RadioSet";
 | 
			
		||||
const TEST_CHOICES = [
 | 
			
		||||
    {
 | 
			
		||||
        label: "label",
 | 
			
		||||
        value: "value"
 | 
			
		||||
        value: "value",
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        label: "another label",
 | 
			
		||||
        value: "another value"
 | 
			
		||||
        value: "another value",
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        label: "another one  label",
 | 
			
		||||
        value: "another on value"
 | 
			
		||||
    }
 | 
			
		||||
        value: "another on value",
 | 
			
		||||
    },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
describe("<RadioSet/>", () => {
 | 
			
		||||
    it("Render radio set", () => {
 | 
			
		||||
        const { container } = render(
 | 
			
		||||
            <RadioSet
 | 
			
		||||
                name={"test_name"}
 | 
			
		||||
                label='Radios set label'
 | 
			
		||||
                value='value'
 | 
			
		||||
                name="test_name"
 | 
			
		||||
                label="Radios set label"
 | 
			
		||||
                value="value"
 | 
			
		||||
                choices={TEST_CHOICES}
 | 
			
		||||
                helpText={"Some help text"}
 | 
			
		||||
                helpText="Some help text"
 | 
			
		||||
                onChange={() => {
 | 
			
		||||
                }}
 | 
			
		||||
            />
 | 
			
		||||
            />,
 | 
			
		||||
        );
 | 
			
		||||
        expect(container.firstChild)
 | 
			
		||||
            .toMatchSnapshot();
 | 
			
		||||
 
 | 
			
		||||
@@ -7,29 +7,31 @@
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
 | 
			
		||||
import { fireEvent, getByDisplayValue, getByText, render } from "customTestRender";
 | 
			
		||||
import {
 | 
			
		||||
    fireEvent, getByDisplayValue, getByText, render,
 | 
			
		||||
} from "customTestRender";
 | 
			
		||||
 | 
			
		||||
import { Select } from "../Select";
 | 
			
		||||
 | 
			
		||||
const TEST_CHOICES = {
 | 
			
		||||
    "1": "one",
 | 
			
		||||
    "2": "two",
 | 
			
		||||
    "3": "three",
 | 
			
		||||
    1: "one",
 | 
			
		||||
    2: "two",
 | 
			
		||||
    3: "three",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
describe("<Select/>", () => {
 | 
			
		||||
    var selectContainer;
 | 
			
		||||
    let selectContainer;
 | 
			
		||||
    const onChangeHandler = jest.fn();
 | 
			
		||||
    beforeEach(() => {
 | 
			
		||||
        const { container } = render(
 | 
			
		||||
            <Select
 | 
			
		||||
                label='Test label'
 | 
			
		||||
                value='1'
 | 
			
		||||
                label="Test label"
 | 
			
		||||
                value="1"
 | 
			
		||||
                choices={TEST_CHOICES}
 | 
			
		||||
                helpText='Help text'
 | 
			
		||||
                helpText="Help text"
 | 
			
		||||
 | 
			
		||||
                onChange={onChangeHandler}
 | 
			
		||||
            />
 | 
			
		||||
            />,
 | 
			
		||||
        );
 | 
			
		||||
        selectContainer = container;
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ describe("<TextInput/>", () => {
 | 
			
		||||
                value="Some text"
 | 
			
		||||
                onChange={() => {
 | 
			
		||||
                }}
 | 
			
		||||
            />
 | 
			
		||||
            />,
 | 
			
		||||
        );
 | 
			
		||||
        expect(container.firstChild)
 | 
			
		||||
            .toMatchSnapshot();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										74
									
								
								src/common/WiFiSettings/ResetWiFiSettings.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/common/WiFiSettings/ResetWiFiSettings.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free software, licensed under the GNU General Public License v3.
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React, { useEffect, useState } from "react";
 | 
			
		||||
import PropTypes from "prop-types";
 | 
			
		||||
 | 
			
		||||
import { Button } from "../../bootstrap/Button";
 | 
			
		||||
import { useAlert } from "../../alertContext/AlertContext";
 | 
			
		||||
import { ALERT_TYPES } from "../../bootstrap/Alert";
 | 
			
		||||
import { useAPIPost } from "../../api/hooks";
 | 
			
		||||
import { API_STATE } from "../../api/utils";
 | 
			
		||||
import { formFieldsSize } from "../../bootstrap/constants";
 | 
			
		||||
 | 
			
		||||
ResetWiFiSettings.propTypes = {
 | 
			
		||||
    ws: PropTypes.object.isRequired,
 | 
			
		||||
    endpoint: PropTypes.string.isRequired,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default function ResetWiFiSettings({ ws, endpoint }) {
 | 
			
		||||
    const [isLoading, setIsLoading] = useState(false);
 | 
			
		||||
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
        const module = "wifi";
 | 
			
		||||
        ws.subscribe(module)
 | 
			
		||||
            .bind(module, "reset", () => {
 | 
			
		||||
                setIsLoading(true);
 | 
			
		||||
                // eslint-disable-next-line no-restricted-globals
 | 
			
		||||
                setTimeout(() => location.reload(), 1000);
 | 
			
		||||
            });
 | 
			
		||||
    }, [ws]);
 | 
			
		||||
 | 
			
		||||
    const [postResetResponse, postReset] = useAPIPost(endpoint);
 | 
			
		||||
    const [setAlert, dismissAlert] = useAlert();
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
        if (postResetResponse.state === API_STATE.ERROR) {
 | 
			
		||||
            setAlert(_("An error occurred during resetting Wi-Fi settings."));
 | 
			
		||||
        } else if (postResetResponse.state === API_STATE.SUCCESS) {
 | 
			
		||||
            setAlert(_("Wi-Fi settings are set to defaults."), ALERT_TYPES.SUCCESS);
 | 
			
		||||
        }
 | 
			
		||||
    }, [postResetResponse, setAlert]);
 | 
			
		||||
 | 
			
		||||
    function onReset() {
 | 
			
		||||
        dismissAlert();
 | 
			
		||||
        postReset();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
            <h4>{_("Reset Wi-Fi Settings")}</h4>
 | 
			
		||||
            <p>
 | 
			
		||||
                {_(`
 | 
			
		||||
If a number of wireless cards doesn't match, you may try to reset the Wi-Fi settings. Note that this will remove the
 | 
			
		||||
current Wi-Fi configuration and restore the default values.
 | 
			
		||||
        `)}
 | 
			
		||||
            </p>
 | 
			
		||||
            <div className={`${formFieldsSize} text-right`}>
 | 
			
		||||
                <Button
 | 
			
		||||
                    className="btn-warning"
 | 
			
		||||
                    forisFormSize
 | 
			
		||||
                    loading={isLoading}
 | 
			
		||||
                    disabled={isLoading}
 | 
			
		||||
 | 
			
		||||
                    onClick={onReset}
 | 
			
		||||
                >
 | 
			
		||||
                    {_("Reset Wi-Fi Settings")}
 | 
			
		||||
                </Button>
 | 
			
		||||
            </div>
 | 
			
		||||
        </>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										250
									
								
								src/common/WiFiSettings/WiFiForm.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								src/common/WiFiSettings/WiFiForm.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,250 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free software, licensed under the GNU General Public License v3.
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
import PropTypes from "prop-types";
 | 
			
		||||
 | 
			
		||||
import { CheckBox } from "../../bootstrap/CheckBox";
 | 
			
		||||
import { PasswordInput } from "../../bootstrap/PasswordInput";
 | 
			
		||||
import { RadioSet } from "../../bootstrap/RadioSet";
 | 
			
		||||
import { Select } from "../../bootstrap/Select";
 | 
			
		||||
import { TextInput } from "../../bootstrap/TextInput";
 | 
			
		||||
import WiFiQRCode from "./WiFiQRCode";
 | 
			
		||||
import WifiGuestForm from "./WiFiGuestForm";
 | 
			
		||||
import { HELP_TEXTS, HTMODES, HWMODES } from "./constants";
 | 
			
		||||
 | 
			
		||||
WiFiForm.propTypes = {
 | 
			
		||||
    formData: PropTypes.shape(
 | 
			
		||||
        { devices: PropTypes.arrayOf(PropTypes.object) },
 | 
			
		||||
    ).isRequired,
 | 
			
		||||
    formErrors: PropTypes.oneOfType([
 | 
			
		||||
        PropTypes.object,
 | 
			
		||||
        PropTypes.array,
 | 
			
		||||
    ]),
 | 
			
		||||
    setFormValue: PropTypes.func.isRequired,
 | 
			
		||||
    hasGuestNetwork: PropTypes.bool,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
WiFiForm.defaultProps = {
 | 
			
		||||
    formData: { devices: [] },
 | 
			
		||||
    setFormValue: () => {},
 | 
			
		||||
    hasGuestNetwork: true,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default function WiFiForm({
 | 
			
		||||
    formData, formErrors, setFormValue, hasGuestNetwork, ...props
 | 
			
		||||
}) {
 | 
			
		||||
    return formData.devices.map((device) => (
 | 
			
		||||
        <DeviceForm
 | 
			
		||||
            key={device.id}
 | 
			
		||||
            formData={device}
 | 
			
		||||
            formErrors={(formErrors || [])[device.id]}
 | 
			
		||||
            setFormValue={setFormValue}
 | 
			
		||||
            hasGuestNetwork={hasGuestNetwork}
 | 
			
		||||
 | 
			
		||||
            {...props}
 | 
			
		||||
        />
 | 
			
		||||
    ));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DeviceForm.propTypes = {
 | 
			
		||||
    formData: PropTypes.shape({
 | 
			
		||||
        id: PropTypes.number.isRequired,
 | 
			
		||||
        enabled: PropTypes.bool.isRequired,
 | 
			
		||||
        SSID: PropTypes.string.isRequired,
 | 
			
		||||
        password: PropTypes.string.isRequired,
 | 
			
		||||
        hidden: PropTypes.bool.isRequired,
 | 
			
		||||
        hwmode: PropTypes.string.isRequired,
 | 
			
		||||
        htmode: PropTypes.string.isRequired,
 | 
			
		||||
        channel: PropTypes.string.isRequired,
 | 
			
		||||
        guest_wifi: PropTypes.object.isRequired,
 | 
			
		||||
    }),
 | 
			
		||||
    formErrors: PropTypes.object.isRequired,
 | 
			
		||||
    setFormValue: PropTypes.func.isRequired,
 | 
			
		||||
    hasGuestNetwork: PropTypes.bool,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
DeviceForm.defaultProps = {
 | 
			
		||||
    formErrors: {},
 | 
			
		||||
    hasGuestNetwork: true,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function DeviceForm({
 | 
			
		||||
    formData, formErrors, setFormValue, hasGuestNetwork, ...props
 | 
			
		||||
}) {
 | 
			
		||||
    const deviceID = formData.id;
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
            <h3>{_(`Wi-Fi ${deviceID + 1}`)}</h3>
 | 
			
		||||
            <CheckBox
 | 
			
		||||
                label={_("Enable")}
 | 
			
		||||
                checked={formData.enabled}
 | 
			
		||||
 | 
			
		||||
                onChange={setFormValue(
 | 
			
		||||
                    (value) => ({ devices: { [deviceID]: { enabled: { $set: value } } } }),
 | 
			
		||||
                )}
 | 
			
		||||
 | 
			
		||||
                {...props}
 | 
			
		||||
            />
 | 
			
		||||
            {formData.enabled
 | 
			
		||||
                ? (
 | 
			
		||||
                    <>
 | 
			
		||||
                        <TextInput
 | 
			
		||||
                            label="SSID"
 | 
			
		||||
                            value={formData.SSID}
 | 
			
		||||
                            error={formErrors.SSID || null}
 | 
			
		||||
                            required
 | 
			
		||||
                            onChange={setFormValue(
 | 
			
		||||
                                (value) => ({ devices: { [deviceID]: { SSID: { $set: value } } } }),
 | 
			
		||||
                            )}
 | 
			
		||||
 | 
			
		||||
                            {...props}
 | 
			
		||||
                        >
 | 
			
		||||
                            <div className="input-group-append">
 | 
			
		||||
                                <WiFiQRCode
 | 
			
		||||
                                    SSID={formData.SSID}
 | 
			
		||||
                                    password={formData.password}
 | 
			
		||||
                                />
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </TextInput>
 | 
			
		||||
 | 
			
		||||
                        <PasswordInput
 | 
			
		||||
                            withEye
 | 
			
		||||
                            label="Password"
 | 
			
		||||
                            value={formData.password}
 | 
			
		||||
                            error={formErrors.password}
 | 
			
		||||
                            helpText={HELP_TEXTS.password}
 | 
			
		||||
                            required
 | 
			
		||||
 | 
			
		||||
                            onChange={setFormValue(
 | 
			
		||||
                                (value) => (
 | 
			
		||||
                                    { devices: { [deviceID]: { password: { $set: value } } } }
 | 
			
		||||
                                ),
 | 
			
		||||
                            )}
 | 
			
		||||
 | 
			
		||||
                            {...props}
 | 
			
		||||
                        />
 | 
			
		||||
 | 
			
		||||
                        <CheckBox
 | 
			
		||||
                            label="Hide SSID"
 | 
			
		||||
                            helpText={HELP_TEXTS.hidden}
 | 
			
		||||
                            checked={formData.hidden}
 | 
			
		||||
 | 
			
		||||
                            onChange={setFormValue(
 | 
			
		||||
                                (value) => (
 | 
			
		||||
                                    { devices: { [deviceID]: { hidden: { $set: value } } } }
 | 
			
		||||
                                ),
 | 
			
		||||
                            )}
 | 
			
		||||
 | 
			
		||||
                            {...props}
 | 
			
		||||
                        />
 | 
			
		||||
 | 
			
		||||
                        <RadioSet
 | 
			
		||||
                            name={`hwmode-${deviceID}`}
 | 
			
		||||
                            label="GHz"
 | 
			
		||||
                            choices={getHwmodeChoices(formData)}
 | 
			
		||||
                            value={formData.hwmode}
 | 
			
		||||
                            helpText={HELP_TEXTS.hwmode}
 | 
			
		||||
 | 
			
		||||
                            onChange={setFormValue(
 | 
			
		||||
                                (value) => ({
 | 
			
		||||
                                    devices: {
 | 
			
		||||
                                        [deviceID]: {
 | 
			
		||||
                                            hwmode: { $set: value },
 | 
			
		||||
                                            channel: { $set: "0" },
 | 
			
		||||
                                        },
 | 
			
		||||
                                    },
 | 
			
		||||
                                }),
 | 
			
		||||
                            )}
 | 
			
		||||
 | 
			
		||||
                            {...props}
 | 
			
		||||
                        />
 | 
			
		||||
 | 
			
		||||
                        <Select
 | 
			
		||||
                            label="802.11n/ac mode"
 | 
			
		||||
                            choices={getHtmodeChoices(formData)}
 | 
			
		||||
                            value={formData.htmode}
 | 
			
		||||
                            helpText={HELP_TEXTS.htmode}
 | 
			
		||||
 | 
			
		||||
                            onChange={setFormValue(
 | 
			
		||||
                                (value) => (
 | 
			
		||||
                                    { devices: { [deviceID]: { htmode: { $set: value } } } }
 | 
			
		||||
                                ),
 | 
			
		||||
                            )}
 | 
			
		||||
 | 
			
		||||
                            {...props}
 | 
			
		||||
                        />
 | 
			
		||||
 | 
			
		||||
                        <Select
 | 
			
		||||
                            label="Channel"
 | 
			
		||||
                            choices={getChannelChoices(formData)}
 | 
			
		||||
                            value={formData.channel}
 | 
			
		||||
 | 
			
		||||
                            onChange={setFormValue(
 | 
			
		||||
                                (value) => (
 | 
			
		||||
                                    { devices: { [deviceID]: { channel: { $set: value } } } }
 | 
			
		||||
                                ),
 | 
			
		||||
                            )}
 | 
			
		||||
 | 
			
		||||
                            {...props}
 | 
			
		||||
                        />
 | 
			
		||||
 | 
			
		||||
                        {hasGuestNetwork && (
 | 
			
		||||
                            <WifiGuestForm
 | 
			
		||||
                                formData={{ id: deviceID, ...formData.guest_wifi }}
 | 
			
		||||
                                formErrors={formErrors.guest_wifi || {}}
 | 
			
		||||
 | 
			
		||||
                                setFormValue={setFormValue}
 | 
			
		||||
 | 
			
		||||
                                {...props}
 | 
			
		||||
                            />
 | 
			
		||||
                        )}
 | 
			
		||||
                    </>
 | 
			
		||||
                )
 | 
			
		||||
                : null}
 | 
			
		||||
        </>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getChannelChoices(device) {
 | 
			
		||||
    const channelChoices = {
 | 
			
		||||
        0: _("auto"),
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    device.available_bands.forEach((availableBand) => {
 | 
			
		||||
        if (availableBand.hwmode !== device.hwmode) return;
 | 
			
		||||
 | 
			
		||||
        availableBand.available_channels.forEach((availableChannel) => {
 | 
			
		||||
            channelChoices[availableChannel.number.toString()] = `
 | 
			
		||||
                        ${availableChannel.number}
 | 
			
		||||
                        (${availableChannel.frequency} MHz ${availableChannel.radar ? " ,DFS" : ""})
 | 
			
		||||
                    `;
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return channelChoices;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getHtmodeChoices(device) {
 | 
			
		||||
    const htmodeChoices = {};
 | 
			
		||||
 | 
			
		||||
    device.available_bands.forEach((availableBand) => {
 | 
			
		||||
        if (availableBand.hwmode !== device.hwmode) return;
 | 
			
		||||
 | 
			
		||||
        availableBand.available_htmodes.forEach((availableHtmod) => {
 | 
			
		||||
            htmodeChoices[availableHtmod] = HTMODES[availableHtmod];
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    return htmodeChoices;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getHwmodeChoices(device) {
 | 
			
		||||
    return device.available_bands.map((availableBand) => ({
 | 
			
		||||
        label: HWMODES[availableBand.hwmode],
 | 
			
		||||
        value: availableBand.hwmode,
 | 
			
		||||
    }));
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										100
									
								
								src/common/WiFiSettings/WiFiGuestForm.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								src/common/WiFiSettings/WiFiGuestForm.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free software, licensed under the GNU General Public License v3.
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
import PropTypes from "prop-types";
 | 
			
		||||
 | 
			
		||||
import { CheckBox } from "../../bootstrap/CheckBox";
 | 
			
		||||
import { TextInput } from "../../bootstrap/TextInput";
 | 
			
		||||
import { PasswordInput } from "../../bootstrap/PasswordInput";
 | 
			
		||||
import WiFiQRCode from "./WiFiQRCode";
 | 
			
		||||
import { HELP_TEXTS } from "./constants";
 | 
			
		||||
 | 
			
		||||
WifiGuestForm.propTypes = {
 | 
			
		||||
    formData: PropTypes.shape({
 | 
			
		||||
        id: PropTypes.number.isRequired,
 | 
			
		||||
        SSID: PropTypes.string.isRequired,
 | 
			
		||||
        password: PropTypes.string.isRequired,
 | 
			
		||||
        enabled: PropTypes.bool.isRequired,
 | 
			
		||||
    }),
 | 
			
		||||
    formErrors: PropTypes.shape({
 | 
			
		||||
        SSID: PropTypes.string,
 | 
			
		||||
        password: PropTypes.string,
 | 
			
		||||
    }),
 | 
			
		||||
    setFormValue: PropTypes.func.isRequired,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default function WifiGuestForm({
 | 
			
		||||
    formData, formErrors, setFormValue, ...props
 | 
			
		||||
}) {
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
            <CheckBox
 | 
			
		||||
                label={_("Enable Guest Wifi")}
 | 
			
		||||
                checked={formData.enabled}
 | 
			
		||||
                helpText={HELP_TEXTS.guest_wifi_enabled}
 | 
			
		||||
 | 
			
		||||
                onChange={setFormValue(
 | 
			
		||||
                    (value) => (
 | 
			
		||||
                        { devices: { [formData.id]: { guest_wifi: { enabled: { $set: value } } } } }
 | 
			
		||||
                    ),
 | 
			
		||||
                )}
 | 
			
		||||
 | 
			
		||||
                {...props}
 | 
			
		||||
            />
 | 
			
		||||
            {formData.enabled
 | 
			
		||||
                ? (
 | 
			
		||||
                    <>
 | 
			
		||||
                        <TextInput
 | 
			
		||||
                            label="SSID"
 | 
			
		||||
                            value={formData.SSID}
 | 
			
		||||
                            error={formErrors.SSID}
 | 
			
		||||
 | 
			
		||||
                            onChange={setFormValue(
 | 
			
		||||
                                (value) => ({
 | 
			
		||||
                                    devices: {
 | 
			
		||||
                                        [formData.id]: { guest_wifi: { SSID: { $set: value } } },
 | 
			
		||||
                                    },
 | 
			
		||||
                                }),
 | 
			
		||||
                            )}
 | 
			
		||||
 | 
			
		||||
                            {...props}
 | 
			
		||||
                        >
 | 
			
		||||
                            <div className="input-group-append">
 | 
			
		||||
                                <WiFiQRCode
 | 
			
		||||
                                    SSID={formData.SSID}
 | 
			
		||||
                                    password={formData.password}
 | 
			
		||||
                                />
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </TextInput>
 | 
			
		||||
 | 
			
		||||
                        <PasswordInput
 | 
			
		||||
                            withEye
 | 
			
		||||
                            label={_("Password")}
 | 
			
		||||
                            value={formData.password}
 | 
			
		||||
                            helpText={HELP_TEXTS.password}
 | 
			
		||||
                            error={formErrors.password}
 | 
			
		||||
                            required
 | 
			
		||||
 | 
			
		||||
                            onChange={setFormValue(
 | 
			
		||||
                                (value) => ({
 | 
			
		||||
                                    devices: {
 | 
			
		||||
                                        [formData.id]: {
 | 
			
		||||
                                            guest_wifi: { password: { $set: value } },
 | 
			
		||||
                                        },
 | 
			
		||||
                                    },
 | 
			
		||||
                                }),
 | 
			
		||||
                            )}
 | 
			
		||||
 | 
			
		||||
                            {...props}
 | 
			
		||||
                        />
 | 
			
		||||
                    </>
 | 
			
		||||
                )
 | 
			
		||||
                : null}
 | 
			
		||||
        </>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										85
									
								
								src/common/WiFiSettings/WiFiQRCode.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								src/common/WiFiSettings/WiFiQRCode.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,85 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free software, licensed under the GNU General Public License v3.
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React, { useState } from "react";
 | 
			
		||||
import QRCode from "qrcode.react";
 | 
			
		||||
import PropTypes from "prop-types";
 | 
			
		||||
 | 
			
		||||
import { ForisURLs } from "../../forisUrls";
 | 
			
		||||
import { Button } from "../../bootstrap/Button";
 | 
			
		||||
import {
 | 
			
		||||
    Modal, ModalBody, ModalFooter, ModalHeader,
 | 
			
		||||
} from "../../bootstrap/Modal";
 | 
			
		||||
import { createAndDownloadPdf, toQRCodeContent } from "./qrCodeHelpers";
 | 
			
		||||
 | 
			
		||||
WiFiQRCode.propTypes = {
 | 
			
		||||
    SSID: PropTypes.string.isRequired,
 | 
			
		||||
    password: PropTypes.string.isRequired,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const QR_ICON_PATH = `${ForisURLs.static}/imgs/QR_icon.svg`;
 | 
			
		||||
 | 
			
		||||
export default function WiFiQRCode({ SSID, password }) {
 | 
			
		||||
    const [modal, setModal] = useState(false);
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
            <button
 | 
			
		||||
                type="button"
 | 
			
		||||
                className="input-group-text"
 | 
			
		||||
                onClick={(e) => {
 | 
			
		||||
                    e.preventDefault();
 | 
			
		||||
                    setModal(true);
 | 
			
		||||
                }}
 | 
			
		||||
            >
 | 
			
		||||
                <img width="20" src={QR_ICON_PATH} alt="QR" style={{ opacity: 0.67 }} />
 | 
			
		||||
            </button>
 | 
			
		||||
            {modal
 | 
			
		||||
                ? <QRCodeModal setShown={setModal} shown={modal} SSID={SSID} password={password} />
 | 
			
		||||
                : null}
 | 
			
		||||
        </>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QRCodeModal.propTypes = {
 | 
			
		||||
    SSID: PropTypes.string.isRequired,
 | 
			
		||||
    password: PropTypes.string.isRequired,
 | 
			
		||||
    shown: PropTypes.bool.isRequired,
 | 
			
		||||
    setShown: PropTypes.func.isRequired,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function QRCodeModal({
 | 
			
		||||
    shown, setShown, SSID, password,
 | 
			
		||||
}) {
 | 
			
		||||
    return (
 | 
			
		||||
        <Modal setShown={setShown} shown={shown}>
 | 
			
		||||
            <ModalHeader setShown={setShown} title={_("Wi-Fi QR Code")} />
 | 
			
		||||
            <ModalBody>
 | 
			
		||||
                <QRCode
 | 
			
		||||
                    renderAs="svg"
 | 
			
		||||
                    value={toQRCodeContent(SSID, password)}
 | 
			
		||||
                    level="M"
 | 
			
		||||
                    size={350}
 | 
			
		||||
                    includeMargin
 | 
			
		||||
                    style={{ display: "block", margin: "auto" }}
 | 
			
		||||
                />
 | 
			
		||||
            </ModalBody>
 | 
			
		||||
            <ModalFooter>
 | 
			
		||||
                <Button
 | 
			
		||||
                    className="btn-outline-primary"
 | 
			
		||||
                    onClick={(e) => {
 | 
			
		||||
                        e.preventDefault();
 | 
			
		||||
                        createAndDownloadPdf(SSID, password);
 | 
			
		||||
                    }}
 | 
			
		||||
                >
 | 
			
		||||
                    <i className="fas fa-arrow-down mr-2" />
 | 
			
		||||
                    {_("Download PDF")}
 | 
			
		||||
                </Button>
 | 
			
		||||
            </ModalFooter>
 | 
			
		||||
        </Modal>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										93
									
								
								src/common/WiFiSettings/WiFiSettings.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								src/common/WiFiSettings/WiFiSettings.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,93 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free software, licensed under the GNU General Public License v3.
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
import PropTypes from "prop-types";
 | 
			
		||||
 | 
			
		||||
import { ForisForm } from "../../form/components/ForisForm";
 | 
			
		||||
import WiFiForm from "./WiFiForm";
 | 
			
		||||
import ResetWiFiSettings from "./ResetWiFiSettings";
 | 
			
		||||
 | 
			
		||||
WiFiSettings.propTypes = {
 | 
			
		||||
    ws: PropTypes.object.isRequired,
 | 
			
		||||
    endpoint: PropTypes.string.isRequired,
 | 
			
		||||
    resetEndpoint: PropTypes.string.isRequired,
 | 
			
		||||
    hasGuestNetwork: PropTypes.bool,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export function WiFiSettings({
 | 
			
		||||
    ws, endpoint, resetEndpoint, hasGuestNetwork,
 | 
			
		||||
}) {
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
            <ForisForm
 | 
			
		||||
                ws={ws}
 | 
			
		||||
                forisConfig={{
 | 
			
		||||
                    endpoint,
 | 
			
		||||
                    wsModule: "wifi",
 | 
			
		||||
                }}
 | 
			
		||||
                prepData={prepData}
 | 
			
		||||
                prepDataToSubmit={prepDataToSubmit}
 | 
			
		||||
                validator={validator}
 | 
			
		||||
            >
 | 
			
		||||
                <WiFiForm hasGuestNetwork={hasGuestNetwork} />
 | 
			
		||||
            </ForisForm>
 | 
			
		||||
            <ResetWiFiSettings ws={ws} endpoint={resetEndpoint} />
 | 
			
		||||
        </>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function prepData(formData) {
 | 
			
		||||
    formData.devices.forEach((device, idx) => {
 | 
			
		||||
        formData.devices[idx].channel = device.channel.toString();
 | 
			
		||||
    });
 | 
			
		||||
    return formData;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function prepDataToSubmit(formData) {
 | 
			
		||||
    formData.devices.forEach((device, idx) => {
 | 
			
		||||
        delete device.available_bands;
 | 
			
		||||
 | 
			
		||||
        formData.devices[idx].channel = parseInt(device.channel);
 | 
			
		||||
 | 
			
		||||
        if (!device.enabled) {
 | 
			
		||||
            formData.devices[idx] = { id: device.id, enabled: false };
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!device.guest_wifi.enabled) formData.devices[idx].guest_wifi = { enabled: false };
 | 
			
		||||
    });
 | 
			
		||||
    return formData;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function validator(formData) {
 | 
			
		||||
    const formErrors = formData.devices.map(
 | 
			
		||||
        (device) => {
 | 
			
		||||
            if (!device.enabled) return {};
 | 
			
		||||
 | 
			
		||||
            const errors = {};
 | 
			
		||||
            if (device.SSID.length > 32) errors.SSID = _("SSID can't be longer than 32 symbols");
 | 
			
		||||
            if (device.SSID.length === 0) errors.SSID = _("SSID can't be empty");
 | 
			
		||||
 | 
			
		||||
            if (device.password.length < 8) errors.password = _("Password must contain at least 8 symbols");
 | 
			
		||||
 | 
			
		||||
            if (!device.guest_wifi.enabled) return errors;
 | 
			
		||||
 | 
			
		||||
            const guest_wifi_errors = {};
 | 
			
		||||
            if (device.guest_wifi.SSID.length > 32) guest_wifi_errors.SSID = _("SSID can't be longer than 32 symbols");
 | 
			
		||||
            if (device.guest_wifi.SSID.length === 0) guest_wifi_errors.SSID = _("SSID can't be empty");
 | 
			
		||||
 | 
			
		||||
            if (device.guest_wifi.password.length < 8) guest_wifi_errors.password = _("Password must contain at least 8 symbols");
 | 
			
		||||
 | 
			
		||||
            if (guest_wifi_errors.SSID || guest_wifi_errors.password) {
 | 
			
		||||
                errors.guest_wifi = guest_wifi_errors;
 | 
			
		||||
            }
 | 
			
		||||
            return errors;
 | 
			
		||||
        },
 | 
			
		||||
    );
 | 
			
		||||
    return JSON.stringify(formErrors) === "[{},{}]" ? null : formErrors;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										40
									
								
								src/common/WiFiSettings/__tests__/ResetWiFiSettings.test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/common/WiFiSettings/__tests__/ResetWiFiSettings.test.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free software, licensed under the GNU General Public License v3.
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
import { render, fireEvent, wait } from "customTestRender";
 | 
			
		||||
 | 
			
		||||
import mockAxios from "jest-mock-axios";
 | 
			
		||||
import { WebSockets } from "webSockets/WebSockets";
 | 
			
		||||
import { mockJSONError } from "testUtils/network";
 | 
			
		||||
import { mockSetAlert } from "testUtils/alertContextMock";
 | 
			
		||||
import { ALERT_TYPES } from "../../../bootstrap/Alert";
 | 
			
		||||
 | 
			
		||||
import ResetWiFiSettings from "../ResetWiFiSettings";
 | 
			
		||||
 | 
			
		||||
describe("<ResetWiFiSettings/>", () => {
 | 
			
		||||
    const webSockets = new WebSockets();
 | 
			
		||||
    const endpoint = "/reforis/api/wifi-reset";
 | 
			
		||||
    let getAllByText;
 | 
			
		||||
 | 
			
		||||
    beforeEach(() => {
 | 
			
		||||
        ({ getAllByText } = render(<ResetWiFiSettings ws={webSockets} endpoint={endpoint} />));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("should display alert on open ports - success", async () => {
 | 
			
		||||
        fireEvent.click(getAllByText("Reset Wi-Fi Settings")[1]);
 | 
			
		||||
        expect(mockAxios.post).toBeCalledWith(endpoint, undefined, expect.anything());
 | 
			
		||||
        mockAxios.mockResponse({ data: { foo: "bar" } });
 | 
			
		||||
        await wait(() => expect(mockSetAlert).toBeCalledWith("Wi-Fi settings are set to defaults.", ALERT_TYPES.SUCCESS));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("should display alert on open ports - failure", async () => {
 | 
			
		||||
        fireEvent.click(getAllByText("Reset Wi-Fi Settings")[1]);
 | 
			
		||||
        mockJSONError();
 | 
			
		||||
        await wait(() => expect(mockSetAlert).toBeCalledWith("An error occurred during resetting Wi-Fi settings."));
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										161
									
								
								src/common/WiFiSettings/__tests__/WiFiSettings.test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								src/common/WiFiSettings/__tests__/WiFiSettings.test.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,161 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free software, licensed under the GNU General Public License v3.
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
import diffSnapshot from "snapshot-diff";
 | 
			
		||||
import mockAxios from "jest-mock-axios";
 | 
			
		||||
 | 
			
		||||
import { fireEvent, render, wait } from "customTestRender";
 | 
			
		||||
import { WebSockets } from "webSockets/WebSockets";
 | 
			
		||||
import { mockJSONError } from "testUtils/network";
 | 
			
		||||
 | 
			
		||||
import { wifiSettingsFixture } from "./__fixtures__/wifiSettings";
 | 
			
		||||
import { WiFiSettings } from "../WiFiSettings";
 | 
			
		||||
 | 
			
		||||
describe("<WiFiSettings/>", () => {
 | 
			
		||||
    let firstRender;
 | 
			
		||||
    let getAllByText;
 | 
			
		||||
    let getAllByLabelText;
 | 
			
		||||
    let getByText;
 | 
			
		||||
    let asFragment;
 | 
			
		||||
    const endpoint = "/reforis/api/wifi";
 | 
			
		||||
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        const webSockets = new WebSockets();
 | 
			
		||||
        const renderRes = render(<WiFiSettings ws={webSockets} endpoint={endpoint} resetEndpoint="foo" />);
 | 
			
		||||
        asFragment = renderRes.asFragment;
 | 
			
		||||
        getAllByText = renderRes.getAllByText;
 | 
			
		||||
        getAllByLabelText = renderRes.getAllByLabelText;
 | 
			
		||||
        getByText = renderRes.getByText;
 | 
			
		||||
        mockAxios.mockResponse({ data: wifiSettingsFixture() });
 | 
			
		||||
        await wait(() => renderRes.getByText("Wi-Fi 1"));
 | 
			
		||||
        firstRender = renderRes.asFragment();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("should handle error", async () => {
 | 
			
		||||
        const webSockets = new WebSockets();
 | 
			
		||||
        const { getByText } = render(<WiFiSettings ws={webSockets} ws={webSockets} endpoint={endpoint} resetEndpoint="foo" />);
 | 
			
		||||
        mockJSONError();
 | 
			
		||||
        await wait(() => {
 | 
			
		||||
            expect(getByText("An error occurred while fetching data.")).toBeTruthy();
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("Snapshot both modules disabled.", () => {
 | 
			
		||||
        expect(firstRender).toMatchSnapshot();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("Snapshot one module enabled.", () => {
 | 
			
		||||
        fireEvent.click(getAllByText("Enable")[0]);
 | 
			
		||||
        expect(diffSnapshot(firstRender, asFragment())).toMatchSnapshot();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("Snapshot 2.4 GHz", () => {
 | 
			
		||||
        fireEvent.click(getAllByText("Enable")[0]);
 | 
			
		||||
        const enabledRender = asFragment();
 | 
			
		||||
        fireEvent.click(getAllByText("2.4")[0]);
 | 
			
		||||
        expect(diffSnapshot(enabledRender, asFragment())).toMatchSnapshot();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("Snapshot guest network.", () => {
 | 
			
		||||
        fireEvent.click(getAllByText("Enable")[0]);
 | 
			
		||||
        const enabledRender = asFragment();
 | 
			
		||||
        fireEvent.click(getAllByText("Enable Guest Wifi")[0]);
 | 
			
		||||
        expect(diffSnapshot(enabledRender, asFragment())).toMatchSnapshot();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("Post form: both modules disabled.", () => {
 | 
			
		||||
        fireEvent.click(getByText("Save"));
 | 
			
		||||
        expect(mockAxios.post).toBeCalled();
 | 
			
		||||
        const data = {
 | 
			
		||||
            devices: [
 | 
			
		||||
                { enabled: false, id: 0 },
 | 
			
		||||
                { enabled: false, id: 1 },
 | 
			
		||||
            ],
 | 
			
		||||
        };
 | 
			
		||||
        expect(mockAxios.post).toHaveBeenCalledWith(endpoint, data, expect.anything());
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("Post form: one module enabled.", () => {
 | 
			
		||||
        fireEvent.click(getAllByText("Enable")[0]);
 | 
			
		||||
 | 
			
		||||
        fireEvent.click(getByText("Save"));
 | 
			
		||||
        expect(mockAxios.post).toBeCalled();
 | 
			
		||||
        const data = {
 | 
			
		||||
            devices: [
 | 
			
		||||
                {
 | 
			
		||||
                    SSID: "TestSSID1",
 | 
			
		||||
                    channel: 60,
 | 
			
		||||
                    enabled: true,
 | 
			
		||||
                    guest_wifi: { enabled: false },
 | 
			
		||||
                    hidden: false,
 | 
			
		||||
                    htmode: "HT40",
 | 
			
		||||
                    hwmode: "11a",
 | 
			
		||||
                    id: 0,
 | 
			
		||||
                    password: "TestPass",
 | 
			
		||||
                },
 | 
			
		||||
                { enabled: false, id: 1 },
 | 
			
		||||
            ],
 | 
			
		||||
        };
 | 
			
		||||
        expect(mockAxios.post).toHaveBeenCalledWith(endpoint, data, expect.anything());
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("Post form: 2.4 GHz", () => {
 | 
			
		||||
        fireEvent.click(getAllByText("Enable")[0]);
 | 
			
		||||
        fireEvent.click(getAllByText("2.4")[0]);
 | 
			
		||||
 | 
			
		||||
        fireEvent.click(getByText("Save"));
 | 
			
		||||
        expect(mockAxios.post).toBeCalled();
 | 
			
		||||
        const data = {
 | 
			
		||||
            devices: [
 | 
			
		||||
                {
 | 
			
		||||
                    SSID: "TestSSID1",
 | 
			
		||||
                    channel: 0,
 | 
			
		||||
                    enabled: true,
 | 
			
		||||
                    guest_wifi: { enabled: false },
 | 
			
		||||
                    hidden: false,
 | 
			
		||||
                    htmode: "HT40",
 | 
			
		||||
                    hwmode: "11g",
 | 
			
		||||
                    id: 0,
 | 
			
		||||
                    password: "TestPass",
 | 
			
		||||
                },
 | 
			
		||||
                { enabled: false, id: 1 },
 | 
			
		||||
            ],
 | 
			
		||||
        };
 | 
			
		||||
        expect(mockAxios.post).toHaveBeenCalledWith(endpoint, data, expect.anything());
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it("Post form: guest network.", () => {
 | 
			
		||||
        fireEvent.click(getAllByText("Enable")[0]);
 | 
			
		||||
        fireEvent.click(getAllByText("Enable Guest Wifi")[0]);
 | 
			
		||||
        fireEvent.change(getAllByLabelText("Password")[1], { target: { value: "test_password" } });
 | 
			
		||||
 | 
			
		||||
        fireEvent.click(getByText("Save"));
 | 
			
		||||
        expect(mockAxios.post).toBeCalled();
 | 
			
		||||
        const data = {
 | 
			
		||||
            devices: [
 | 
			
		||||
                {
 | 
			
		||||
                    SSID: "TestSSID1",
 | 
			
		||||
                    channel: 60,
 | 
			
		||||
                    enabled: true,
 | 
			
		||||
                    guest_wifi: {
 | 
			
		||||
                        SSID: "TestGuestSSID",
 | 
			
		||||
                        enabled: true,
 | 
			
		||||
                        password: "test_password",
 | 
			
		||||
                    },
 | 
			
		||||
                    hidden: false,
 | 
			
		||||
                    htmode: "HT40",
 | 
			
		||||
                    hwmode: "11a",
 | 
			
		||||
                    id: 0,
 | 
			
		||||
                    password: "TestPass",
 | 
			
		||||
                },
 | 
			
		||||
                { enabled: false, id: 1 },
 | 
			
		||||
            ],
 | 
			
		||||
        };
 | 
			
		||||
        expect(mockAxios.post).toHaveBeenCalledWith(endpoint, data, expect.anything());
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										318
									
								
								src/common/WiFiSettings/__tests__/__fixtures__/wifiSettings.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										318
									
								
								src/common/WiFiSettings/__tests__/__fixtures__/wifiSettings.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,318 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free software, licensed under the GNU General Public License v3.
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
export function wifiSettingsFixture() {
 | 
			
		||||
    return {
 | 
			
		||||
        devices: [
 | 
			
		||||
            {
 | 
			
		||||
                SSID: "TestSSID1",
 | 
			
		||||
                available_bands: [
 | 
			
		||||
                    {
 | 
			
		||||
                        available_channels: [
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2412,
 | 
			
		||||
                                number: 1,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2417,
 | 
			
		||||
                                number: 2,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2422,
 | 
			
		||||
                                number: 3,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2427,
 | 
			
		||||
                                number: 4,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2432,
 | 
			
		||||
                                number: 5,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2437,
 | 
			
		||||
                                number: 6,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2442,
 | 
			
		||||
                                number: 7,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2447,
 | 
			
		||||
                                number: 8,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2452,
 | 
			
		||||
                                number: 9,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2457,
 | 
			
		||||
                                number: 10,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2462,
 | 
			
		||||
                                number: 11,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                        ],
 | 
			
		||||
                        available_htmodes: [
 | 
			
		||||
                            "NOHT",
 | 
			
		||||
                            "HT20",
 | 
			
		||||
                            "HT40",
 | 
			
		||||
                            "VHT20",
 | 
			
		||||
                            "VHT40",
 | 
			
		||||
                            "VHT80",
 | 
			
		||||
                        ],
 | 
			
		||||
                        hwmode: "11g",
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        available_channels: [
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5180,
 | 
			
		||||
                                number: 36,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5200,
 | 
			
		||||
                                number: 40,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5220,
 | 
			
		||||
                                number: 44,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5240,
 | 
			
		||||
                                number: 48,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5260,
 | 
			
		||||
                                number: 52,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5280,
 | 
			
		||||
                                number: 56,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5300,
 | 
			
		||||
                                number: 60,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5320,
 | 
			
		||||
                                number: 64,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5500,
 | 
			
		||||
                                number: 100,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5520,
 | 
			
		||||
                                number: 104,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5540,
 | 
			
		||||
                                number: 108,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5560,
 | 
			
		||||
                                number: 112,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5580,
 | 
			
		||||
                                number: 116,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5600,
 | 
			
		||||
                                number: 120,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5620,
 | 
			
		||||
                                number: 124,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5640,
 | 
			
		||||
                                number: 128,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5660,
 | 
			
		||||
                                number: 132,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5680,
 | 
			
		||||
                                number: 136,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5700,
 | 
			
		||||
                                number: 140,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5720,
 | 
			
		||||
                                number: 144,
 | 
			
		||||
                                radar: true,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5745,
 | 
			
		||||
                                number: 149,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5765,
 | 
			
		||||
                                number: 153,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5785,
 | 
			
		||||
                                number: 157,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5805,
 | 
			
		||||
                                number: 161,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 5825,
 | 
			
		||||
                                number: 165,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                        ],
 | 
			
		||||
                        available_htmodes: [
 | 
			
		||||
                            "NOHT",
 | 
			
		||||
                            "HT20",
 | 
			
		||||
                            "HT40",
 | 
			
		||||
                            "VHT20",
 | 
			
		||||
                            "VHT40",
 | 
			
		||||
                            "VHT80",
 | 
			
		||||
                        ],
 | 
			
		||||
                        hwmode: "11a",
 | 
			
		||||
                    },
 | 
			
		||||
                ],
 | 
			
		||||
                channel: 60,
 | 
			
		||||
                enabled: false,
 | 
			
		||||
                guest_wifi: {
 | 
			
		||||
                    SSID: "TestGuestSSID",
 | 
			
		||||
                    enabled: false,
 | 
			
		||||
                    password: "",
 | 
			
		||||
                },
 | 
			
		||||
                hidden: false,
 | 
			
		||||
                htmode: "HT40",
 | 
			
		||||
                hwmode: "11a",
 | 
			
		||||
                id: 0,
 | 
			
		||||
                password: "TestPass",
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                SSID: "Turris",
 | 
			
		||||
                available_bands: [
 | 
			
		||||
                    {
 | 
			
		||||
                        available_channels: [
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2412,
 | 
			
		||||
                                number: 1,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2417,
 | 
			
		||||
                                number: 2,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2422,
 | 
			
		||||
                                number: 3,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2427,
 | 
			
		||||
                                number: 4,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2432,
 | 
			
		||||
                                number: 5,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2437,
 | 
			
		||||
                                number: 6,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2442,
 | 
			
		||||
                                number: 7,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2447,
 | 
			
		||||
                                number: 8,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2452,
 | 
			
		||||
                                number: 9,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2457,
 | 
			
		||||
                                number: 10,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                frequency: 2462,
 | 
			
		||||
                                number: 11,
 | 
			
		||||
                                radar: false,
 | 
			
		||||
                            },
 | 
			
		||||
                        ],
 | 
			
		||||
                        available_htmodes: [
 | 
			
		||||
                            "NOHT",
 | 
			
		||||
                            "HT20",
 | 
			
		||||
                            "HT40",
 | 
			
		||||
                        ],
 | 
			
		||||
                        hwmode: "11g",
 | 
			
		||||
                    },
 | 
			
		||||
                ],
 | 
			
		||||
                channel: 11,
 | 
			
		||||
                enabled: false,
 | 
			
		||||
                guest_wifi: {
 | 
			
		||||
                    SSID: "TestSSID",
 | 
			
		||||
                    enabled: false,
 | 
			
		||||
                    password: "",
 | 
			
		||||
                },
 | 
			
		||||
                hidden: false,
 | 
			
		||||
                htmode: "HT40",
 | 
			
		||||
                hwmode: "11g",
 | 
			
		||||
                id: 1,
 | 
			
		||||
                password: "TestPass",
 | 
			
		||||
            },
 | 
			
		||||
        ],
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,912 @@
 | 
			
		||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
 | 
			
		||||
 | 
			
		||||
exports[`<WiFiSettings/> Snapshot 2.4 GHz 1`] = `
 | 
			
		||||
"Snapshot Diff:
 | 
			
		||||
- First value
 | 
			
		||||
+ Second value
 | 
			
		||||
 | 
			
		||||
@@ -246,207 +246,95 @@
 | 
			
		||||
              value=\\"0\\"
 | 
			
		||||
            >
 | 
			
		||||
              auto
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"36\\"
 | 
			
		||||
+             value=\\"1\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         36
 | 
			
		||||
-                         (5180 MHz )
 | 
			
		||||
+                         1
 | 
			
		||||
+                         (2412 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"40\\"
 | 
			
		||||
+             value=\\"2\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         40
 | 
			
		||||
-                         (5200 MHz )
 | 
			
		||||
+                         2
 | 
			
		||||
+                         (2417 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"44\\"
 | 
			
		||||
+             value=\\"3\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         44
 | 
			
		||||
-                         (5220 MHz )
 | 
			
		||||
+                         3
 | 
			
		||||
+                         (2422 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"48\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         48
 | 
			
		||||
-                         (5240 MHz )
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"52\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         52
 | 
			
		||||
-                         (5260 MHz  ,DFS)
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"56\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         56
 | 
			
		||||
-                         (5280 MHz  ,DFS)
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"60\\"
 | 
			
		||||
+             value=\\"4\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         60
 | 
			
		||||
-                         (5300 MHz  ,DFS)
 | 
			
		||||
+                         4
 | 
			
		||||
+                         (2427 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"64\\"
 | 
			
		||||
+             value=\\"5\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         64
 | 
			
		||||
-                         (5320 MHz  ,DFS)
 | 
			
		||||
+                         5
 | 
			
		||||
+                         (2432 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"100\\"
 | 
			
		||||
+             value=\\"6\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         100
 | 
			
		||||
-                         (5500 MHz  ,DFS)
 | 
			
		||||
+                         6
 | 
			
		||||
+                         (2437 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"104\\"
 | 
			
		||||
+             value=\\"7\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         104
 | 
			
		||||
-                         (5520 MHz  ,DFS)
 | 
			
		||||
+                         7
 | 
			
		||||
+                         (2442 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"108\\"
 | 
			
		||||
+             value=\\"8\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         108
 | 
			
		||||
-                         (5540 MHz  ,DFS)
 | 
			
		||||
+                         8
 | 
			
		||||
+                         (2447 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"112\\"
 | 
			
		||||
+             value=\\"9\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         112
 | 
			
		||||
-                         (5560 MHz  ,DFS)
 | 
			
		||||
+                         9
 | 
			
		||||
+                         (2452 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"116\\"
 | 
			
		||||
+             value=\\"10\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         116
 | 
			
		||||
-                         (5580 MHz  ,DFS)
 | 
			
		||||
+                         10
 | 
			
		||||
+                         (2457 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
            <option
 | 
			
		||||
-             value=\\"120\\"
 | 
			
		||||
+             value=\\"11\\"
 | 
			
		||||
            >
 | 
			
		||||
              
 | 
			
		||||
-                         120
 | 
			
		||||
-                         (5600 MHz  ,DFS)
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"124\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         124
 | 
			
		||||
-                         (5620 MHz  ,DFS)
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"128\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         128
 | 
			
		||||
-                         (5640 MHz  ,DFS)
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"132\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         132
 | 
			
		||||
-                         (5660 MHz  ,DFS)
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"136\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         136
 | 
			
		||||
-                         (5680 MHz  ,DFS)
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"140\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         140
 | 
			
		||||
-                         (5700 MHz  ,DFS)
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"144\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         144
 | 
			
		||||
-                         (5720 MHz  ,DFS)
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"149\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         149
 | 
			
		||||
-                         (5745 MHz )
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"153\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         153
 | 
			
		||||
-                         (5765 MHz )
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"157\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         157
 | 
			
		||||
-                         (5785 MHz )
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"161\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         161
 | 
			
		||||
-                         (5805 MHz )
 | 
			
		||||
-                     
 | 
			
		||||
-           </option>
 | 
			
		||||
-           <option
 | 
			
		||||
-             value=\\"165\\"
 | 
			
		||||
-           >
 | 
			
		||||
-             
 | 
			
		||||
-                         165
 | 
			
		||||
-                         (5825 MHz )
 | 
			
		||||
+                         11
 | 
			
		||||
+                         (2462 MHz )
 | 
			
		||||
                      
 | 
			
		||||
            </option>
 | 
			
		||||
          </select>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div"
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
exports[`<WiFiSettings/> Snapshot both modules disabled. 1`] = `
 | 
			
		||||
<DocumentFragment>
 | 
			
		||||
  <div
 | 
			
		||||
    class="col-sm-12 offset-lg-1 col-lg-10 p-0 mb-3"
 | 
			
		||||
  >
 | 
			
		||||
    <form>
 | 
			
		||||
      <h3>
 | 
			
		||||
        Wi-Fi 1
 | 
			
		||||
      </h3>
 | 
			
		||||
      <div
 | 
			
		||||
        class="form-group"
 | 
			
		||||
      >
 | 
			
		||||
        <div
 | 
			
		||||
          class="custom-control custom-checkbox "
 | 
			
		||||
        >
 | 
			
		||||
          <input
 | 
			
		||||
            class="custom-control-input"
 | 
			
		||||
            id="1"
 | 
			
		||||
            type="checkbox"
 | 
			
		||||
          />
 | 
			
		||||
          <label
 | 
			
		||||
            class="custom-control-label"
 | 
			
		||||
            for="1"
 | 
			
		||||
          >
 | 
			
		||||
            Enable
 | 
			
		||||
          </label>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <h3>
 | 
			
		||||
        Wi-Fi 2
 | 
			
		||||
      </h3>
 | 
			
		||||
      <div
 | 
			
		||||
        class="form-group"
 | 
			
		||||
      >
 | 
			
		||||
        <div
 | 
			
		||||
          class="custom-control custom-checkbox "
 | 
			
		||||
        >
 | 
			
		||||
          <input
 | 
			
		||||
            class="custom-control-input"
 | 
			
		||||
            id="2"
 | 
			
		||||
            type="checkbox"
 | 
			
		||||
          />
 | 
			
		||||
          <label
 | 
			
		||||
            class="custom-control-label"
 | 
			
		||||
            for="2"
 | 
			
		||||
          >
 | 
			
		||||
            Enable
 | 
			
		||||
          </label>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div
 | 
			
		||||
        class="text-right"
 | 
			
		||||
      >
 | 
			
		||||
        <button
 | 
			
		||||
          class="btn btn-primary  col-sm-12 col-lg-3"
 | 
			
		||||
          type="submit"
 | 
			
		||||
        >
 | 
			
		||||
            Save
 | 
			
		||||
        </button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </form>
 | 
			
		||||
  </div>
 | 
			
		||||
  <h4>
 | 
			
		||||
    Reset Wi-Fi Settings
 | 
			
		||||
  </h4>
 | 
			
		||||
  <p>
 | 
			
		||||
    
 | 
			
		||||
If a number of wireless cards doesn't match, you may try to reset the Wi-Fi settings. Note that this will remove the
 | 
			
		||||
current Wi-Fi configuration and restore the default values.
 | 
			
		||||
        
 | 
			
		||||
  </p>
 | 
			
		||||
  <div
 | 
			
		||||
    class="col-sm-12 offset-lg-1 col-lg-10 p-0 mb-3 text-right"
 | 
			
		||||
  >
 | 
			
		||||
    <button
 | 
			
		||||
      class="btn btn-warning col-sm-12 col-lg-3"
 | 
			
		||||
      type="button"
 | 
			
		||||
    >
 | 
			
		||||
        Reset Wi-Fi Settings
 | 
			
		||||
    </button>
 | 
			
		||||
  </div>
 | 
			
		||||
</DocumentFragment>
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
exports[`<WiFiSettings/> Snapshot guest network. 1`] = `
 | 
			
		||||
"Snapshot Diff:
 | 
			
		||||
- First value
 | 
			
		||||
+ Second value
 | 
			
		||||
 | 
			
		||||
@@ -475,10 +475,89 @@
 | 
			
		||||
          
 | 
			
		||||
              </small>
 | 
			
		||||
            </label>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
+       <div
 | 
			
		||||
+         class=\\"form-group\\"
 | 
			
		||||
+       >
 | 
			
		||||
+         <label
 | 
			
		||||
+           for=\\"20\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           SSID
 | 
			
		||||
+         </label>
 | 
			
		||||
+         <div
 | 
			
		||||
+           class=\\"input-group\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           <input
 | 
			
		||||
+             class=\\"form-control\\"
 | 
			
		||||
+             id=\\"20\\"
 | 
			
		||||
+             type=\\"text\\"
 | 
			
		||||
+             value=\\"TestGuestSSID\\"
 | 
			
		||||
+           />
 | 
			
		||||
+           <div
 | 
			
		||||
+             class=\\"input-group-append\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             <button
 | 
			
		||||
+               class=\\"input-group-text\\"
 | 
			
		||||
+               type=\\"button\\"
 | 
			
		||||
+             >
 | 
			
		||||
+               <img
 | 
			
		||||
+                 alt=\\"QR\\"
 | 
			
		||||
+                 src=\\"/reforis/static/reforis/imgs/QR_icon.svg\\"
 | 
			
		||||
+                 style=\\"opacity: 0.67;\\"
 | 
			
		||||
+                 width=\\"20\\"
 | 
			
		||||
+               />
 | 
			
		||||
+             </button>
 | 
			
		||||
+           </div>
 | 
			
		||||
+         </div>
 | 
			
		||||
+       </div>
 | 
			
		||||
+       <div
 | 
			
		||||
+         class=\\"form-group\\"
 | 
			
		||||
+       >
 | 
			
		||||
+         <label
 | 
			
		||||
+           for=\\"21\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           Password
 | 
			
		||||
+         </label>
 | 
			
		||||
+         <div
 | 
			
		||||
+           class=\\"input-group\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           <input
 | 
			
		||||
+             autocomplete=\\"new-password\\"
 | 
			
		||||
+             class=\\"form-control  is-invalid\\"
 | 
			
		||||
+             id=\\"21\\"
 | 
			
		||||
+             required=\\"\\"
 | 
			
		||||
+             type=\\"password\\"
 | 
			
		||||
+             value=\\"\\"
 | 
			
		||||
+           />
 | 
			
		||||
+           <div
 | 
			
		||||
+             class=\\"input-group-append\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             <button
 | 
			
		||||
+               class=\\"input-group-text\\"
 | 
			
		||||
+               type=\\"button\\"
 | 
			
		||||
+             >
 | 
			
		||||
+               <i
 | 
			
		||||
+                 class=\\"fa fa-eye\\"
 | 
			
		||||
+               />
 | 
			
		||||
+             </button>
 | 
			
		||||
+           </div>
 | 
			
		||||
+         </div>
 | 
			
		||||
+         <div
 | 
			
		||||
+           class=\\"invalid-feedback\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           Password must contain at least 8 symbols
 | 
			
		||||
+         </div>
 | 
			
		||||
+         <small
 | 
			
		||||
+           class=\\"form-text text-muted\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           
 | 
			
		||||
+         WPA2 pre-shared key, that is required to connect to the network.
 | 
			
		||||
+     
 | 
			
		||||
+         </small>
 | 
			
		||||
+       </div>
 | 
			
		||||
        <h3>
 | 
			
		||||
          Wi-Fi 2
 | 
			
		||||
        </h3>
 | 
			
		||||
        <div
 | 
			
		||||
          class=\\"form-group\\"
 | 
			
		||||
@@ -502,10 +581,11 @@
 | 
			
		||||
        <div
 | 
			
		||||
          class=\\"text-right\\"
 | 
			
		||||
        >
 | 
			
		||||
          <button
 | 
			
		||||
            class=\\"btn btn-primary  col-sm-12 col-lg-3\\"
 | 
			
		||||
+           disabled=\\"\\"
 | 
			
		||||
            type=\\"submit\\"
 | 
			
		||||
          >
 | 
			
		||||
              Save
 | 
			
		||||
          </button>
 | 
			
		||||
        </div>"
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
exports[`<WiFiSettings/> Snapshot one module enabled. 1`] = `
 | 
			
		||||
"Snapshot Diff:
 | 
			
		||||
- First value
 | 
			
		||||
+ Second value
 | 
			
		||||
 | 
			
		||||
@@ -23,10 +23,462 @@
 | 
			
		||||
            >
 | 
			
		||||
              Enable
 | 
			
		||||
            </label>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
+       <div
 | 
			
		||||
+         class=\\"form-group\\"
 | 
			
		||||
+       >
 | 
			
		||||
+         <label
 | 
			
		||||
+           for=\\"4\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           SSID
 | 
			
		||||
+         </label>
 | 
			
		||||
+         <div
 | 
			
		||||
+           class=\\"input-group\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           <input
 | 
			
		||||
+             class=\\"form-control\\"
 | 
			
		||||
+             id=\\"4\\"
 | 
			
		||||
+             required=\\"\\"
 | 
			
		||||
+             type=\\"text\\"
 | 
			
		||||
+             value=\\"TestSSID1\\"
 | 
			
		||||
+           />
 | 
			
		||||
+           <div
 | 
			
		||||
+             class=\\"input-group-append\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             <button
 | 
			
		||||
+               class=\\"input-group-text\\"
 | 
			
		||||
+               type=\\"button\\"
 | 
			
		||||
+             >
 | 
			
		||||
+               <img
 | 
			
		||||
+                 alt=\\"QR\\"
 | 
			
		||||
+                 src=\\"/reforis/static/reforis/imgs/QR_icon.svg\\"
 | 
			
		||||
+                 style=\\"opacity: 0.67;\\"
 | 
			
		||||
+                 width=\\"20\\"
 | 
			
		||||
+               />
 | 
			
		||||
+             </button>
 | 
			
		||||
+           </div>
 | 
			
		||||
+         </div>
 | 
			
		||||
+       </div>
 | 
			
		||||
+       <div
 | 
			
		||||
+         class=\\"form-group\\"
 | 
			
		||||
+       >
 | 
			
		||||
+         <label
 | 
			
		||||
+           for=\\"5\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           Password
 | 
			
		||||
+         </label>
 | 
			
		||||
+         <div
 | 
			
		||||
+           class=\\"input-group\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           <input
 | 
			
		||||
+             autocomplete=\\"new-password\\"
 | 
			
		||||
+             class=\\"form-control\\"
 | 
			
		||||
+             id=\\"5\\"
 | 
			
		||||
+             required=\\"\\"
 | 
			
		||||
+             type=\\"password\\"
 | 
			
		||||
+             value=\\"TestPass\\"
 | 
			
		||||
+           />
 | 
			
		||||
+           <div
 | 
			
		||||
+             class=\\"input-group-append\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             <button
 | 
			
		||||
+               class=\\"input-group-text\\"
 | 
			
		||||
+               type=\\"button\\"
 | 
			
		||||
+             >
 | 
			
		||||
+               <i
 | 
			
		||||
+                 class=\\"fa fa-eye\\"
 | 
			
		||||
+               />
 | 
			
		||||
+             </button>
 | 
			
		||||
+           </div>
 | 
			
		||||
+         </div>
 | 
			
		||||
+         <small
 | 
			
		||||
+           class=\\"form-text text-muted\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           
 | 
			
		||||
+         WPA2 pre-shared key, that is required to connect to the network.
 | 
			
		||||
+     
 | 
			
		||||
+         </small>
 | 
			
		||||
+       </div>
 | 
			
		||||
+       <div
 | 
			
		||||
+         class=\\"form-group\\"
 | 
			
		||||
+       >
 | 
			
		||||
+         <div
 | 
			
		||||
+           class=\\"custom-control custom-checkbox \\"
 | 
			
		||||
+         >
 | 
			
		||||
+           <input
 | 
			
		||||
+             class=\\"custom-control-input\\"
 | 
			
		||||
+             id=\\"6\\"
 | 
			
		||||
+             type=\\"checkbox\\"
 | 
			
		||||
+           />
 | 
			
		||||
+           <label
 | 
			
		||||
+             class=\\"custom-control-label\\"
 | 
			
		||||
+             for=\\"6\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             Hide SSID
 | 
			
		||||
+             <small
 | 
			
		||||
+               class=\\"form-text text-muted\\"
 | 
			
		||||
+             >
 | 
			
		||||
+               If set, network is not visible when scanning for available networks.
 | 
			
		||||
+             </small>
 | 
			
		||||
+           </label>
 | 
			
		||||
+         </div>
 | 
			
		||||
+       </div>
 | 
			
		||||
+       <div
 | 
			
		||||
+         class=\\"form-group\\"
 | 
			
		||||
+       >
 | 
			
		||||
+         <label
 | 
			
		||||
+           class=\\"d-block\\"
 | 
			
		||||
+           for=\\"7\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           GHz
 | 
			
		||||
+         </label>
 | 
			
		||||
+         <div
 | 
			
		||||
+           class=\\"custom-control custom-radio custom-control-inline\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           <input
 | 
			
		||||
+             class=\\"custom-control-input\\"
 | 
			
		||||
+             id=\\"hwmode-0-0\\"
 | 
			
		||||
+             name=\\"hwmode-0\\"
 | 
			
		||||
+             type=\\"radio\\"
 | 
			
		||||
+             value=\\"11g\\"
 | 
			
		||||
+           />
 | 
			
		||||
+           <label
 | 
			
		||||
+             class=\\"custom-control-label\\"
 | 
			
		||||
+             for=\\"hwmode-0-0\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             2.4
 | 
			
		||||
+           </label>
 | 
			
		||||
+         </div>
 | 
			
		||||
+         <div
 | 
			
		||||
+           class=\\"custom-control custom-radio custom-control-inline\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           <input
 | 
			
		||||
+             checked=\\"\\"
 | 
			
		||||
+             class=\\"custom-control-input\\"
 | 
			
		||||
+             id=\\"hwmode-0-1\\"
 | 
			
		||||
+             name=\\"hwmode-0\\"
 | 
			
		||||
+             type=\\"radio\\"
 | 
			
		||||
+             value=\\"11a\\"
 | 
			
		||||
+           />
 | 
			
		||||
+           <label
 | 
			
		||||
+             class=\\"custom-control-label\\"
 | 
			
		||||
+             for=\\"hwmode-0-1\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             5
 | 
			
		||||
+           </label>
 | 
			
		||||
+         </div>
 | 
			
		||||
+         <small
 | 
			
		||||
+           class=\\"form-text text-muted\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           
 | 
			
		||||
+         The 2.4 GHz band is more widely supported by clients, but tends to have more interference. The 5 GHz band is a
 | 
			
		||||
+         newer standard and may not be supported by all your devices. It usually has less interference, but the signal
 | 
			
		||||
+         does not carry so well indoors.
 | 
			
		||||
+         </small>
 | 
			
		||||
+       </div>
 | 
			
		||||
+       <div
 | 
			
		||||
+         class=\\"form-group\\"
 | 
			
		||||
+       >
 | 
			
		||||
+         <label
 | 
			
		||||
+           for=\\"8\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           802.11n/ac mode
 | 
			
		||||
+         </label>
 | 
			
		||||
+         <select
 | 
			
		||||
+           class=\\"custom-select\\"
 | 
			
		||||
+           id=\\"8\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"NOHT\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             Disabled
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"HT20\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             802.11n - 20 MHz wide channel
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"HT40\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             802.11n - 40 MHz wide channel
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"VHT20\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             802.11ac - 20 MHz wide channel
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"VHT40\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             802.11ac - 40 MHz wide channel
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"VHT80\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             802.11ac - 80 MHz wide channel
 | 
			
		||||
+           </option>
 | 
			
		||||
+         </select>
 | 
			
		||||
+         <small
 | 
			
		||||
+           class=\\"form-text text-muted\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           
 | 
			
		||||
+         Change this to adjust 802.11n/ac mode of operation. 802.11n with 40 MHz wide channels can yield higher
 | 
			
		||||
+         throughput but can cause more interference in the network. If you don't know what to choose, use the default
 | 
			
		||||
+         option with 20 MHz wide channel.
 | 
			
		||||
+     
 | 
			
		||||
+         </small>
 | 
			
		||||
+       </div>
 | 
			
		||||
+       <div
 | 
			
		||||
+         class=\\"form-group\\"
 | 
			
		||||
+       >
 | 
			
		||||
+         <label
 | 
			
		||||
+           for=\\"9\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           Channel
 | 
			
		||||
+         </label>
 | 
			
		||||
+         <select
 | 
			
		||||
+           class=\\"custom-select\\"
 | 
			
		||||
+           id=\\"9\\"
 | 
			
		||||
+         >
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"0\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             auto
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"36\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         36
 | 
			
		||||
+                         (5180 MHz )
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"40\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         40
 | 
			
		||||
+                         (5200 MHz )
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"44\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         44
 | 
			
		||||
+                         (5220 MHz )
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"48\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         48
 | 
			
		||||
+                         (5240 MHz )
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"52\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         52
 | 
			
		||||
+                         (5260 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"56\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         56
 | 
			
		||||
+                         (5280 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"60\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         60
 | 
			
		||||
+                         (5300 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"64\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         64
 | 
			
		||||
+                         (5320 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"100\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         100
 | 
			
		||||
+                         (5500 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"104\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         104
 | 
			
		||||
+                         (5520 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"108\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         108
 | 
			
		||||
+                         (5540 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"112\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         112
 | 
			
		||||
+                         (5560 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"116\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         116
 | 
			
		||||
+                         (5580 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"120\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         120
 | 
			
		||||
+                         (5600 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"124\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         124
 | 
			
		||||
+                         (5620 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"128\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         128
 | 
			
		||||
+                         (5640 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"132\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         132
 | 
			
		||||
+                         (5660 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"136\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         136
 | 
			
		||||
+                         (5680 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"140\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         140
 | 
			
		||||
+                         (5700 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"144\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         144
 | 
			
		||||
+                         (5720 MHz  ,DFS)
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"149\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         149
 | 
			
		||||
+                         (5745 MHz )
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"153\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         153
 | 
			
		||||
+                         (5765 MHz )
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"157\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         157
 | 
			
		||||
+                         (5785 MHz )
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"161\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         161
 | 
			
		||||
+                         (5805 MHz )
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+           <option
 | 
			
		||||
+             value=\\"165\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             
 | 
			
		||||
+                         165
 | 
			
		||||
+                         (5825 MHz )
 | 
			
		||||
+                     
 | 
			
		||||
+           </option>
 | 
			
		||||
+         </select>
 | 
			
		||||
+       </div>
 | 
			
		||||
+       <div
 | 
			
		||||
+         class=\\"form-group\\"
 | 
			
		||||
+       >
 | 
			
		||||
+         <div
 | 
			
		||||
+           class=\\"custom-control custom-checkbox \\"
 | 
			
		||||
+         >
 | 
			
		||||
+           <input
 | 
			
		||||
+             class=\\"custom-control-input\\"
 | 
			
		||||
+             id=\\"10\\"
 | 
			
		||||
+             type=\\"checkbox\\"
 | 
			
		||||
+           />
 | 
			
		||||
+           <label
 | 
			
		||||
+             class=\\"custom-control-label\\"
 | 
			
		||||
+             for=\\"10\\"
 | 
			
		||||
+           >
 | 
			
		||||
+             Enable Guest Wifi
 | 
			
		||||
+             <small
 | 
			
		||||
+               class=\\"form-text text-muted\\"
 | 
			
		||||
+             >
 | 
			
		||||
+               
 | 
			
		||||
+         Enables Wi-Fi for guests, which is separated from LAN network. Devices connected to this network are allowed to
 | 
			
		||||
+         access the internet, but aren't allowed to access other devices and the configuration interface of the router.
 | 
			
		||||
+         Parameters of the guest network can be set in the Guest network tab.
 | 
			
		||||
+         
 | 
			
		||||
+             </small>
 | 
			
		||||
+           </label>
 | 
			
		||||
+         </div>
 | 
			
		||||
+       </div>
 | 
			
		||||
        <h3>
 | 
			
		||||
          Wi-Fi 2
 | 
			
		||||
        </h3>
 | 
			
		||||
        <div
 | 
			
		||||
          class=\\"form-group\\""
 | 
			
		||||
`;
 | 
			
		||||
							
								
								
									
										39
									
								
								src/common/WiFiSettings/constants.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/common/WiFiSettings/constants.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free software, licensed under the GNU General Public License v3.
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
export const HTMODES = {
 | 
			
		||||
    NOHT: _("Disabled"),
 | 
			
		||||
    HT20: _("802.11n - 20 MHz wide channel"),
 | 
			
		||||
    HT40: _("802.11n - 40 MHz wide channel"),
 | 
			
		||||
    VHT20: _("802.11ac - 20 MHz wide channel"),
 | 
			
		||||
    VHT40: _("802.11ac - 40 MHz wide channel"),
 | 
			
		||||
    VHT80: _("802.11ac - 80 MHz wide channel"),
 | 
			
		||||
};
 | 
			
		||||
export const HWMODES = {
 | 
			
		||||
    "11g": "2.4",
 | 
			
		||||
    "11a": "5",
 | 
			
		||||
};
 | 
			
		||||
export const HELP_TEXTS = {
 | 
			
		||||
    password: _(`
 | 
			
		||||
        WPA2 pre-shared key, that is required to connect to the network.
 | 
			
		||||
    `),
 | 
			
		||||
    hidden: _("If set, network is not visible when scanning for available networks."),
 | 
			
		||||
    hwmode: _(`
 | 
			
		||||
        The 2.4 GHz band is more widely supported by clients, but tends to have more interference. The 5 GHz band is a
 | 
			
		||||
        newer standard and may not be supported by all your devices. It usually has less interference, but the signal
 | 
			
		||||
        does not carry so well indoors.`),
 | 
			
		||||
    htmode: _(`
 | 
			
		||||
        Change this to adjust 802.11n/ac mode of operation. 802.11n with 40 MHz wide channels can yield higher
 | 
			
		||||
        throughput but can cause more interference in the network. If you don't know what to choose, use the default
 | 
			
		||||
        option with 20 MHz wide channel.
 | 
			
		||||
    `),
 | 
			
		||||
    guest_wifi_enabled: _(`
 | 
			
		||||
        Enables Wi-Fi for guests, which is separated from LAN network. Devices connected to this network are allowed to
 | 
			
		||||
        access the internet, but aren't allowed to access other devices and the configuration interface of the router.
 | 
			
		||||
        Parameters of the guest network can be set in the Guest network tab.
 | 
			
		||||
        `),
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										28
									
								
								src/common/WiFiSettings/qrCodeHelpers.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/common/WiFiSettings/qrCodeHelpers.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2019 CZ.NIC z.s.p.o. (http://www.nic.cz/)
 | 
			
		||||
 *
 | 
			
		||||
 * This is free software, licensed under the GNU General Public License v3.
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import pdfMake from "pdfmake";
 | 
			
		||||
 | 
			
		||||
export function createAndDownloadPdf(SSID, password) {
 | 
			
		||||
    const docDefinition = {
 | 
			
		||||
        content: [
 | 
			
		||||
            {
 | 
			
		||||
                text: "Wi-Fi", style: "header", fontSize: 55, alignment: "center",
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                qr: toQRCodeContent(SSID, password), fit: "350", margin: [0, 80], alignment: "center",
 | 
			
		||||
            },
 | 
			
		||||
            { text: `SSID: ${SSID}`, fontSize: 25, alignment: "center" },
 | 
			
		||||
            { text: `Password: ${password}`, fontSize: 25, alignment: "center" },
 | 
			
		||||
        ],
 | 
			
		||||
    };
 | 
			
		||||
    pdfMake.createPdf(docDefinition).download("wifi.pdf");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function toQRCodeContent(SSID, password) {
 | 
			
		||||
    return `WIFI:S:${SSID};T:WPA2;P:${password};;`;
 | 
			
		||||
}
 | 
			
		||||
@@ -7,7 +7,9 @@
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
 | 
			
		||||
import { fireEvent, getByText, queryByText, render, wait } from "customTestRender";
 | 
			
		||||
import {
 | 
			
		||||
    fireEvent, getByText, queryByText, render, wait,
 | 
			
		||||
} from "customTestRender";
 | 
			
		||||
import mockAxios from "jest-mock-axios";
 | 
			
		||||
import { mockJSONError } from "testUtils/network";
 | 
			
		||||
import { mockSetAlert } from "testUtils/alertContextMock";
 | 
			
		||||
@@ -18,8 +20,8 @@ describe("<RebootButton/>", () => {
 | 
			
		||||
    let componentContainer;
 | 
			
		||||
    beforeEach(() => {
 | 
			
		||||
        const { container } = render(<>
 | 
			
		||||
            <div id="modal-container"/>
 | 
			
		||||
            <RebootButton/>
 | 
			
		||||
            <div id="modal-container" />
 | 
			
		||||
            <RebootButton />
 | 
			
		||||
        </>);
 | 
			
		||||
        componentContainer = container;
 | 
			
		||||
    });
 | 
			
		||||
@@ -51,5 +53,4 @@ describe("<RebootButton/>", () => {
 | 
			
		||||
        await wait(() => expect(mockSetAlert)
 | 
			
		||||
            .toBeCalledWith("Reboot request failed."));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -12,17 +12,17 @@ import { STATES, SubmitButton } from "../components/SubmitButton";
 | 
			
		||||
 | 
			
		||||
describe("<SubmitButton/>", () => {
 | 
			
		||||
    it("Render ready", () => {
 | 
			
		||||
        const { container } = render(<SubmitButton state={STATES.READY}/>);
 | 
			
		||||
        const { container } = render(<SubmitButton state={STATES.READY} />);
 | 
			
		||||
        expect(container)
 | 
			
		||||
            .toMatchSnapshot();
 | 
			
		||||
    });
 | 
			
		||||
    it("Render saving", () => {
 | 
			
		||||
        const { container } = render(<SubmitButton state={STATES.SAVING}/>);
 | 
			
		||||
        const { container } = render(<SubmitButton state={STATES.SAVING} />);
 | 
			
		||||
        expect(container)
 | 
			
		||||
            .toMatchSnapshot();
 | 
			
		||||
    });
 | 
			
		||||
    it("Render load", () => {
 | 
			
		||||
        const { container } = render(<SubmitButton state={STATES.LOAD}/>);
 | 
			
		||||
        const { container } = render(<SubmitButton state={STATES.LOAD} />);
 | 
			
		||||
        expect(container)
 | 
			
		||||
            .toMatchSnapshot();
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -5,99 +5,98 @@
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import React from "react";
 | 
			
		||||
 | 
			
		||||
import { act, fireEvent, render, waitForElement } from 'customTestRender';
 | 
			
		||||
import mockAxios from 'jest-mock-axios';
 | 
			
		||||
import { ForisForm } from "../components/ForisForm";
 | 
			
		||||
import {
 | 
			
		||||
    act, fireEvent, render, waitForElement,
 | 
			
		||||
} from "customTestRender";
 | 
			
		||||
import mockAxios from "jest-mock-axios";
 | 
			
		||||
import { WebSockets } from "webSockets/WebSockets";
 | 
			
		||||
 | 
			
		||||
import { ForisForm } from "../components/ForisForm";
 | 
			
		||||
 | 
			
		||||
// It's possible to unittest each hooks via react-hooks-testing-library.
 | 
			
		||||
// But it's better and easier to test it by test components which uses this hooks.
 | 
			
		||||
 | 
			
		||||
const TestForm = ({formData, formErrors, setFormValue}) => {
 | 
			
		||||
    return <>
 | 
			
		||||
const TestForm = ({ formData, formErrors, setFormValue }) => (
 | 
			
		||||
    <>
 | 
			
		||||
        <input
 | 
			
		||||
            data-testid='test-input'
 | 
			
		||||
            data-testid="test-input"
 | 
			
		||||
            value={formData.field}
 | 
			
		||||
            onChange={setFormValue(value => ({field: {$set: value}}))}
 | 
			
		||||
            onChange={setFormValue((value) => ({ field: { $set: value } }))}
 | 
			
		||||
        />
 | 
			
		||||
        <p>{formErrors.field}</p>
 | 
			
		||||
    </>
 | 
			
		||||
};
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
describe('useForm hook.', () => {
 | 
			
		||||
describe("useForm hook.", () => {
 | 
			
		||||
    let mockValidator;
 | 
			
		||||
    let mockPrepData;
 | 
			
		||||
    let mockPrepDataToSubmit;
 | 
			
		||||
    let input;
 | 
			
		||||
    let form;
 | 
			
		||||
    const Child = jest.fn(props => <TestForm {...props}/>);
 | 
			
		||||
    const Child = jest.fn((props) => <TestForm {...props} />);
 | 
			
		||||
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        mockPrepData = jest.fn(() => ({field: 'preparedData'}));
 | 
			
		||||
        mockPrepDataToSubmit = jest.fn(() => ({field: 'preparedDataToSubmit'}));
 | 
			
		||||
        mockValidator = jest.fn(data => data.field === 'invalidValue' ? {field: 'Error'} : {});
 | 
			
		||||
        const {getByTestId, container} = render(
 | 
			
		||||
        mockPrepData = jest.fn(() => ({ field: "preparedData" }));
 | 
			
		||||
        mockPrepDataToSubmit = jest.fn(() => ({ field: "preparedDataToSubmit" }));
 | 
			
		||||
        mockValidator = jest.fn((data) => (data.field === "invalidValue" ? { field: "Error" } : {}));
 | 
			
		||||
        const { getByTestId, container } = render(
 | 
			
		||||
            <ForisForm
 | 
			
		||||
                ws={new WebSockets()}
 | 
			
		||||
                // Just some module which exists...
 | 
			
		||||
                forisConfig={{
 | 
			
		||||
                    endpoint: 'testEndpoint',
 | 
			
		||||
                    wsModule: 'testWSModule'
 | 
			
		||||
                    endpoint: "testEndpoint",
 | 
			
		||||
                    wsModule: "testWSModule",
 | 
			
		||||
                }}
 | 
			
		||||
                prepData={mockPrepData}
 | 
			
		||||
                prepDataToSubmit={mockPrepDataToSubmit}
 | 
			
		||||
                validator={mockValidator}
 | 
			
		||||
            >
 | 
			
		||||
                <Child/>
 | 
			
		||||
            </ForisForm>
 | 
			
		||||
                <Child />
 | 
			
		||||
            </ForisForm>,
 | 
			
		||||
        );
 | 
			
		||||
        mockAxios.mockResponse({field: 'fetchedData'});
 | 
			
		||||
        mockAxios.mockResponse({ field: "fetchedData" });
 | 
			
		||||
 | 
			
		||||
        input = await waitForElement(() =>
 | 
			
		||||
            getByTestId('test-input')
 | 
			
		||||
        );
 | 
			
		||||
        input = await waitForElement(() => getByTestId("test-input"));
 | 
			
		||||
        form = container.firstChild.firstChild;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Validation on changing.', () => {
 | 
			
		||||
    it("Validation on changing.", () => {
 | 
			
		||||
        expect(mockValidator).toHaveBeenCalledTimes(1);
 | 
			
		||||
        expect(Child).toHaveBeenCalledTimes(1);
 | 
			
		||||
        expect(Child.mock.calls[0][0].formErrors).toMatchObject({});
 | 
			
		||||
 | 
			
		||||
        act(() => {
 | 
			
		||||
            fireEvent.change(input, {target: {value: 'invalidValue', type: 'text'}});
 | 
			
		||||
            fireEvent.change(input, { target: { value: "invalidValue", type: "text" } });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        expect(Child).toHaveBeenCalledTimes(2);
 | 
			
		||||
        expect(mockValidator).toHaveBeenCalledTimes(2);
 | 
			
		||||
        expect(Child.mock.calls[1][0].formErrors).toMatchObject({field: 'Error'});
 | 
			
		||||
        expect(Child.mock.calls[1][0].formErrors).toMatchObject({ field: "Error" });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Update text value.', () => {
 | 
			
		||||
        fireEvent.change(input, {target: {value: 'newValue', type: 'text'}})
 | 
			
		||||
        expect(input.value).toBe('newValue');
 | 
			
		||||
    it("Update text value.", () => {
 | 
			
		||||
        fireEvent.change(input, { target: { value: "newValue", type: "text" } });
 | 
			
		||||
        expect(input.value).toBe("newValue");
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Update text value.', () => {
 | 
			
		||||
        fireEvent.change(input, {target: {value: 123, type: 'number'}})
 | 
			
		||||
        expect(input.value).toBe('123');
 | 
			
		||||
    it("Update text value.", () => {
 | 
			
		||||
        fireEvent.change(input, { target: { value: 123, type: "number" } });
 | 
			
		||||
        expect(input.value).toBe("123");
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Update checkbox value.', () => {
 | 
			
		||||
        fireEvent.change(input, {target: {checked: true, type: 'checkbox'}})
 | 
			
		||||
    it("Update checkbox value.", () => {
 | 
			
		||||
        fireEvent.change(input, { target: { checked: true, type: "checkbox" } });
 | 
			
		||||
        expect(input.checked).toBe(true);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Fetch data.', () => {
 | 
			
		||||
        expect(mockAxios.get).toHaveBeenCalledWith('testEndpoint', expect.anything());
 | 
			
		||||
    it("Fetch data.", () => {
 | 
			
		||||
        expect(mockAxios.get).toHaveBeenCalledWith("testEndpoint", expect.anything());
 | 
			
		||||
        expect(mockPrepData).toHaveBeenCalledTimes(1);
 | 
			
		||||
        expect(Child.mock.calls[0][0].formData).toMatchObject({field: 'preparedData'});
 | 
			
		||||
        expect(Child.mock.calls[0][0].formData).toMatchObject({ field: "preparedData" });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('Submit.', () => {
 | 
			
		||||
    it("Submit.", () => {
 | 
			
		||||
        expect(mockAxios.get).toHaveBeenCalledTimes(1);
 | 
			
		||||
        expect(mockPrepDataToSubmit).toHaveBeenCalledTimes(0);
 | 
			
		||||
 | 
			
		||||
@@ -106,8 +105,8 @@ describe('useForm hook.', () => {
 | 
			
		||||
        expect(mockPrepDataToSubmit).toHaveBeenCalledTimes(1);
 | 
			
		||||
        expect(mockAxios.post).toHaveBeenCalledTimes(1);
 | 
			
		||||
        expect(mockAxios.post).toHaveBeenCalledWith(
 | 
			
		||||
            'testEndpoint',
 | 
			
		||||
            {'field': 'preparedDataToSubmit'},
 | 
			
		||||
            "testEndpoint",
 | 
			
		||||
            { field: "preparedDataToSubmit" },
 | 
			
		||||
            expect.anything(),
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ import {
 | 
			
		||||
    validateIPv4Address,
 | 
			
		||||
    validateIPv6Address,
 | 
			
		||||
    validateIPv6Prefix,
 | 
			
		||||
    validateMAC
 | 
			
		||||
    validateMAC,
 | 
			
		||||
} from "validations";
 | 
			
		||||
 | 
			
		||||
describe("Validation functions", () => {
 | 
			
		||||
@@ -50,7 +50,6 @@ describe("Validation functions", () => {
 | 
			
		||||
            .toBe(undefined);
 | 
			
		||||
        expect(validateIPv6Address("::"))
 | 
			
		||||
            .toBe(undefined);
 | 
			
		||||
 | 
			
		||||
    });
 | 
			
		||||
    it("validateIPv6Address invalid", () => {
 | 
			
		||||
        expect(validateIPv6Address("invalid"))
 | 
			
		||||
@@ -85,7 +84,6 @@ describe("Validation functions", () => {
 | 
			
		||||
            .toBe(undefined);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    it("validateDomain valid", () => {
 | 
			
		||||
        expect(validateDomain("example.com"))
 | 
			
		||||
            .toBe(undefined);
 | 
			
		||||
@@ -108,7 +106,6 @@ describe("Validation functions", () => {
 | 
			
		||||
            .toBe(undefined);
 | 
			
		||||
        expect(validateDUID("ABCDEF12AB"))
 | 
			
		||||
            .toBe(undefined);
 | 
			
		||||
 | 
			
		||||
    });
 | 
			
		||||
    it("validateDUID invalid", () => {
 | 
			
		||||
        expect(validateDUID("gggggggg"))
 | 
			
		||||
 
 | 
			
		||||
@@ -45,6 +45,7 @@ export {
 | 
			
		||||
 | 
			
		||||
// Common
 | 
			
		||||
export { RebootButton } from "./common/RebootButton";
 | 
			
		||||
export { WiFiSettings } from "./common/WiFiSettings/WiFiSettings";
 | 
			
		||||
 | 
			
		||||
// Form
 | 
			
		||||
export { ForisForm } from "./form/components/ForisForm";
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ window.AlertContext = React.createContext();
 | 
			
		||||
function AlertContextMock({ children }) {
 | 
			
		||||
    return (
 | 
			
		||||
        <AlertContext.Provider value={[mockSetAlert, mockDismissAlert]}>
 | 
			
		||||
                { children }
 | 
			
		||||
            { children }
 | 
			
		||||
        </AlertContext.Provider>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import mockAxios from 'jest-mock-axios';
 | 
			
		||||
import mockAxios from "jest-mock-axios";
 | 
			
		||||
 | 
			
		||||
export function mockJSONError(data) {
 | 
			
		||||
    mockAxios.mockError({ response: { data, headers: { "content-type": "application/json" } } });
 | 
			
		||||
 
 | 
			
		||||
@@ -5,8 +5,8 @@
 | 
			
		||||
 * See /LICENSE for more information.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
import mockAxios from 'jest-mock-axios';
 | 
			
		||||
import moment from 'moment-timezone';
 | 
			
		||||
import mockAxios from "jest-mock-axios";
 | 
			
		||||
import moment from "moment-timezone";
 | 
			
		||||
 | 
			
		||||
// Setup axios cleanup
 | 
			
		||||
global.afterEach(() => {
 | 
			
		||||
@@ -14,9 +14,9 @@ global.afterEach(() => {
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// Mock babel (gettext)
 | 
			
		||||
global._ = str => str;
 | 
			
		||||
global.ngettext = str => str;
 | 
			
		||||
global.babel = {format: (str) => str};
 | 
			
		||||
global._ = (str) => str;
 | 
			
		||||
global.ngettext = (str) => str;
 | 
			
		||||
global.babel = { format: (str) => str };
 | 
			
		||||
global.ForisTranslations = {};
 | 
			
		||||
 | 
			
		||||
// Mock web sockets
 | 
			
		||||
@@ -25,9 +25,9 @@ window.WebSocket = jest.fn();
 | 
			
		||||
// Mock scrollIntoView
 | 
			
		||||
global.HTMLElement.prototype.scrollIntoView = () => {};
 | 
			
		||||
 | 
			
		||||
jest.doMock('moment', () => {
 | 
			
		||||
    moment.tz.setDefault('UTC');
 | 
			
		||||
// Mock timezone utilities
 | 
			
		||||
jest.doMock("moment", () => {
 | 
			
		||||
    moment.tz.setDefault("UTC");
 | 
			
		||||
    return moment;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
Date.now = jest.fn(() => new Date(Date.UTC(2019, 1, 1, 12, 13, 14)).valueOf());
 | 
			
		||||
 
 | 
			
		||||
@@ -7,10 +7,10 @@
 | 
			
		||||
 | 
			
		||||
import React from "react";
 | 
			
		||||
import { render } from "customTestRender";
 | 
			
		||||
import { API_STATE } from "api/utils";
 | 
			
		||||
import {
 | 
			
		||||
    withEither, withSpinner, withSending, withSpinnerOnSending, withError, withErrorMessage,
 | 
			
		||||
} from "../conditionalHOCs";
 | 
			
		||||
import { API_STATE } from "api/utils";
 | 
			
		||||
 | 
			
		||||
describe("conditional HOCs", () => {
 | 
			
		||||
    const First = () => <p>First</p>;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user