Skip to content
Snippets Groups Projects
Commit a429bd20 authored by Anders Lindh Olsson's avatar Anders Lindh Olsson :8ball:
Browse files

Merge branch 'main' into from_main

parents 72c28620 5a979e4d
No related branches found
No related tags found
2 merge requests!497CE-2790: Prepare for 4.0.0,!446Merge main into develop
Pipeline #174372 waiting for manual action
**/node_modules
**/dist
*.log
.coverage
.coverage.*
SKIP_PREFLIGHT_CHECK=true
ESLINT_NO_DEV_ERRORS=true
\ No newline at end of file
ESLINT_NO_DEV_ERRORS=true
NODE_OPTIONS=
REACT_APP_SERVER_ADDRESS=https://localhost/api
REACT_APP_API_BASE_ENDPOINT=/api/spec
REACT_APP_TOKEN_RENEW_INTERVAL=180000
\ No newline at end of file
REACT_APP_TOKEN_RENEW_INTERVAL=180000
{
"plugins": [
"react",
"import",
"cypress"
],
"plugins": ["react", "import", "cypress"],
"extends": [
"react-app",
"eslint:recommended",
......@@ -17,20 +13,16 @@
"constructor-super": "off",
"default-case": "error",
"dot-notation": "error",
"eqeqeq": ["error", "always", {"null": "ignore"}],
"eqeqeq": ["error", "always", { "null": "ignore" }],
"guard-for-in": "error",
"import/no-unresolved": "error",
"no-array-constructor": "error",
"no-caller": "error",
"no-catch-shadow": "error",
"no-console": [
"warn", {
"allow": [
"warn",
"error",
"info",
"debug"
]
"warn",
{
"allow": ["warn", "error", "info", "debug"]
}
],
"no-constant-condition": "warn",
......@@ -55,9 +47,12 @@
"no-sequences": "error",
"no-undef-init": "error",
"no-unused-expressions": "error",
"no-unused-vars": ["error", { "vars": "all", "args": "none", "ignoreRestSiblings": true }],
"no-unused-vars": [
"error",
{ "vars": "all", "args": "none", "ignoreRestSiblings": true }
],
"operator-assignment": ["error", "always"],
"quotes": ["error", "double", {"avoidEscape": true}],
"quotes": ["error", "double", { "avoidEscape": true }],
"radix": "error",
"spaced-comment": "error",
"yoda": "error",
......@@ -81,12 +76,10 @@
},
"overrides": [
{
"files": [
"**/*.stories.*"
],
"files": ["**/*.stories.*"],
"rules": {
"import/no-anonymous-default-export": "off"
}
}
]
}
\ No newline at end of file
}
......@@ -37,4 +37,4 @@ yarn-error.log*
/eslint
/cypress/screenshots
/cypress/videos
.idea
\ No newline at end of file
.idea
......@@ -5,6 +5,7 @@ default:
- docker
stages:
- setup
- check
- build
- test
......@@ -13,19 +14,24 @@ stages:
include:
- project: "ics-infrastructure/gitlab-ci-yml"
file: "PreCommit.gitlab-ci.yml"
- project: "ics-infrastructure/gitlab-ci-yml"
file: "SonarScanner.gitlab-ci.yml"
variables:
CONTAINER_IMAGE: "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME"
CYPRESS_CACHE_FOLDER: "cache/Cypress"
CYPRESS_CACHE_FOLDER: "$CI_PROJECT_DIR/cache/Cypress"
npm_config_cache: "$CI_PROJECT_DIR/.npm"
install-dependencies:
stage: check
stage: setup
script:
- npm ci
artifacts:
paths:
- .cache/*
- cache/Cypress
- node_modules
- ${CYPRESS_CACHE_FOLDER} # for some inexplicable reason this path MUST be in a variable
- .npm
run-pre-commit:
needs:
......@@ -36,9 +42,6 @@ lint:
stage: check
script:
- npm run code-quality
needs:
- job: install-dependencies
artifacts: true
artifacts:
reports:
codequality: gl-codequality.json
......@@ -46,14 +49,14 @@ lint:
build-container:
stage: build
image: docker:latest
needs:
- job: install-dependencies
artifacts: true
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
- docker build -t $CONTAINER_IMAGE --build-arg REACT_APP_MUI_PRO_LICENSE_KEY=${REACT_APP_MUI_PRO_LICENSE_KEY} .
- docker push $CONTAINER_IMAGE
needs:
- job: install-dependencies
artifacts: true
build-storybook:
stage: build
......@@ -66,20 +69,35 @@ build-storybook:
paths:
- storybook-static
test-components-chrome:
run-sonar-scanner:
stage: test
needs:
- job: build-container
.test-components:
stage: test
image: cypress/browsers:node-20.10.0-chrome-118.0.5993.88-1-ff-118.0.2-edge-118.0.2088.46-1
script:
- CHOKIDAR_USEPOLLING=true WATCHPACK_POLLING=true npx cypress run --component --browser chrome
needs:
- job: install-dependencies
artifacts: true
- npm ci
- npm start &
- CHOKIDAR_USEPOLLING=true WATCHPACK_POLLING=true npx cypress run --component --browser ${BROWSER}
needs: [] # no requirements since it does an install
artifacts:
when: on_failure
paths:
- cypress/videos
- cypress/screenshots
test-components-chrome:
extends: .test-components
variables:
BROWSER: chrome
test-components-firefox:
extends: .test-components
variables:
BROWSER: firefox
.deploy:
stage: deploy
image: registry.esss.lu.se/ics-docker/awxkit
......@@ -94,7 +112,11 @@ test-components-chrome:
environment:
name: ${INSTANCE}
url: https://ce-deploy-${INSTANCE}.cslab.esss.lu.se/
when: manual
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
when: never
- if: $CI_COMMIT_BRANCH || $CI_COMMIT_TAG
when: manual
deploy-to-test:
extends: .deploy
......
default_language_version:
node: 20.10.0
files: "^src/"
exclude: '(?i)\.svg'
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
......
{
"trailingComma": "none",
"singleAttributePerLine": true
}
\ No newline at end of file
}
const config = {
stories: [
"../src/**/*.stories.mdx",
"../src/**/*.stories.@(js|jsx|ts|tsx)"
],
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions",
"@storybook/preset-create-react-app"
],
webpackFinal: async (config) => {
config.resolve.fallback = {
"http": require.resolve("stream-http"),
"https": require.resolve("https-browserify")
};
return config;
},
framework: {
name: "@storybook/react-webpack5",
options: {}
},
staticDirs: ['../public'],
};
export default config;
\ No newline at end of file
const config = {
stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions",
"@storybook/preset-create-react-app"
],
webpackFinal: async (config) => {
config.resolve.fallback = {
http: require.resolve("stream-http"),
https: require.resolve("https-browserify")
};
return config;
},
framework: {
name: "@storybook/react-webpack5",
options: {}
},
staticDirs: ["../public"]
};
export default config;
<script>
window.SERVER_ADDRESS=''
window.API_BASE_ENDPOINT='/api/spec'
window.TOKEN_RENEW_INTERVAL=180000
window.NAMING_ADDRESS='https://naming.esss.lu.se'
window.ENVIRONMENT_TITLE = ''
window.SERVER_ADDRESS = "";
window.API_BASE_ENDPOINT = "/api/spec";
window.TOKEN_RENEW_INTERVAL = 180000;
window.NAMING_ADDRESS = "https://naming.esss.lu.se";
window.ENVIRONMENT_TITLE = "";
</script>
import { initialize, mswLoader } from 'msw-storybook-addon';
import { handlers } from "../src/mocks/handlers"
import { initialize, mswLoader } from "msw-storybook-addon";
import { handlers } from "../src/mocks/handlers";
// Initialize MSW
initialize({}, handlers);
const preview = {
parameters: {
actions: { argTypesRegex: '^on[A-Z].*' },
actions: { argTypesRegex: "^on[A-Z].*" }
},
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
date: /Date$/
}
},
loaders: [mswLoader],
loaders: [mswLoader]
};
export default preview;
# build CE deploy & monitor Frontend
# build deploy & monitor frontend
FROM node:20.10.0 as builder
ARG REACT_APP_MUI_PRO_LICENSE_KEY
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
ENV PATH /usr/src/app/node_modules/.bin:$PATH
COPY . /usr/src/app
#Remove node-cache if building from local env that compiled project previously natively
RUN rm -rf /usr/src/app/node_modules
RUN npm ci
ENV PUBLIC_URL "/"
......@@ -15,7 +13,7 @@ RUN REACT_APP_MUI_PRO_LICENSE_KEY=${REACT_APP_MUI_PRO_LICENSE_KEY} npm run build
# production environment
FROM nginx:1.19.6-alpine
RUN rm -rf /etc/nginx/conf.d
RUN rm -rf /etc/nginx/conf.d
RUN mkdir /etc/nginx/conf.d
COPY docker/default.conf /etc/nginx/conf.d
COPY --from=builder /usr/src/app/build /usr/share/nginx/html/
......
......@@ -3,18 +3,21 @@
This project is meant to be the web User Interface for the CE deploy & monitor tool. The project is written in ReactJS.
## Developing environment
* NodeJS and npm
* Docker (if want to run backend locally for test purposes)
* IDE for JavaScript developement (e.g. Visual Studio Code)
* Credentials from ESS Artifactory, with permission to the ics-npm registry
- NodeJS and npm
- Docker (if want to run backend locally for test purposes)
- IDE for JavaScript developement (e.g. Visual Studio Code)
- Credentials from ESS Artifactory, with permission to the ics-npm registry
(For developing purposes it is suggested to use _Node Version Manager_ [NVM] which makes easy to change between different Node versions).
* Windows: https://github.com/coreybutler/nvm-windows
* Mac/Linux: https://github.com/nvm-sh/nvm
- Windows: https://github.com/coreybutler/nvm-windows
- Mac/Linux: https://github.com/nvm-sh/nvm
### Required versions
* Node: v14.10+
* npm: v6.10+
- Node: v14.10+
- npm: v6.10+
## Local development setup
......@@ -22,37 +25,41 @@ This project is meant to be the web User Interface for the CE deploy & monitor t
This project includes private dependencies from Artifactory, so additional configuration is required.
1. Create an `.npmrc` file based on the example provided in this registry, substituting your email and base64 credentials.
1. Install dependencies with `npm ci`.
1. Create an `.npmrc` file based on the example provided in this registry, substituting your email and base64 credentials.
1. Install dependencies with `npm ci`.
Note, we lock dependency versions with _package-lock.json_; please install dependencies with `npm ci` (not npm install) to avoid overwriting the package-lock.
### Proxying to Existing Backends
For being able to run the backend, and frontend application on the same machine (locally) a proxy has been set in the project!
If you <ins>don't want to run</ins> the backend server, and frontend on the same machine, or have different settings, please adjust the `package.json` at the following line:
`"proxy": "http://localhost:8080"`
## External configuration
All necessary configuration is stored in a config file in the `public` folder, called `config.js`. The config file has to be included in the _index.html_ file!
The following values can be set in the file:
| Environment variable | Description |
| -------------------------|-------------|
| SERVER_ADDRESS | The backend server base URL _(host:port)_ (if backend server is running natively on the same host as the UI then the value has to be empty, and proxy has to be set!)|
| API_BASE_ENDPOINT | The context path of the application's REST API _(e.g. /api/spec)_ |
| SWAGGER_UI_URL | The URL for the backend Swagger-ui interface _(e.g./api/docs)_ |
| TOKEN_RENEW_INTERVAL | Time interval to renew JWT auth token _(in milliseconds)_ |
| NAMING_ADDRESS | Naming service base URL (used for IOC name Naming reference feature) |
| ENVIRONMENT_TITLE | Adds a (sub)text to the HTLM title, and also for the appBar header. Supposed to show information to the user which environment they are using. The default value is empty. _Optional field!_ |
| Environment variable | Description |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| SERVER_ADDRESS | The backend server base URL _(host:port)_ (if backend server is running natively on the same host as the UI then the value has to be empty, and proxy has to be set!) |
| API_BASE_ENDPOINT | The context path of the application's REST API _(e.g. /api/spec)_ |
| SWAGGER_UI_URL | The URL for the backend Swagger-ui interface _(e.g./api/docs)_ |
| TOKEN_RENEW_INTERVAL | Time interval to renew JWT auth token _(in milliseconds)_ |
| NAMING_ADDRESS | Naming service base URL (used for IOC name Naming reference feature) |
| ENVIRONMENT_TITLE | Adds a (sub)text to the HTLM title, and also for the appBar header. Supposed to show information to the user which environment they are using. The default value is empty. _Optional field!_ |
Refering to a value in the JS source code is: _window.field-name_ (e.g. window.SERVER_ADDRESS).
### Setting Environment Variables
Environment variables are stored in `.env` files.
Precedency of environment variable files are (files on the left have more priority than files on the right):
* npm start: `.env.development.local`, `.env.local`, `.env.development`, `.env`
* npm run build: `.env.production.local`, `.env.local`, `.env.production`, `.env`
* npm test: `.env.test.local`, `.env.test`, `.env` (note .env.local is missing)
- npm start: `.env.development.local`, `.env.local`, `.env.development`, `.env`
- npm run build: `.env.production.local`, `.env.local`, `.env.production`, `.env`
- npm test: `.env.test.local`, `.env.test`, `.env` (note .env.local is missing)
All environment variables start with `REACT_APP_` prefix.
......@@ -73,27 +80,34 @@ The page will reload if you make edits.\
You will also see any lint errors in the console.
## [ESLint](https://eslint.org) & [Prettier](https://prettier.io)
Linting can be checked, and to some extent auto fixed by running following scripts:
Linting can be checked, and to some extent auto fixed by running following scripts:
### `npm run lint`
will run `npx eslint src` which will run eslint on all files in the src directory and write out the results of the check in your console.
will run `npx eslint src` which will run eslint on all files in the src directory and write out the results of the check in your console.
### `npm run lint:fix`
will run `npm run lint -- --fix` which will run eslint on all files in the src directory and fix what can be auto fixed and write out the rest of the results of the check, of what could not be auto fixed, in your console.
will run `npm run lint -- --fix` which will run eslint on all files in the src directory and fix what can be auto fixed and write out the rest of the results of the check, of what could not be auto fixed, in your console.
### `npm run prettier`
will run `npx prettier src --check` which will run prettier on all files in the src directory and write out which files would be changed in your console.
will run `npx prettier src --check` which will run prettier on all files in the src directory and write out which files would be changed in your console.
### `npm run prettier:fix`
will run `npm run prettier -- --write` which will run prettier on all files in the src directory and write out which files have be changed in your console.
will run `npm run prettier -- --write` which will run prettier on all files in the src directory and write out which files have be changed in your console.
### `npm run format`
will run `npm run prettier:fix && npm run lint:fix` which will run lint:fix and the prettier:fix scripts mentioned above.
will run `npm run prettier:fix && npm run lint:fix` which will run lint:fix and the prettier:fix scripts mentioned above.
## [Pre-Commit](https://pre-commit.com/)
### Installation
You will need to install pre-commit first locally on you machine, the install it in you project, instructions on how to do this you can find here: https://pre-commit.com/#install
You will need to install pre-commit first locally on you machine, the install it in you project, instructions on how to do this you can find here: https://pre-commit.com/#install
By running `pre-commit run --all-files` pre-commit will run both eslint and prettier on all files in src, much like the scripts from the package.json
......@@ -101,6 +115,7 @@ By running `pre-commit run --all-files` pre-commit will run both eslint and pret
For end-to-end testing we user Cypress, tests are written in gherkin syntax.
To run Cypress tests, <ins>you have to</ins>
- run the backend server
- run the frontend code
......@@ -108,9 +123,11 @@ Details:
https://github.com/TheBrainFamily/cypress-cucumber-preprocessor
Then to open Cypress dialog window enter:
### `npx cypress open`
To run Cypress tests from command line (without the test-dialog), enter
### `npx cypress run`
## Jest-tests
......
module.exports = {
webpack: {
configure: webpackConfig => {
configure: (webpackConfig) => {
const scopePluginIndex = webpackConfig.resolve.plugins.findIndex(
({ constructor }) => constructor && constructor.name === "ModuleScopePlugin"
({ constructor }) =>
constructor && constructor.name === "ModuleScopePlugin"
);
webpackConfig.resolve.plugins.splice(scopePluginIndex, 1);
webpackConfig.resolve = {
fallback: {
"http": require.resolve("stream-http"),
"https": require.resolve("https-browserify")
},
http: require.resolve("stream-http"),
https: require.resolve("https-browserify")
}
};
webpackConfig.ignoreWarnings = [
function ignoreSourcemapsloaderWarnings(warning) {
return (
......@@ -21,10 +22,10 @@ module.exports = {
warning.details &&
warning.details.includes("source-map-loader")
);
},
}
];
return webpackConfig;
},
},
};
\ No newline at end of file
}
}
};
const { defineConfig } = require("cypress");
const cucumber = require('cypress-cucumber-preprocessor').default
const cucumber = require("cypress-cucumber-preprocessor").default;
module.exports = defineConfig({
fixturesFolder: "src/mocks/fixtures",
......@@ -10,9 +10,9 @@ module.exports = defineConfig({
// We've imported your old cypress plugins here.
// You may want to clean this up later by importing these.
setupNodeEvents(on, config) {
on('file:preprocessor', cucumber());
on("file:preprocessor", cucumber());
},
specPattern: "cypress/e2e/**/*.{feature,features}",
specPattern: "cypress/e2e/**/*.{feature,features}"
},
component: {
......@@ -20,8 +20,7 @@ module.exports = defineConfig({
specPattern: "src/**/*.spec.{js,jsx,ts,tsx}",
devServer: {
framework: "create-react-app",
bundler: "webpack",
},
bundler: "webpack"
}
}
});
Feature: Deployment Tool Main Page
I want to see login screen when opening application
@focus
Scenario: Opening application when not authenticated
Given the user is not authenticated
When the user opens the application
Then the login button should be visible
\ No newline at end of file
Then the login button should be visible
import { Given, When, Then } from "cypress-cucumber-preprocessor/steps";
const baseUrl = 'http://localhost:3000'
const baseUrl = "http://localhost:3000";
Given('the user is not authenticated', () => {
cy.clearCookies();
Given("the user is not authenticated", () => {
cy.clearCookies();
cy.request({
url: baseUrl+'/api/v1/get_helper/user_info',
failOnStatusCode: false
})
.should((response) => {
expect(response.status).to.eq(401)
})
})
cy.request({
url: baseUrl + "/api/v1/get_helper/user_info",
failOnStatusCode: false
}).should((response) => {
expect(response.status).to.eq(401);
});
});
When('the user opens the application', () => {
When("the user opens the application", () => {
cy.visit(baseUrl);
})
Then('the login button should be visible', () => {
cy.get("button").contains("Login")
})
});
Then("the login button should be visible", () => {
cy.get("button").contains("Login");
});
......@@ -28,4 +28,6 @@
import "@testing-library/cypress/add-commands";
// import custom auth commands
Cypress.Commands.add("login", () => {cy.setCookie("ce-deploy-auth", "DEADBEEF")});
Cypress.Commands.add("login", () => {
cy.setCookie("ce-deploy-auth", "DEADBEEF");
});
<!DOCTYPE html>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<meta charset="utf-8" />
<meta
http-equiv="X-UA-Compatible"
content="IE=edge"
/>
<meta
name="viewport"
content="width=device-width,initial-scale=1.0"
/>
<title>Components App</title>
</head>
<body>
<div data-cy-root></div>
</body>
</html>
\ No newline at end of file
</html>
......@@ -14,16 +14,16 @@
// ***********************************************************
// Import commands.js using ES2015 syntax:
import "./commands"
import "./commands";
// Alternatively you can use CommonJS syntax:
// require("./commands")
import { mount } from "cypress/react"
import { interceptAPI } from "./interceptAPI"
import { mount } from "cypress/react";
import { interceptAPI } from "./interceptAPI";
import configure from "./configureWindowVars";
Cypress.Commands.add("mount", mount)
Cypress.Commands.add("mount", mount);
// Example use:
// cy.mount(<MyComponent />)
......@@ -34,4 +34,4 @@ configure();
// intercept API calls in component tests
beforeEach(() => {
interceptAPI();
});
\ No newline at end of file
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment