Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement sample frontend for testing #1

Merged
merged 34 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
33fe4c9
[Feature] initial commit
fleitmann-senacor Oct 22, 2024
0801a80
Merge remote-tracking branch 'origin/main' into feature/implement_fro…
fleitmann-senacor Oct 22, 2024
efeb4c6
[Feature] extraction der Formularinhalte / Elemente in Kind-Komponenten
fleitmann-senacor Oct 22, 2024
091fc0e
[Feature] add github pipeline definition for ci
fleitmann-senacor Oct 23, 2024
ef8b2a6
[Bugfix] fix ci syntax error
fleitmann-senacor Oct 23, 2024
73dd201
[Bugfix] fix ci syntax error
fleitmann-senacor Oct 23, 2024
53004b8
[Bugfix] fix pipeline failing due to indentation error
fleitmann-senacor Oct 23, 2024
07afa00
[Change] fix build warnings
fleitmann-senacor Oct 23, 2024
053dcc3
[Change] implement cypress test for form fields
fleitmann-senacor Oct 23, 2024
e3f2467
[Feature] implement cypress tests, refactor components / pages
fleitmann-senacor Oct 23, 2024
e6ab81e
[Change] commit current working directory
fleitmann-senacor Oct 23, 2024
35feaa9
Some basic refactoring
gonzo12 Oct 24, 2024
7cee3e9
Refac wip
gonzo12 Oct 25, 2024
dc94c51
Refac wip
gonzo12 Oct 25, 2024
fde0e3e
Some formatting
gonzo12 Oct 25, 2024
7c458f1
Some formatting and linting configuration
gonzo12 Oct 29, 2024
09ded92
Push ci draft for pr build
gonzo12 Oct 29, 2024
c1551a3
Re-gen package-lock.json
gonzo12 Oct 29, 2024
6094fbe
Copy dist to bucket
gonzo12 Oct 29, 2024
82ceddf
Add missing coverage dep
gonzo12 Oct 29, 2024
652a60b
Fix build script
gonzo12 Oct 29, 2024
3ae560e
build
gonzo12 Oct 29, 2024
f6e0f4b
Install gcloud cli
gonzo12 Oct 30, 2024
f4e6991
Install gcloud cli
gonzo12 Oct 30, 2024
9e6555c
Install gcloud cli
gonzo12 Oct 30, 2024
a6f27f2
Fix gsutil command
gonzo12 Oct 30, 2024
980da50
use gloud instead gsutil
gonzo12 Oct 30, 2024
1ac0357
do not want the dist folder in bucket
gonzo12 Oct 30, 2024
9f10db1
peculiar syntax it is
gonzo12 Oct 30, 2024
e436786
define gcp deployment base path
gonzo12 Oct 30, 2024
868ff96
define gcp deployment base path
gonzo12 Oct 30, 2024
84e68d0
sometimes i just don't understand
gonzo12 Oct 30, 2024
ee5f462
mv config.json to public
gonzo12 Oct 30, 2024
da57dda
No Cache
gonzo12 Oct 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
**/node_modules
**/dist
6 changes: 6 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue}]
charset = utf-8
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VITE_BASE_PATH=/
1 change: 1 addition & 0 deletions .env.gcp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VITE_BASE_PATH=/lpt-ui/
63 changes: 63 additions & 0 deletions .github/workflows/pr-to-main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: build-verify-deploy

on: # yamllint disable-line rule:truthy
pull_request:
types:
- opened
- edited
- reopened
- ready_for_review
- synchronize
branches:
# Only run on pull requests targeting main
- main

