Skip to content

Commit 36c4645

Browse files
authored
Merge pull request umami-software#3294 from umami-software/analytics
v2.17.0
2 parents 2e84fc6 + 97c687f commit 36c4645

File tree

42 files changed

+395
-114
lines changed

Some content is hidden

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

42 files changed

+395
-114
lines changed

.eslintrc.json

Lines changed: 5 additions & 1 deletion
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",
@@ -14,6 +15,7 @@
1415
"sourceType": "module"
1516
},
1617
"extends": [
18+
"plugin:@typescript-eslint/eslint-recommended",
1719
"plugin:@typescript-eslint/recommended",
1820
"eslint:recommended",
1921
"plugin:prettier/recommended",
@@ -33,12 +35,14 @@
3335
"react/prop-types": "off",
3436
"import/no-anonymous-default-export": "off",
3537
"import/no-named-as-default": "off",
38+
"css-modules/no-unused-class": "off",
3639
"@next/next/no-img-element": "off",
3740
"@typescript-eslint/no-empty-function": "off",
3841
"@typescript-eslint/no-explicit-any": "off",
3942
"@typescript-eslint/no-var-requires": "off",
4043
"@typescript-eslint/no-empty-interface": "off",
41-
"@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 }]
4246
},
4347
"globals": {
4448
"React": "writable"

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+
}

cypress/support/e2e.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ Cypress.Commands.add('getDataTest', (value: string) => {
55
return cy.get(`[data-test=${value}]`);
66
});
77

8+
Cypress.Commands.add('logout', () => {
9+
cy.getDataTest('button-profile').click();
10+
cy.getDataTest('item-logout').click();
11+
cy.url().should('eq', Cypress.config().baseUrl + '/login');
12+
});
13+
814
Cypress.Commands.add('login', (username: string, password: string) => {
915
cy.session([username, password], () => {
1016
cy.request({

cypress/support/index.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/// <reference types="cypress" />
2+
/* global JQuery */
23

34
declare namespace Cypress {
45
interface Chainable {
@@ -7,6 +8,11 @@ declare namespace Cypress {
78
* @example cy.getDataTest('greeting')
89
*/
910
getDataTest(value: string): Chainable<JQuery<HTMLElement>>;
11+
/**
12+
* Custom command to logout through UI.
13+
* @example cy.logout()
14+
*/
15+
logout(): Chainable<JQuery<HTMLElement>>;
1016
/**
1117
* Custom command to login user into the app.
1218
* @example cy.login('admin', 'password)

next.config.js

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,29 @@ const trackerHeaders = [
5959
},
6060
];
6161

62+
const apiHeaders = [
63+
{
64+
key: 'Access-Control-Allow-Origin',
65+
value: '*'
66+
},
67+
{
68+
key: 'Access-Control-Allow-Headers',
69+
value: '*'
70+
},
71+
{
72+
key: 'Access-Control-Allow-Methods',
73+
value: 'GET, DELETE, POST, PUT'
74+
},
75+
{
76+
key: 'Access-Control-Max-Age',
77+
value: corsMaxAge || '86400'
78+
},
79+
];
80+
6281
const headers = [
6382
{
6483
source: '/api/:path*',
65-
headers: [
66-
{ key: 'Access-Control-Allow-Origin', value: '*' },
67-
{ key: 'Access-Control-Allow-Headers', value: '*' },
68-
{ key: 'Access-Control-Allow-Methods', value: 'GET, DELETE, POST, PUT' },
69-
{ key: 'Access-Control-Max-Age', value: corsMaxAge || '86400' },
70-
],
84+
headers: apiHeaders
7185
},
7286
{
7387
source: '/:path*',
@@ -89,6 +103,11 @@ if (trackerScriptURL) {
89103
}
90104

91105
if (collectApiEndpoint) {
106+
headers.push({
107+
source: collectApiEndpoint,
108+
headers: apiHeaders,
109+
});
110+
92111
rewrites.push({
93112
source: collectApiEndpoint,
94113
destination: '/api/send',

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "umami",
3-
"version": "2.16.1",
3+
"version": "2.17.0",
44
"description": "A simple, fast, privacy-focused alternative to Google Analytics.",
55
"author": "Umami Software, Inc. <[email protected]>",
66
"license": "MIT",

0 commit comments

Comments
 (0)