Skip to content

Commit

Permalink
Feature/1135 formatter naming conventions (#1250)
Browse files Browse the repository at this point in the history
* squash branch

* apply formatter rules

* fix after rebase and apply formatter

* rename files to kebab case (#1264)

* squash branch

* rename files to kebab case

* regen package-lock

* run prettier

---------

Co-authored-by: Yanick Minder <[email protected]>
Co-authored-by: Yanick Minder <[email protected]>
  • Loading branch information
3 people authored Dec 24, 2024
1 parent 9e4fc0f commit b70b28b
Show file tree
Hide file tree
Showing 173 changed files with 616 additions and 434 deletions.
7 changes: 7 additions & 0 deletions frontend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ https://eslint.org/
We use **prettier** to format scss json and yaml files:
https://prettier.io/

We use **prettier** to format scss json and yaml files:
https://prettier.io/

If you get a does not match pattern error, it is likely because of the custom words for the OKR tool
here is a regex101 project that showcases how the regex works:
https://regex101.com/r/VUyAt6/1

## Test Coverage

For generating the coverage of our frontend specs (jest), you can use following command:
Expand Down
22 changes: 11 additions & 11 deletions frontend/cypress/e2e/check-in.cy.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as users from '../fixtures/users.json';
import { uniqueSuffix } from '../support/helper/utils';
import CyOverviewPage from '../support/helper/dom-helper/pages/overviewPage';
import { Unit } from '../../src/app/shared/types/enums/Unit';
import { Unit } from '../../src/app/shared/types/enums/unit';
import KeyResultDetailPage from '../support/helper/dom-helper/pages/keyResultDetailPage';
import CheckInDialog from '../support/helper/dom-helper/dialogs/checkInDialog';
import CheckInHistoryDialog from '../support/helper/dom-helper/dialogs/checkInHistoryDialog';
Expand Down Expand Up @@ -126,7 +126,7 @@ describe('okr check-in', () => {
.fillCheckInInitiatives('Will be difficult')
.submit();
keyResultDetailPage
.showAllCheckins()
.showAllCheckIns()
.checkForAttribute('Confidence:', '5 / 10')
.checkForAttribute('Confidence:', '6 / 10')
.checkForAttribute('Veränderungen:', 'We bought a new house')
Expand Down Expand Up @@ -156,7 +156,7 @@ describe('okr check-in', () => {
.fillCheckInInitiatives('A cat would be great')
.submit();
cy.contains('Aktuell: 30 CHF');
keyResultDetailPage.showAllCheckins();
keyResultDetailPage.showAllCheckIns();
cy.contains('Check-in History');
cy.contains('Wert: 30 CHF');
CheckInHistoryDialog.do()
Expand Down Expand Up @@ -191,7 +191,7 @@ describe('okr check-in', () => {
.fillCheckInInitiatives('A cat would be great')
.submit();
cy.contains('Aktuell: 30 EUR');
keyResultDetailPage.showAllCheckins();
keyResultDetailPage.showAllCheckIns();
cy.contains('Check-in History');
cy.contains('Wert: 30 EUR');
CheckInHistoryDialog.do()
Expand All @@ -213,7 +213,7 @@ describe('okr check-in', () => {
.fillCheckInInitiatives('A cat would be great')
.submit();
cy.contains('Aktuell: 30 FTE');
keyResultDetailPage.showAllCheckins();
keyResultDetailPage.showAllCheckIns();
cy.contains('Check-in History');
cy.contains('Wert: 30 FTE');
});
Expand All @@ -233,7 +233,7 @@ describe('okr check-in', () => {
.fillCheckInCommentary('There is a new car')
.fillCheckInInitiatives('Buy now a new pool')
.submit();
keyResultDetailPage.showAllCheckins()
keyResultDetailPage.showAllCheckIns()
.editLatestCheckIn();
cy.contains('For editing ordinal checkin');
cy.contains('Confidence um Target Zone zu erreichen');
Expand Down Expand Up @@ -308,14 +308,14 @@ function getCurrentDate() {
const mm = today.getMonth() + 1; // Months start at 0!
const dd = today.getDate();

let dd_str = '' + dd;
let mm_str = '' + mm;
let ddStr = '' + dd;
let mmStr = '' + mm;
if (dd < 10) {
dd_str = '0' + dd_str;
ddStr = '0' + ddStr;
}
if (mm < 10) {
mm_str = '0' + mm_str;
mmStr = '0' + mmStr;
}

return dd_str + '.' + mm_str + '.' + yyyy;
return ddStr + '.' + mmStr + '.' + yyyy;
}
2 changes: 1 addition & 1 deletion frontend/cypress/e2e/key-result.cy.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as users from '../fixtures/users.json';
import CyOverviewPage from '../support/helper/dom-helper/pages/overviewPage';
import KeyResultDetailPage from '../support/helper/dom-helper/pages/keyResultDetailPage';
import { Unit } from '../../src/app/shared/types/enums/Unit';
import { Unit } from '../../src/app/shared/types/enums/unit';
import KeyResultDialog from '../support/helper/dom-helper/dialogs/keyResultDialog';

describe('okr key-result', () => {
Expand Down
2 changes: 1 addition & 1 deletion frontend/cypress/e2e/scoring.cy.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as users from '../fixtures/users.json';
import { getPercentageMetric, getPercentageOrdinal } from 'cypress/support/helper/scoringSupport';
import CyOverviewPage from '../support/helper/dom-helper/pages/overviewPage';
import { Unit } from '../../src/app/shared/types/enums/Unit';
import { Unit } from '../../src/app/shared/types/enums/unit';
import KeyResultDetailPage from '../support/helper/dom-helper/pages/keyResultDetailPage';

describe('okr scoring', () => {
Expand Down
2 changes: 1 addition & 1 deletion frontend/cypress/e2e/tab.cy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as users from '../fixtures/users.json';
import CyOverviewPage from '../support/helper/dom-helper/pages/overviewPage';
import { Unit } from '../../src/app/shared/types/enums/Unit';
import { Unit } from '../../src/app/shared/types/enums/unit';
import KeyResultDetailPage from '../support/helper/dom-helper/pages/keyResultDetailPage';

describe('tabbing workflows', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Dialog from './dialog';
import { Unit } from '../../../../../src/app/shared/types/enums/Unit';
import { Unit } from '../../../../../src/app/shared/types/enums/unit';
import ConfirmDialog from './confirmDialog';
import Chainable = Cypress.Chainable;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default class KeyResultDetailPage extends Page {
return new KeyResultDialog();
}

showAllCheckins() {
showAllCheckIns() {
this.elements.showAllCheckins()
.click();
return new CheckInHistoryDialog();
Expand Down
63 changes: 61 additions & 2 deletions frontend/eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,42 @@ import stylistic from '@stylistic/eslint-plugin'
import html from '@html-eslint/eslint-plugin'
import angular from 'angular-eslint'
import htmlParser from '@html-eslint/parser'
import { createRegexForWords } from './eslintHelper.mjs'
import checkFile from 'eslint-plugin-check-file'

export default tsEslint.config(
{
files: ['src/app/shared/types/**/*'],
rules: {
'check-file/filename-naming-convention': [
'error',
{
'**/*.{js,ts}': 'KEBAB_CASE',
},
],
},
},
{
ignores: ['cypress/downloads/**/*'],
},
{
files: ['**/*.ts'],
files: ['src/**/*.ts', 'cypress/**/*.ts'],
extends: [
eslint.configs.recommended,
...tsEslint.configs.recommended,
...tsEslint.configs.stylistic,
...angular.configs.tsRecommended,
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.json', './tsconfig.spec.json'],
},
},
processor: angular.processInlineTemplates,
languageOptions: {
parserOptions: {
project: ['./tsconfig.json', './tsconfig.spec.json'],
},
globals: {
//Cypress things not recognized by eslint
cy: 'readonly',
Expand Down Expand Up @@ -130,10 +151,40 @@ export default tsEslint.config(
style: 'kebab-case',
},
],
'@typescript-eslint/naming-convention': [
'error',
{
selector: ['class', 'interface'],
format: ['PascalCase'],
},
{
selector: 'variable',
modifiers: [],
format: ['camelCase', 'UPPER_CASE'],
},
{
selector: 'enum',
format: ['PascalCase'],
},
{
selector: 'enumMember',
format: ['UPPER_CASE'],
},
{
selector: ['method', 'function'],
format: ['camelCase'],
},
{
selector: 'typeParameter',
format: ['PascalCase'],
},
],
'id-match': ['error', createRegexForWords(['KeyResult', 'CheckIn', 'TeamManagement', 'StretchGoal'])],
},
},

{
files: ['**/*.spec.ts'],
files: ['src/**/*.spec.ts', 'cypress/**/*.spec.ts'],
extends: [...tsEslint.configs.recommended],
rules: {
//Rules removed for Test files because they are unnecessary for tests
Expand All @@ -159,6 +210,13 @@ export default tsEslint.config(
'@html-eslint/require-img-alt': 'off',
'@html-eslint/indent': ['error', 2],
'@html-eslint/require-closing-tags': ['error', { selfClosing: 'always' }],
'@html-eslint/id-naming-convention': [
'error',
'regex',
{
pattern: `(?=(^[a-z]+(-[a-z]+)*$))(?=(${createRegexForWords(['KeyResult', 'CheckIn', 'TeamManagement', 'StretchGoal'])}))`,
},
],
//Doesn't work with Angular 17+
'@html-eslint/element-newline': 'off',
},
Expand All @@ -168,6 +226,7 @@ export default tsEslint.config(
'unused-imports': unusedImports,
'@stylistic': stylistic,
'@html-eslint': html,
'check-file': checkFile,
},
}
)
59 changes: 59 additions & 0 deletions frontend/eslintHelper.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
export function createRegexForWords(wordList) {
// This function builds a case-insensitive regex pattern for a given word.

const part1List = []
const part2List = []

wordList.forEach((word) => {
const part1 = createRegexToCheckIfWordLookAlike(word)
const part2 = createFallbackRegex(word)
part1List.push(part1)
part2List.push(part2)
})
return `(${part1List.join('|')})|(${part2List.join('')})`
}

function getCaseInsensitiveRegexForChar(c) {
return `[${c.toUpperCase()}${c.toLowerCase()}]`
}

function createCaseInsensitiveRegexForWord(word) {
return word
.match(/[A-Z][a-z]+/g)
.join('.?')
.split('')
.map((c) => (/[a-zA-Z]/g.test(c) ? getCaseInsensitiveRegexForChar(c) : c))
.join('')
}

function transformToUnderscoreUppercase(word) {
return word
.split(/(?=[A-Z])/) // Split at uppercase letters without removing them
.join('_')
.toUpperCase()
}

function transformToHyphenLowercase(word) {
return word
.split(/(?=[A-Z])/) // Split at uppercase letters without removing them
.join('-')
.toLowerCase()
}

function getWordRegexWithOptionalLetters(word) {
return word.replace(/(\[[^\[\]]+\])(?![.?])/g, '$1?') // Puts a "?" between the case-insensitive braces if there is no "?" or "." already
}

function createRegexToCheckIfWordLookAlike(word) {
let wordLooksLikeRegex = createCaseInsensitiveRegexForWord(word)
wordLooksLikeRegex = getWordRegexWithOptionalLetters(wordLooksLikeRegex)
const wordCorrectRegex = getCaseInsensitiveRegexForChar(word[0]) + word.slice(1)
const wordInUpperCase = transformToUnderscoreUppercase(word)
const wordInLowerCase = transformToHyphenLowercase(word)
return `(?=.*${wordLooksLikeRegex}.*)(.*${wordCorrectRegex}.*|[A-Z_]*${wordInUpperCase}[A-Z_]*|[a-z-]*${wordInLowerCase}[a-z-]*)`
}

function createFallbackRegex(word) {
const caseInsensitiveWordRegex = createCaseInsensitiveRegexForWord(word)
return `(?=^(?!.*${caseInsensitiveWordRegex}).*)`
}
31 changes: 31 additions & 0 deletions frontend/eslintHelper.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as eslintHelper from "./eslintHelper.mjs"
import { $locationShim } from "@angular/common/upgrade";

describe("eslintHelper", () => {
const combinedRegex:string = "((?=.*[Kk]?[Ee]?[Yy].?[Rr]?[Ee]?[Ss]?[Uu]?[Ll]?[Tt]?.*)(.*[Kk]eyResult.*|[A-Z_]*KEY_RESULT[A-Z_]*|[a-z-]*key-result[a-z-]*)|(?=.*[Cc]?[Hh]?[Ee]?[Cc]?[Kk].?[Ii]?[Nn]?.*)(.*[Cc]heckIn.*|[A-Z_]*CHECK_IN[A-Z_]*|[a-z-]*check-in[a-z-]*))|((?=^(?!.*[Kk][Ee][Yy].?[Rr][Ee][Ss][Uu][Ll][Tt]).*)(?=^(?!.*[Cc][Hh][Ee][Cc][Kk].?[Ii][Nn]).*))"
const keyResultRegex:string = "((?=.*[Kk]?[Ee]?[Yy].?[Rr]?[Ee]?[Ss]?[Uu]?[Ll]?[Tt]?.*)(.*[Kk]eyResult.*|[A-Z_]*KEY_RESULT[A-Z_]*|[a-z-]*key-result[a-z-]*))|((?=^(?!.*[Kk][Ee][Yy].?[Rr][Ee][Ss][Uu][Ll][Tt]).*))"
const checkInRegex:string = "((?=.*[Cc]?[Hh]?[Ee]?[Cc]?[Kk].?[Ii]?[Nn]?.*)(.*[Cc]heckIn.*|[A-Z_]*CHECK_IN[A-Z_]*|[a-z-]*check-in[a-z-]*))|((?=^(?!.*[Cc][Hh][Ee][Cc][Kk].?[Ii][Nn]).*))"

it.each([
[["KeyResult"], keyResultRegex],
[["CheckIn"], checkInRegex],
[["KeyResult", "CheckIn"], combinedRegex],
])("should return regex %p", (wordToRegex, expectedRegex) => {
expect(eslintHelper.createRegexForWords(wordToRegex)).toEqual(expectedRegex);
});

it.each([
[["KeyResult"], ["KeyResult", "CurrentKeyResult", "keyResult", "keyResultId", "key-result", "test-key-result-test"],["Keyresult", "CurrentKeyresult", "keyresult", "keyresultId", "KEyResult", "KeyResUlt", "test-keyresult-test"]],
[["CheckIn"], ["CheckIn", "CurrentCheckIn", "checkIn", "checkInId", "check-in", "test-check-in-test"],["Checkin", "CurrentCheckin", "checkin", "checkinId", "cHeckIn", "checkIN", "test-checkin-test"]],
[["KeyResult", "CheckIn"], ["KeyResult", "CurrentKeyResult", "keyResult", "keyResultId", "key-result", "test-key-result-test", "CheckIn", "CurrentCheckIn", "checkIn", "checkInId", "check-in", "test-check-in-test"],["Keyresult", "CurrentKeyresult", "keyresult", "keyresultId", "KEyResult", "KeyResUlt", "test-keyresult-test", "Checkin", "CurrentCheckin", "checkin", "checkinId", "cHeckIn", "checkIN", "test-checkin-test"]],
])("should run regex %p threw the matching and not matching list", (wordToRegex:string[], matchingListToRegex:string[], notMatchingListToRegex:string[]) => {
const regexOfCustomWord = new RegExp(eslintHelper.createRegexForWords(wordToRegex));
matchingListToRegex = matchingListToRegex.filter(word => regexOfCustomWord.test(word));
notMatchingListToRegex = notMatchingListToRegex.filter(word => regexOfCustomWord.test(word));

expect(matchingListToRegex.length).toBe(matchingListToRegex.length);
expect(notMatchingListToRegex.length).toBe(0)
});

})

28 changes: 25 additions & 3 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,17 @@
"@eslint/js": "^9.15.0",
"@html-eslint/eslint-plugin": "^0.27.0",
"@html-eslint/parser": "^0.27.0",
"@stylistic/eslint-plugin": "^2.11.0",
"@types/eslint__js": "^8.42.3",
"@types/jest": "^29.5.13",
"@types/uuid": "^10.0.0",
"@typescript-eslint/eslint-plugin": "^8.15.0",
"angular-eslint": "19.0.2",
"browserslist": "^4.24.2",
"cypress": "^13.15.0",
"cypress-real-events": "^1.13.0",
"eslint": "^9.16.0",
"eslint-plugin-check-file": "^2.8.0",
"eslint-plugin-unused-imports": "^4.1.4",
"jest": "^29.7.0",
"jest-preset-angular": "^14.2.4",
Expand Down
Loading

0 comments on commit b70b28b

Please sign in to comment.