jobs:
build-verify-deploy:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4
- name: Get npm cache directory
id: npm-cache-dir
shell: bash
run: echo "dir=$(npm config get cache)" >> ${GITHUB_OUTPUT}
- name: Cache dependencies
uses: actions/cache@v4.0.1
id: npm-cache
with:
path: |
${{ steps.npm-cache-dir.outputs.dir }}
/github/home/.cache/Cypress
key: npm-cypress-${{ hashFiles('package-lock.json') }}
restore-keys: |
npm-cypress-
npm-
- name: Install dependencies
run: npm ci --prefer-offline --no-audit --no-progress --no-fund
- name: Check linting across the board
shell: bash
run: npm run lint:ci
- name: Run unit tests
shell: bash
run: |
# no tests to run:
npm run test:cover || echo 0
- name: Build application
shell: bash
run: npm run build:gcp
- name: GCP Auth
uses: 'google-github-actions/auth@v2'
with:
project_id: ${{ vars.GOOGLE_PROJECT_ID }}
credentials_json: ${{ secrets.AUTOMATION_SA_KEY_JSON }}
- name: Install gcloud cli
uses: 'google-github-actions/setup-gcloud@v2'
- name: Copy dist to bucket
shell: bash
run: |
gcloud storage cp -r dist/* gs://lpt-ui/
# Cache simplification:
gcloud storage objects update gs://lpt-ui/* --cache-control="no-cache, no-store, must-revalidate"

30 changes: 30 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
.DS_Store
dist
dist-ssr
coverage
*.local

/cypress/videos/
/cypress/screenshots/

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

*.tsbuildinfo
10 changes: 10 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.DS_Store
node_modules
.env
.env.*
!.env.example

# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock
17 changes: 17 additions & 0 deletions .prettierrc.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const config = {
printWidth: 120,
semi: false,
singleQuote: true,
trailingComma: 'none',
overrides: [
{
files: '*.html',
options: {
printWidth: 80
}
}
],
plugins: ['prettier-plugin-organize-imports']
}

export default config
2 changes: 2 additions & 0 deletions .stylelintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/coverage/
/dist/
3 changes: 3 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"recommendations": ["Vue.volar", "vitest.explorer", "dbaeumer.vscode-eslint", "esbenp.prettier-vscode"]
}
15 changes: 15 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# build stage
FROM node:lts-alpine as build-stage
LABEL stage=builder
WORKDIR /app
COPY package*.json ./
# install all dependencies, including dev dependencies required for build
RUN npm install && npm cache clean --force
COPY ./ ./
RUN npm run build

# production stage
FROM nginx:stable-alpine as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
59 changes: 59 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,61 @@
# lpt-application-ui

UI used for the credit application application, fetching the credit data of a customer

## Recommended IDE Setup

[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur).

## Type Support for `.vue` Imports in TS

TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types.

## Customize configuration

See [Vite Configuration Reference](https://vite.dev/config/).

## Project Setup

```sh
bun install
```

### Compile and Hot-Reload for Development

```sh
bun dev
```

### Type-Check, Compile and Minify for Production

```sh
bun build
```

### Run Unit Tests with [Vitest](https://vitest.dev/)

```sh
bun test:unit
```

### Run End-to-End Tests with [Cypress](https://www.cypress.io/)

```sh
bun test:e2e:dev
```

This runs the end-to-end tests against the Vite development server.
It is much faster than the production build.

But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments):

```sh
bun build
bun test:e2e
```

### Lint with [ESLint](https://eslint.org/)

```sh
bun lint
```
Binary file added bun.lockb
Binary file not shown.
8 changes: 8 additions & 0 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { defineConfig } from 'cypress'

export default defineConfig({
e2e: {
specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}',
baseUrl: 'http://localhost:4173'
}
})
62 changes: 62 additions & 0 deletions cypress/e2e/credit-application/verify-form-fields.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
describe('Verify Form fields', () => {
beforeEach(() => {
cy.visit('/')
})

it('opens the application and displays the correct information', () => {
cy.title().should('equal', 'Der "ich möchte Dinge finanzieren" Kredit 💰')
})

it('contains the required input fields with default values', () => {
// credit amount
cy.get('[data-test-id="creditAmount"]').should('exist').invoke('val').should('equal', '10000')
cy.get('[data-test-id="creditAmountInput"]').should('exist').should('contain.value', '10000')

// firstName
cy.get('[data-test-id="firstName"]').should('exist').should('contain.value', '')

// lastName
cy.get('[data-test-id="lastName"]').should('exist').should('contain.value', '')

// zipCode
cy.get('[data-test-id="zipCode"]').should('exist').should('contain.value', '')

// occupation
cy.get('[data-test-id="occupation"]').should('exist').should('have.value', null)

// net-income
cy.get('[data-test-id="monthlyNetIncome"]').should('exist').invoke('val').should('equal', '2200')
cy.get('[data-test-id="monthlyNetIncome"]').should('exist').should('contain.value', '2200')

// expenses
cy.get('[data-test-id="monthlyExpenses"]').should('exist').invoke('val').should('equal', '1600')
cy.get('[data-test-id="monthlyExpenses"]').should('exist').should('contain.value', '1600')
})

describe('combined inputs behave correctly', () => {
// only tested on one field combination
it('updates the number input when the range slider gets updated', () => {
// credit amount
cy.get('[data-test-id="creditAmount"]').should('exist').invoke('val').should('equal', '10000')
cy.get('[data-test-id="creditAmountInput"]').should('exist').should('contain.value', '10000')

// update the range slider
cy.get('[data-test-id="creditAmount"]').invoke('val', '20000')
cy.get('[data-test-id="creditAmount"]').trigger('input')

cy.get('[data-test-id="creditAmountInput"]').should('exist').should('contain.value', '20000')
})
it('updates the range slider when the input gets updated', () => {
// credit amount
cy.get('[data-test-id="creditAmount"]').should('exist').invoke('val').should('equal', '10000')
cy.get('[data-test-id="creditAmountInput"]').should('exist').should('contain.value', '10000')

// update the range slider
cy.get('[data-test-id="creditAmountInput"]').clear()
cy.get('[data-test-id="creditAmountInput"]').type('20000')
cy.get('[data-test-id="creditAmountInput"]').trigger('input')

cy.get('[data-test-id="creditAmount"]').should('exist').invoke('val').should('equal', '20000')
})
})
})
34 changes: 34 additions & 0 deletions cypress/e2e/credit-application/verify-form-submission.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { CreditDecisionResult } from '../../../src/credit-application/models/credit-decision-result.enum'
import { Occupations } from '../../../src/credit-application/models/occupations.enum'
import { setFormValues, submitForm } from '../../support/commands'
import { creditApplicationRequestAlias, interceptCreditApplicationRequest } from '../../support/requests'

describe('Verify Form Submission', () => {
beforeEach(() => {
cy.visit('/')
})

it('valid and accepted form behaves as expected', () => {
setFormValues({
creditAmount: 36_000,
firstName: 'Rolf',
lastName: 'Zuckowski',
zipCode: '76131',
occupation: Occupations.FREELANCER,
monthlyNetIncome: '800',
monthlyExpenses: '500'
})

interceptCreditApplicationRequest(CreditDecisionResult.APPROVED)

submitForm()

cy.wait([`\@${creditApplicationRequestAlias}`])

// TODO - do whatever is supposed to happen
})

it('invalid form behaves as expected', () => {
// TODO - do whatever is supposed to happen
})
})
Loading