Skip to content

Commit 1c654f1

Browse files
committed
Merge branch 'master'
2 parents d64d8c3 + 38ab685 commit 1c654f1

File tree

513 files changed

+9079
-8742
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

513 files changed

+9079
-8742
lines changed

.eslintrc.json

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"browser": true,
44
"es2020": true,
55
"node": true,
6+
"jquery": true,
67
"jest": true
78
},
89
"parser": "@typescript-eslint/parser",
@@ -13,14 +14,8 @@
1314
"ecmaVersion": 11,
1415
"sourceType": "module"
1516
},
16-
"settings": {
17-
"import/resolver": {
18-
"node": {
19-
"moduleDirectory": ["node_modules", "src/"]
20-
}
21-
}
22-
},
2317
"extends": [
18+
"plugin:@typescript-eslint/eslint-recommended",
2419
"plugin:@typescript-eslint/recommended",
2520
"eslint:recommended",
2621
"plugin:prettier/recommended",
@@ -40,12 +35,14 @@
4035
"react/prop-types": "off",
4136
"import/no-anonymous-default-export": "off",
4237
"import/no-named-as-default": "off",
38+
"css-modules/no-unused-class": "off",
4339
"@next/next/no-img-element": "off",
4440
"@typescript-eslint/no-empty-function": "off",
4541
"@typescript-eslint/no-explicit-any": "off",
4642
"@typescript-eslint/no-var-requires": "off",
4743
"@typescript-eslint/no-empty-interface": "off",
48-
"@typescript-eslint/no-unused-vars": ["error", { "ignoreRestSiblings": true }]
44+
"@typescript-eslint/no-unused-vars": ["error", { "ignoreRestSiblings": true }],
45+
"@typescript-eslint/no-namespace": ["error", { "allowDeclarations": true }]
4946
},
5047
"globals": {
5148
"React": "writable"

.github/workflows/cd-cloud.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ on:
44
push:
55
branches:
66
- analytics
7+
- cloud
78

89
jobs:
910
build:

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ jobs:
1616
strategy:
1717
matrix:
1818
include:
19-
- node-version: 18.17
19+
- node-version: 18.18
2020
db-type: postgresql
21-
- node-version: 18.17
21+
- node-version: 18.18
2222
db-type: mysql
2323

2424
steps:

Dockerfile

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Install dependencies only when needed
2-
FROM node:18-alpine AS deps
2+
FROM node:22-alpine AS deps
33
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
44
RUN apk add --no-cache libc6-compat
55
WORKDIR /app
@@ -9,7 +9,7 @@ RUN yarn config set network-timeout 300000
99
RUN yarn install --frozen-lockfile
1010

1111
# Rebuild the source code only when needed
12-
FROM node:18-alpine AS builder
12+
FROM node:22-alpine AS builder
1313
WORKDIR /app
1414
COPY --from=deps /app/node_modules ./node_modules
1515
COPY . .
@@ -26,18 +26,21 @@ ENV NEXT_TELEMETRY_DISABLED 1
2626
RUN yarn build-docker
2727

2828
# Production image, copy all the files and run next
29-
FROM node:18-alpine AS runner
29+
FROM node:22-alpine AS runner
3030
WORKDIR /app
3131

32+
ARG NODE_OPTIONS
33+
3234
ENV NODE_ENV production
3335
ENV NEXT_TELEMETRY_DISABLED 1
36+
ENV NODE_OPTIONS $NODE_OPTIONS
3437

3538
RUN addgroup --system --gid 1001 nodejs
3639
RUN adduser --system --uid 1001 nextjs
3740

3841
RUN set -x \
3942
&& apk add --no-cache curl \
40-
&& yarn add npm-run-all dotenv semver prisma@5.17.0
43+
&& yarn add npm-run-all dotenv semver prisma@6.1.0
4144

4245
# You only need to copy next.config.js if you are NOT using the default configuration
4346
COPY --from=builder /app/next.config.js .

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ A detailed getting started guide can be found at [umami.is/docs](https://umami.i
3535

3636
### Requirements
3737

38-
- A server with Node.js version 16.13 or newer
38+
- A server with Node.js version 18.18 or newer
3939
- A database. Umami supports [MariaDB](https://www.mariadb.org/) (minimum v10.5), [MySQL](https://www.mysql.com/) (minimum v8.0) and [PostgreSQL](https://www.postgresql.org/) (minimum v12.14) databases.
4040

4141
### Install Yarn
@@ -121,7 +121,7 @@ To update the Docker image, simply pull the new images and rebuild:
121121

122122
```bash
123123
docker compose pull
124-
docker compose up --force-recreate
124+
docker compose up --force-recreate -d
125125
```
126126

127127
---

cypress/e2e/api.cy.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
describe('Website tests', () => {
2+
Cypress.session.clearAllSavedSessions();
3+
4+
beforeEach(() => {
5+
cy.login(Cypress.env('umami_user'), Cypress.env('umami_password'));
6+
});
7+
8+
//let userId;
9+
10+
it('creates a user.', () => {
11+
cy.fixture('users').then(data => {
12+
const userPost = data.userPost;
13+
cy.request({
14+
method: 'POST',
15+
url: '/api/users',
16+
headers: {
17+
'Content-Type': 'application/json',
18+
Authorization: Cypress.env('authorization'),
19+
},
20+
body: userPost,
21+
}).then(response => {
22+
//userId = response.body.id;
23+
expect(response.status).to.eq(200);
24+
expect(response.body).to.have.property('username', 'cypress1');
25+
expect(response.body).to.have.property('role', 'User');
26+
});
27+
});
28+
});
29+
});

cypress/e2e/login.cy.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,36 @@
11
describe('Login tests', () => {
2+
beforeEach(() => {
3+
cy.visit('/login');
4+
});
5+
26
it(
37
'logs user in with correct credentials and logs user out',
48
{
59
defaultCommandTimeout: 10000,
610
},
711
() => {
8-
cy.visit('/login');
9-
cy.getDataTest('input-username').find('input').click();
10-
cy.getDataTest('input-username').find('input').type(Cypress.env('umami_user'), { delay: 50 });
11-
cy.getDataTest('input-password').find('input').click();
12+
cy.getDataTest('input-username').find('input').as('inputUsername').click();
13+
cy.get('@inputUsername').type(Cypress.env('umami_user'), { delay: 0 });
14+
cy.get('@inputUsername').click();
1215
cy.getDataTest('input-password')
1316
.find('input')
14-
.type(Cypress.env('umami_password'), { delay: 50 });
17+
.type(Cypress.env('umami_password'), { delay: 0 });
1518
cy.getDataTest('button-submit').click();
1619
cy.url().should('eq', Cypress.config().baseUrl + '/dashboard');
17-
cy.getDataTest('button-profile').click();
18-
cy.getDataTest('item-logout').click();
19-
cy.url().should('eq', Cypress.config().baseUrl + '/login');
20+
cy.logout();
2021
},
2122
);
23+
24+
it('login with blank inputs or incorrect credentials', () => {
25+
cy.getDataTest('button-submit').click();
26+
cy.contains(/Required/i).should('be.visible');
27+
28+
cy.getDataTest('input-username').find('input').as('inputUsername');
29+
cy.get('@inputUsername').click();
30+
cy.get('@inputUsername').type(Cypress.env('umami_user'), { delay: 0 });
31+
cy.get('@inputUsername').click();
32+
cy.getDataTest('input-password').find('input').type('wrongpassword', { delay: 0 });
33+
cy.getDataTest('button-submit').click();
34+
cy.contains(/Incorrect username and\/or password./i).should('be.visible');
35+
});
2236
});

cypress/e2e/user.cy.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
describe('Website tests', () => {
2+
Cypress.session.clearAllSavedSessions();
3+
4+
beforeEach(() => {
5+
cy.login(Cypress.env('umami_user'), Cypress.env('umami_password'));
6+
cy.visit('/settings/users');
7+
});
8+
9+
it('Add a User', () => {
10+
// add user
11+
cy.contains(/Create user/i).should('be.visible');
12+
cy.getDataTest('button-create-user').click();
13+
cy.getDataTest('input-username').find('input').as('inputName').click();
14+
cy.get('@inputName').type('Test-user', { delay: 0 });
15+
cy.getDataTest('input-password').find('input').as('inputPassword').click();
16+
cy.get('@inputPassword').type('testPasswordCypress', { delay: 0 });
17+
cy.getDataTest('dropdown-role').click();
18+
cy.getDataTest('dropdown-item-user').click();
19+
cy.getDataTest('button-submit').click();
20+
cy.get('td[label="Username"]').should('contain.text', 'Test-user');
21+
cy.get('td[label="Role"]').should('contain.text', 'User');
22+
});
23+
24+
it('Edit a User role and password', () => {
25+
// edit user
26+
cy.get('table tbody tr')
27+
.contains('td', /Test-user/i)
28+
.parent()
29+
.within(() => {
30+
cy.getDataTest('link-button-edit').click(); // Clicks the button inside the row
31+
});
32+
cy.getDataTest('input-password').find('input').as('inputPassword').click();
33+
cy.get('@inputPassword').type('newPassword', { delay: 0 });
34+
cy.getDataTest('dropdown-role').click();
35+
cy.getDataTest('dropdown-item-viewOnly').click();
36+
cy.getDataTest('button-submit').click();
37+
38+
cy.visit('/settings/users');
39+
cy.get('table tbody tr')
40+
.contains('td', /Test-user/i)
41+
.parent()
42+
.should('contain.text', 'View only');
43+
44+
cy.logout();
45+
cy.url().should('eq', Cypress.config().baseUrl + '/login');
46+
cy.getDataTest('input-username').find('input').as('inputUsername').click();
47+
cy.get('@inputUsername').type('Test-user', { delay: 0 });
48+
cy.get('@inputUsername').click();
49+
cy.getDataTest('input-password').find('input').type('newPassword', { delay: 0 });
50+
cy.getDataTest('button-submit').click();
51+
cy.url().should('eq', Cypress.config().baseUrl + '/dashboard');
52+
});
53+
54+
it('Delete a website', () => {
55+
// delete user
56+
cy.get('table tbody tr')
57+
.contains('td', /Test-user/i)
58+
.parent()
59+
.within(() => {
60+
cy.getDataTest('button-delete').click(); // Clicks the button inside the row
61+
});
62+
cy.contains(/Are you sure you want to delete Test-user?/i).should('be.visible');
63+
cy.getDataTest('button-confirm').click();
64+
});
65+
});

cypress/e2e/website.cy.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ describe('Website tests', () => {
1010
cy.visit('/settings/websites');
1111
cy.getDataTest('button-website-add').click();
1212
cy.contains(/Add website/i).should('be.visible');
13-
cy.getDataTest('input-name').find('input').click();
14-
cy.getDataTest('input-name').find('input').type('Add test', { delay: 50 });
13+
cy.getDataTest('input-name').find('input').as('inputUsername').click();
14+
cy.getDataTest('input-name').find('input').type('Add test', { delay: 0 });
1515
cy.getDataTest('input-domain').find('input').click();
16-
cy.getDataTest('input-domain').find('input').type('addtest.com', { delay: 50 });
16+
cy.getDataTest('input-domain').find('input').type('addtest.com', { delay: 0 });
1717
cy.getDataTest('button-submit').click();
1818
cy.get('td[label="Name"]').should('contain.text', 'Add test');
1919
cy.get('td[label="Domain"]').should('contain.text', 'addtest.com');
@@ -41,10 +41,10 @@ describe('Website tests', () => {
4141
cy.contains(/Details/i).should('be.visible');
4242
cy.getDataTest('input-name').find('input').click();
4343
cy.getDataTest('input-name').find('input').clear();
44-
cy.getDataTest('input-name').find('input').type('Updated website', { delay: 50 });
44+
cy.getDataTest('input-name').find('input').type('Updated website', { delay: 0 });
4545
cy.getDataTest('input-domain').find('input').click();
4646
cy.getDataTest('input-domain').find('input').clear();
47-
cy.getDataTest('input-domain').find('input').type('updatedwebsite.com', { delay: 50 });
47+
cy.getDataTest('input-domain').find('input').type('updatedwebsite.com', { delay: 0 });
4848
cy.getDataTest('button-submit').click({ force: true });
4949
cy.getDataTest('input-name').find('input').should('have.value', 'Updated website');
5050
cy.getDataTest('input-domain').find('input').should('have.value', 'updatedwebsite.com');

cypress/fixtures/users.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"userGet": {
3+
"name": "cypress",
4+
"email": "password",
5+
"role": "User"
6+
},
7+
"userPost": {
8+
"username": "cypress1",
9+
"password": "password",
10+
"role": "User"
11+
},
12+
"userDelete": {
13+
"name": "Charlie",
14+
"email": "[email protected]",
15+
"age": 35
16+
}
17+
}

0 commit comments

Comments
 (0)