diff --git a/.eslintrc b/.eslintrc
index 775ef8fd..06a1b38d 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,46 +1,10 @@
{
"root": true,
"extends": [
- "airbnb",
- "airbnb-typescript",
- "plugin:@typescript-eslint/recommended"
+ "@shlinkio/js-coding-standard"
],
"parserOptions": {
"project": "./tsconfig.json"
},
- "ignorePatterns": ["src/service*.ts"],
- "rules": {
- "object-curly-newline": "off",
- "implicit-arrow-linebreak": "off",
- "no-restricted-globals": "off",
- "default-case": "off",
- "max-len": ["error", { "code": 120, "ignoreComments": true, "ignoreStrings": true, "ignoreTemplateLiterals": true }],
- "import/no-cycle": "off",
- "import/prefer-default-export": "off",
- "import/no-extraneous-dependencies": "off",
- "react/react-in-jsx-scope": "off",
- "react/prop-types": "off",
- "react/require-default-props": "off",
- "react/function-component-definition": "off",
- "react/no-array-index-key": "off",
- "react/no-unstable-nested-components": "off",
- "react/jsx-one-expression-per-line": "off",
- "react/jsx-props-no-spreading": "off",
- "react/jsx-no-useless-fragment": "off",
- "@typescript-eslint/no-unused-expressions": "off",
- "@typescript-eslint/ban-types": "off",
- "@typescript-eslint/no-explicit-any": "off",
- "@typescript-eslint/lines-between-class-members": "off"
- },
- "overrides": [
- {
- "files": ["*.test.*"],
- "rules": {
- "prefer-promise-reject-errors": "off",
- "no-param-reassign": "off",
- "react/no-children-prop": "off",
- "@typescript-eslint/no-shadow": "off"
- }
- }
- ]
+ "ignorePatterns": ["src/service*.ts"]
}
diff --git a/package-lock.json b/package-lock.json
index dc8d2f07..0d6b632c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -50,6 +50,7 @@
"workbox-strategies": "^6.5.1"
},
"devDependencies": {
+ "@shlinkio/eslint-config-js-coding-standard": "~2.0.0",
"@stryker-mutator/core": "^5.6.1",
"@stryker-mutator/jest-runner": "^5.6.1",
"@stryker-mutator/typescript-checker": "^5.6.1",
@@ -68,8 +69,6 @@
"@types/react-redux": "^7.1.23",
"@types/react-tag-autocomplete": "^6.1.1",
"@types/uuid": "^8.3.4",
- "@typescript-eslint/eslint-plugin": "^5.16.0",
- "@typescript-eslint/parser": "^5.16.0",
"@wojtekmaj/enzyme-adapter-react-17": "0.6.5",
"adm-zip": "^0.5.9",
"babel-jest": "^27.5.1",
@@ -77,8 +76,6 @@
"dart-sass": "^1.25.0",
"enzyme": "^3.11.0",
"eslint": "^8.12.0",
- "eslint-config-airbnb": "^19.0.4",
- "eslint-config-airbnb-typescript": "^16.1.4",
"identity-obj-proxy": "^3.0.0",
"jest": "^27.5.1",
"react-scripts": "^5.0.0",
@@ -3485,6 +3482,21 @@
"integrity": "sha512-BUyKJGdDWqvWC5GEhyOiUrGNi9iJUr4CU0O2WxJL6QJhHeeA/NVBalH+FeK0r/x/W0rPymXt5s78TDS7d6lCwg==",
"dev": true
},
+ "node_modules/@shlinkio/eslint-config-js-coding-standard": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@shlinkio/eslint-config-js-coding-standard/-/eslint-config-js-coding-standard-2.0.0.tgz",
+ "integrity": "sha512-yD/+NVu3vxcA23ptsFGxX827+tZgGfBoWMonRcliG56HOMYDrf7OET7f7Xvi1or2U0PLQDOPRShk4IlR3Km6kA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/eslint-plugin": "^5.16.0",
+ "@typescript-eslint/parser": "^5.16.0",
+ "eslint-config-airbnb": "^19.0.4",
+ "eslint-config-airbnb-typescript": "^16.1.4"
+ },
+ "peerDependencies": {
+ "eslint": "^8.12.0"
+ }
+ },
"node_modules/@sinonjs/commons": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz",
@@ -29244,6 +29256,18 @@
"integrity": "sha512-BUyKJGdDWqvWC5GEhyOiUrGNi9iJUr4CU0O2WxJL6QJhHeeA/NVBalH+FeK0r/x/W0rPymXt5s78TDS7d6lCwg==",
"dev": true
},
+ "@shlinkio/eslint-config-js-coding-standard": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@shlinkio/eslint-config-js-coding-standard/-/eslint-config-js-coding-standard-2.0.0.tgz",
+ "integrity": "sha512-yD/+NVu3vxcA23ptsFGxX827+tZgGfBoWMonRcliG56HOMYDrf7OET7f7Xvi1or2U0PLQDOPRShk4IlR3Km6kA==",
+ "dev": true,
+ "requires": {
+ "@typescript-eslint/eslint-plugin": "^5.16.0",
+ "@typescript-eslint/parser": "^5.16.0",
+ "eslint-config-airbnb": "^19.0.4",
+ "eslint-config-airbnb-typescript": "^16.1.4"
+ }
+ },
"@sinonjs/commons": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz",
diff --git a/package.json b/package.json
index f1f86301..9655a4a9 100644
--- a/package.json
+++ b/package.json
@@ -66,6 +66,7 @@
"workbox-strategies": "^6.5.1"
},
"devDependencies": {
+ "@shlinkio/eslint-config-js-coding-standard": "~2.0.0",
"@stryker-mutator/core": "^5.6.1",
"@stryker-mutator/jest-runner": "^5.6.1",
"@stryker-mutator/typescript-checker": "^5.6.1",
@@ -84,8 +85,6 @@
"@types/react-redux": "^7.1.23",
"@types/react-tag-autocomplete": "^6.1.1",
"@types/uuid": "^8.3.4",
- "@typescript-eslint/eslint-plugin": "^5.16.0",
- "@typescript-eslint/parser": "^5.16.0",
"@wojtekmaj/enzyme-adapter-react-17": "0.6.5",
"adm-zip": "^0.5.9",
"babel-jest": "^27.5.1",
@@ -93,8 +92,6 @@
"dart-sass": "^1.25.0",
"enzyme": "^3.11.0",
"eslint": "^8.12.0",
- "eslint-config-airbnb": "^19.0.4",
- "eslint-config-airbnb-typescript": "^16.1.4",
"identity-obj-proxy": "^3.0.0",
"jest": "^27.5.1",
"react-scripts": "^5.0.0",
diff --git a/src/visits/types/helpers.ts b/src/visits/types/helpers.ts
index be1417c6..0b449968 100644
--- a/src/visits/types/helpers.ts
+++ b/src/visits/types/helpers.ts
@@ -3,10 +3,10 @@ import { formatIsoDate } from '../../utils/helpers/date';
import { ShlinkVisitsParams } from '../../api/types';
import { CreateVisit, NormalizedOrphanVisit, NormalizedVisit, OrphanVisit, Stats, Visit, VisitsParams } from './index';
-export const isOrphanVisit = (visit: Visit): visit is OrphanVisit => !!(visit as OrphanVisit).visitedUrl;
+export const isOrphanVisit = (visit: Visit): visit is OrphanVisit => (visit as OrphanVisit).visitedUrl !== undefined;
export const isNormalizedOrphanVisit = (visit: NormalizedVisit): visit is NormalizedOrphanVisit =>
- !!(visit as NormalizedOrphanVisit).visitedUrl;
+ (visit as NormalizedOrphanVisit).visitedUrl !== undefined;
export interface GroupedNewVisits {
orphanVisits: CreateVisit[];
diff --git a/test/servers/DeleteServerModal.test.tsx b/test/servers/DeleteServerModal.test.tsx
index 83bb6d5b..83c917c7 100644
--- a/test/servers/DeleteServerModal.test.tsx
+++ b/test/servers/DeleteServerModal.test.tsx
@@ -1,5 +1,5 @@
import { shallow, ShallowWrapper } from 'enzyme';
-import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
+import { Button, Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
import { Mock } from 'ts-mockery';
import { useNavigate } from 'react-router-dom';
import DeleteServerModal from '../../src/servers/DeleteServerModal';
@@ -45,7 +45,7 @@ describe('', () => {
});
it('toggles when clicking cancel button', () => {
- const cancelBtn = wrapper.find('button').first();
+ const cancelBtn = wrapper.find(Button).first();
cancelBtn.simulate('click');
@@ -55,7 +55,7 @@ describe('', () => {
});
it('deletes server when clicking accept button', () => {
- const acceptBtn = wrapper.find('button').last();
+ const acceptBtn = wrapper.find(Button).last();
acceptBtn.simulate('click');
diff --git a/test/short-urls/helpers/QrCodeModal.test.tsx b/test/short-urls/helpers/QrCodeModal.test.tsx
index 16149cf4..44c7cd57 100644
--- a/test/short-urls/helpers/QrCodeModal.test.tsx
+++ b/test/short-urls/helpers/QrCodeModal.test.tsx
@@ -13,7 +13,7 @@ import { QrErrorCorrectionDropdown } from '../../../src/short-urls/helpers/qr-co
describe('', () => {
let wrapper: ShallowWrapper;
- const saveImage = jest.fn();
+ const saveImage = jest.fn().mockReturnValue(Promise.resolve());
const QrCodeModal = createQrCodeModal(Mock.of({ saveImage }), () => null);
const shortUrl = 'https://doma.in/abc123';
const createWrapper = (version: SemVer = '2.6.0') => {
diff --git a/test/tags/helpers/DeleteTagConfirmModal.test.tsx b/test/tags/helpers/DeleteTagConfirmModal.test.tsx
index 866dadce..0ba07ea1 100644
--- a/test/tags/helpers/DeleteTagConfirmModal.test.tsx
+++ b/test/tags/helpers/DeleteTagConfirmModal.test.tsx
@@ -1,5 +1,5 @@
import { shallow, ShallowWrapper } from 'enzyme';
-import { Modal, ModalBody, ModalFooter } from 'reactstrap';
+import { Button, Modal, ModalBody, ModalFooter } from 'reactstrap';
import DeleteTagConfirmModal from '../../../src/tags/helpers/DeleteTagConfirmModal';
import { TagDeletion } from '../../../src/tags/reducers/tagDelete';
@@ -30,11 +30,11 @@ describe('', () => {
wrapper = createWrapper({ error: false, deleting: false });
const body = wrapper.find(ModalBody);
const footer = wrapper.find(ModalFooter);
- const delBtn = footer.find('.btn-danger');
+ const delBtn = footer.find(Button).last();
expect(body.html()).toContain(`Are you sure you want to delete tag ${tag}?`);
expect(delBtn.prop('disabled')).toEqual(false);
- expect(delBtn.text()).toEqual('Delete tag');
+ expect(delBtn.html()).toContain('>Delete tag<');
});
it('shows error message when deletion failed', () => {
@@ -47,16 +47,16 @@ describe('', () => {
it('shows loading status while deleting', () => {
wrapper = createWrapper({ error: false, deleting: true });
const footer = wrapper.find(ModalFooter);
- const delBtn = footer.find('.btn-danger');
+ const delBtn = footer.find(Button).last();
expect(delBtn.prop('disabled')).toEqual(true);
- expect(delBtn.text()).toEqual('Deleting tag...');
+ expect(delBtn.html()).toContain('>Deleting tag...<');
});
it('deletes tag modal when btn is clicked', async () => {
wrapper = createWrapper({ error: false, deleting: true });
const footer = wrapper.find(ModalFooter);
- const delBtn = footer.find('.btn-danger');
+ const delBtn = footer.find(Button).last();
await delBtn.simulate('click'); // eslint-disable-line @typescript-eslint/await-thenable