Remove cypress directory, move tsconfig

This commit is contained in:
Matthias 2024-04-14 09:12:13 +02:00
parent b6be4edba1
commit 0d27a036de
14 changed files with 0 additions and 634 deletions

View File

@ -1,44 +0,0 @@
import { setLoginInfo, defaultMocks } from './helpers';
function backtestMocks() {
cy.intercept('GET', '**/api/v1/show_config', {
fixture: 'backtest/show_config_webserver.json',
}).as('ShowConf');
cy.intercept('GET', '**/api/v1/strategies', { fixture: 'backtest/strategies.json' }).as(
'Strategies',
);
}
describe('Backtesting', () => {
it('Starts webserver mode', () => {
///
defaultMocks();
backtestMocks();
setLoginInfo();
cy.visit('/backtest');
cy.wait('@Ping');
cy.wait('@ShowConf');
// cy.wait('@Strategies');
cy.get('a').should('contain', 'Backtest');
cy.contains('Run backtest', { timeout: 10000 });
cy.contains('Strategy');
const strategySelect = cy.get('select[id=strategy-select]');
strategySelect.should('exist');
strategySelect.select('SampleStrategy');
cy.get('option[value=SampleStrategy]').should('exist');
cy.get('[id=bt-analyze-btn]').should('be.disabled');
cy.intercept('POST', '**/api/v1/backtest', { fixture: 'backtest/backtest_post_start.json' }).as(
'BacktestStart',
);
cy.intercept('GET', '**/api/v1/backtest', { fixture: 'backtest/backtest_get_end.json' }).as(
'BacktestPoll',
);
cy.get('button[id=start-backtest]').click();
cy.wait('@BacktestStart');
cy.wait('@BacktestPoll');
// All buttons are now enabled
cy.get('[id=bt-analyze-btn]').should('be.enabled');
});
});

View File

@ -1,45 +0,0 @@
import { setLoginInfo, defaultMocks } from './helpers';
function tradeMocks() {
cy.intercept('GET', '**/api/v1/status', { fixture: 'status_empty.json' }).as('Status');
cy.intercept('GET', '**/api/v1/profit', { fixture: 'profit.json' }).as('Profit');
cy.intercept('GET', '**/api/v1/trades*', { fixture: 'trades.json' }).as('Trades');
cy.intercept('GET', '**/api/v1/balance', { fixture: 'balance.json' }).as('Balance');
cy.intercept('GET', '**/api/v1/whitelist', { fixture: 'whitelist.json' }).as('Whitelist');
cy.intercept('GET', '**/api/v1/blacklist', { fixture: 'blacklist.json' }).as('Blacklist');
cy.intercept('GET', '**/api/v1/locks', { fixture: 'locks_empty.json' }).as('Locks');
}
describe('Chart', () => {
it('Chart view', { scrollBehavior: false }, () => {
defaultMocks();
tradeMocks();
setLoginInfo();
cy.viewport('macbook-11');
cy.visit('/graph');
cy.wait('@Ping');
cy.wait('@Status');
cy.wait('@Profit');
cy.wait('@Balance');
cy.wait('@Trades');
cy.wait('@Whitelist');
cy.wait('@Blacklist');
cy.wait('@Locks');
cy.wait('@PairCandles');
// Disable autorefresh
cy.get('input[title="AutoRefresh"]').click();
cy.get('span').contains('NoActionStrategyFut | 1m').should('be.visible');
cy.get('.form-check').contains('Heikin Ashi').click();
// Reload triggers a new request
cy.get('button[title*="Refresh chart"]').click();
cy.wait('@PairCandles');
// Disable Heikin Ashi
cy.get('.form-check').contains('Heikin Ashi').click();
// Default plotconfig exists
cy.get('.form-select').get('option').contains('default').should('exist');
});
});

View File

@ -1,44 +0,0 @@
import { setLoginInfo, defaultMocks } from './helpers';
function tradeMocks() {
cy.intercept('GET', '**/api/v1/status', { fixture: 'status_empty.json' }).as('Status');
cy.intercept('GET', '**/api/v1/profit', { fixture: 'profit.json' }).as('Profit');
cy.intercept('GET', '**/api/v1/trades*', { fixture: 'trades.json' }).as('Trades');
cy.intercept('GET', '**/api/v1/balance', { fixture: 'balance.json' }).as('Balance');
cy.intercept('GET', '**/api/v1/whitelist', { fixture: 'whitelist.json' }).as('Whitelist');
cy.intercept('GET', '**/api/v1/blacklist', { fixture: 'blacklist.json' }).as('Blacklist');
cy.intercept('GET', '**/api/v1/locks', { fixture: 'locks_empty.json' }).as('Locks');
// TODO: Daily mock is missing.
// cy.intercept('GET', '**/api/v1/daily', { fixture: 'performance.json' }).as('Performance');
}
describe('Dashboard', () => {
it('Dashboard view', () => {
defaultMocks();
tradeMocks();
setLoginInfo();
cy.visit('/dashboard');
cy.wait('@Ping');
cy.wait('@Status');
cy.wait('@Profit');
cy.wait('@Balance');
cy.wait('@Trades');
cy.wait('@Whitelist');
cy.wait('@Blacklist');
cy.wait('@Locks');
cy.get('.drag-header').contains('Bot comparison').should('be.visible');
cy.get('.drag-header').contains('Daily Profit').should('be.visible');
cy.get('.drag-header').contains('Open Trades').should('be.visible');
cy.get('.drag-header').contains('Cumulative Profit').should('be.visible');
// Assert Botcomparison content
cy.get('span').contains('TestBot').should('be.visible');
cy.get('span').contains('Summary').should('be.visible');
// Scroll lower
cy.get('.drag-header').contains('Closed Trades').scrollIntoView();
cy.get('.drag-header').contains('Closed Trades').should('be.visible');
cy.get('.drag-header').contains('Profit Distribution').should('be.visible');
cy.get('.drag-header').contains('Trades Log').should('be.visible');
});
});

View File

@ -1,31 +0,0 @@
export function setLoginInfo() {
localStorage.setItem(
'ftAuthLoginInfo',
JSON.stringify({
'ftbot.0': {
botName: 'TestBot',
apiUrl: 'http://localhost:3000',
accessToken: 'access_token_tesst',
refreshToken: 'refresh_test',
autoRefresh: true,
},
}),
);
localStorage.setItem('ftSelectedBot', 'ftbot.0');
}
export function defaultMocks() {
cy.intercept('**/api/v1/**', {
statusCode: 200,
headers: { 'access-control-allow-origin': '*' },
}).as('RandomAPICall');
cy.intercept('GET', '**/api/v1/ping', { fixture: 'ping.json' }).as('Ping');
cy.intercept('GET', '**/api/v1/show_config', {
fixture: 'show_config.json',
}).as('ShowConf');
cy.intercept('GET', '**/api/v1/pair_candles?*', {
fixture: 'pair_candles_btc_1m.json',
}).as('PairCandles');
}

View File

@ -1,150 +0,0 @@
describe('Login', () => {
it('Is not logged in', () => {
cy.visit('/');
cy.get('button').should('contain', 'Login');
cy.get('li').should('contain', 'No bot selected');
cy.get('button').contains('Login').click();
cy.get('.modal-title').contains('Login to your bot');
// Test prefilled URL
cy.get('input[id=url-input]').should('have.value', 'http://localhost:3000');
cy.get('#name-input').should('exist');
cy.get('#username-input').should('exist');
cy.get('#password-input').should('exist');
// Modal popup will use "OK" instead of "submit"
cy.get('button[type=submit]').should('not.exist');
});
it('Explicit login page', () => {
cy.visit('/login');
cy.get('button').should('contain', 'Login');
cy.get('li').should('contain', 'No bot selected');
cy.get('.card-header').contains('Freqtrade bot Login');
// Test prefilled URL
cy.get('input[id=url-input]').should('have.value', 'http://localhost:3000');
cy.get('input[id=name-input]').should('exist');
cy.get('input[id=username-input]').should('exist');
cy.get('input[id=password-input]').should('exist');
cy.get('button[type=submit]').should('exist');
});
it('Redirect when not logged in', () => {
cy.visit('/trade');
cy.location().should((loc) => {
expect(loc.pathname).to.eq('/login');
expect(loc.search).to.eq('?redirect=/trade');
});
});
it('Test Login', () => {
cy.visit('/login');
cy.get('.card-header').contains('Freqtrade bot Login');
cy.get('input[id=name-input]').type('TestBot');
cy.get('input[id=username-input]').type('Freqtrader');
cy.get('input[id=password-input]').type('SuperDuperBot');
cy.intercept('**/api/v1/**', {
statusCode: 200,
body: { access_token: 'access_token_tesst', refresh_token: 'refresh_test' },
headers: { 'access-control-allow-origin': '*' },
}).as('RandomAPICall');
cy.intercept(
{
method: 'Post',
url: '**/api/v1/token/login',
},
{
statusCode: 200,
body: { access_token: 'access_token_tesst', refresh_token: 'refresh_test' },
headers: { 'access-control-allow-origin': '*' },
},
).as('login');
cy.get('button[type=submit]')
.click()
.should(() => {
const loginInfo = JSON.parse(localStorage.getItem('ftAuthLoginInfo') || '{}');
const bot1 = 'ftbot.0';
expect(loginInfo[bot1].botName).to.eq('TestBot');
expect(loginInfo[bot1].botName).to.eq('TestBot');
expect(loginInfo[bot1].apiUrl).to.eq('http://localhost:3000');
expect(loginInfo[bot1].accessToken).to.eq('access_token_tesst');
expect(loginInfo[bot1].refreshToken).to.eq('refresh_test');
});
// Forwarded to Main page
cy.location().should((loc) => {
expect(loc.pathname).to.eq('/');
expect(loc.search).to.eq('');
});
cy.get('button').should('contain', 'Add new bot');
cy.get('span').should('contain', 'TestBot');
// Check API calls have been made.
cy.wait('@RandomAPICall');
// login button gone
cy.get('button').should('not.contain', 'Login');
// Test logout
cy.get('[id=avatar-drop]').parent().click();
cy.get('.dropdown-menu > .dropdown-item:last').click();
cy.get('button').should('contain', 'Login');
// login button there again
});
it('Test Login failed - wrong api url', () => {
cy.visit('/login');
cy.get('.card-header').contains('Freqtrade bot Login');
cy.get('input[id=name-input]').type('TestBot');
cy.get('input[id=username-input]').type('Freqtrader');
cy.get('input[id=password-input]').type('SuperDuperBot');
cy.intercept('**/api/v1/**', {
statusCode: 200,
body: { access_token: 'access_token_tesst', refresh_token: 'refresh_test' },
headers: { 'access-control-allow-origin': '*' },
}).as('RandomAPICall');
cy.intercept(
{
method: 'Post',
url: '**/api/v1/token/login',
},
{
statusCode: 404,
body: { access_token: 'access_token_tesst', refresh_token: 'refresh_test' },
headers: { 'access-control-allow-origin': '*' },
},
).as('login');
cy.get('button[type=submit]').click();
cy.get('div').should('contain', 'Login failed.');
cy.get('div').should('contain', 'API Url required');
});
it('Test Login failed - wrong password url', () => {
cy.visit('/login');
cy.get('.card-header').contains('Freqtrade bot Login');
cy.get('input[id=name-input]').type('TestBot');
cy.get('input[id=username-input]').type('Freqtrader');
cy.get('input[id=password-input]').type('SuperDuperBot');
cy.intercept('**/api/v1/**', {
statusCode: 200,
body: { access_token: 'access_token_tesst', refresh_token: 'refresh_test' },
headers: { 'access-control-allow-origin': '*' },
}).as('RandomAPICall');
cy.intercept(
{
method: 'Post',
url: '**/api/v1/token/login',
},
{
statusCode: 401,
body: { access_token: 'access_token_tesst', refresh_token: 'refresh_test' },
headers: { 'access-control-allow-origin': '*' },
},
).as('login');
cy.get('button[type=submit]').click();
cy.get('div').should('contain', 'Connected to bot, however Login');
cy.get('div').should('contain', 'Name and Password are required.');
});
});

View File

@ -1,18 +0,0 @@
import { setLoginInfo, defaultMocks } from './helpers';
describe('Logs', () => {
it('Displays and reloads logs', () => {
///
defaultMocks();
cy.intercept('GET', '**/api/v1/logs', { fixture: 'logs.json' }).as('Logs');
setLoginInfo();
cy.visit('/logs');
cy.wait('@Ping');
cy.wait('@ShowConf');
cy.wait('@Logs');
cy.get('span').should('contain.text', 'Checking exchange...');
cy.get('button[id=refresh-logs]').click();
cy.wait('@Logs');
});
});

View File

@ -1,77 +0,0 @@
import { setLoginInfo, defaultMocks } from './helpers';
function webserverMocksForPairlistConfig() {
cy.intercept('GET', '**/api/v1/show_config', {
fixture: 'backtest/show_config_webserver.json',
}).as('ShowConf');
cy.intercept('GET', '**/api/v1/pairlists/available*', {
fixture: 'pairlists_available.json',
}).as('PairlistsAvailable');
const jobID = 'c0578b6a-dd34-4bb7-b83c-492f02da2cfd';
cy.intercept('POST', '**/api/v1/pairlists/evaluate', {
status: 'Pairlist evaluation started in background.',
job_id: jobID,
}).as('EvaluateStart');
cy.intercept('GET', `**/api/v1/background/${jobID}`, {
job_id: jobID,
job_category: 'pairlist',
status: 'success',
running: false,
progress: null,
}).as('FetchBGJob');
cy.intercept('GET', `**/api/v1/pairlists/evaluate/${jobID}`, {
error: null,
status: 'success',
result: {
whitelist: ['BTC/USDT', 'ETH/USDT', 'BNB/USDT'],
length: 3,
method: ['VolumePairList'],
},
}).as('FetchPairlistResult');
}
describe('Pairlist Configurator', () => {
it('Pairlist Configurator nav', () => {
defaultMocks();
webserverMocksForPairlistConfig();
setLoginInfo();
cy.visit('/');
cy.wait('@ShowConf');
cy.contains('Pairlist Config').should('exist').click();
cy.wait('@PairlistsAvailable');
cy.contains('VolumePairList').should('exist');
cy.get('.available-pairlists > :nth-child(4)').should('contain', 'VolumePairList');
// Assign volumePairlist to selected list
cy.get('.available-pairlists > :nth-child(4) > button').click();
// Result is disabled
cy.get('.btn-group > :nth-child(3)').should('have.value', 'Results').should('be.disabled');
// Is part of the output
cy.get('.copy-container')
.scrollIntoView()
.should('be.visible')
.should('contain', '"method": "VolumePairList",');
cy.get('button').contains('Evaluate').click();
cy.wait('@EvaluateStart');
cy.wait('@FetchBGJob');
cy.wait('@FetchPairlistResult');
// Assert result view
cy.get('.btn-group > :nth-child(3)')
.should('have.value', 'Results')
.should('be.enabled')
.should('be.checked');
cy.get('.copy-container')
.should('be.visible')
.should('contain', '"BTC/USDT",')
.should('contain', '"ETH/USDT",')
.should('contain', '"BNB/USDT"');
});
});

View File

@ -1,28 +0,0 @@
import { setLoginInfo, defaultMocks } from './helpers';
describe('Settings', () => {
it('Settings stores', () => {
///
setLoginInfo();
defaultMocks();
cy.visit('/');
cy.wait('@Ping');
cy.wait('@ShowConf');
cy.get('li').contains('Online').should('be.visible');
cy.get('h1').contains('Welcome to the Freqtrade UI', { timeout: 5000 }).should('be.visible');
// cy.wait('@Strategies');
cy.get('[id=avatar-drop]').should('be.visible').parent().click();
cy.get('.dropdown-menu > * > [href="/settings"]').click();
cy.contains('FreqUI Settings');
// cy.get('[id=settings-lock-layout]').should('be.visible');
cy.get('select:first')
.select('asTitle')
.should(() => {
const settings = JSON.parse(localStorage.getItem('ftUISettings') || '{}');
expect(settings['openTradesInTitle']).to.eq('asTitle');
});
});
});

View File

@ -1,84 +0,0 @@
import { setLoginInfo, defaultMocks } from './helpers';
function tradeMocks() {
cy.intercept('GET', '**/api/v1/status', { fixture: 'status_empty.json' }).as('Status');
cy.intercept('GET', '**/api/v1/profit', { fixture: 'profit.json' }).as('Profit');
cy.intercept('GET', '**/api/v1/trades*', { fixture: 'trades.json' }).as('Trades');
cy.intercept('GET', '**/api/v1/balance', { fixture: 'balance.json' }).as('Balance');
cy.intercept('GET', '**/api/v1/whitelist', { fixture: 'whitelist.json' }).as('Whitelist');
cy.intercept('GET', '**/api/v1/blacklist', { fixture: 'blacklist.json' }).as('Blacklist');
cy.intercept('GET', '**/api/v1/locks', { fixture: 'locks_empty.json' }).as('Locks');
cy.intercept('GET', '**/api/v1/performance', { fixture: 'performance.json' }).as('Performance');
cy.intercept('POST', '**/api/v1/reload_config', { fixture: 'reload_config.json' }).as(
'ReloadConfig',
);
}
describe('Trade', () => {
it('Trade view', { scrollBehavior: false }, () => {
defaultMocks();
tradeMocks();
setLoginInfo();
cy.viewport('macbook-11');
cy.visit('/trade');
cy.wait('@Ping');
cy.wait('@Status');
cy.wait('@Profit');
cy.wait('@Balance');
cy.wait('@Trades');
cy.wait('@Whitelist');
cy.wait('@Blacklist');
cy.wait('@Locks');
cy.get('.drag-header').contains('Multi Pane').should('be.visible');
cy.get('.drag-header').contains('Chart').should('be.visible');
cy.get('button').should('contain', 'BTC/USDT');
cy.get('button').should('contain', 'ETH/USDT').should('be.visible');
cy.get('button').contains('ETH/USDT').should('be.visible');
cy.get('button').contains('Performance').should('be.visible').click();
cy.wait('@Performance');
cy.get('th').contains('Profit USDT').should('be.visible');
// Test messageBox behavior
// No modal visible
cy.get('.modal-dialog > .modal-content > .modal-footer > .btn-secondary')
.filter(':visible')
.should('have.length', 0);
cy.get('button[title*="Stop Trading"]').click();
// Modal open
cy.get('.modal-dialog > .modal-content > .modal-footer > .btn-secondary')
.filter(':visible')
.contains('Cancel')
.should('be.visible')
.click();
// Modal closed
cy.get('.modal-dialog > .modal-content > .modal-footer > .btn-secondary')
.filter(':visible')
.should('have.length', 0);
// General
cy.get('button[role="tab"]').contains('General').click();
cy.get('button').contains('ETH/USDT').should('not.be.visible');
// 2nd segment
cy.get('.drag-header').contains('Open Trades').scrollIntoView().should('be.visible');
cy.get('.drag-header').contains('Closed Trades').scrollIntoView().should('be.visible');
cy.get('span').contains('TRX/USDT').should('be.visible');
cy.get('td').contains('8070.5').should('be.visible');
// Scroll to top
cy.contains('Multi Pane').scrollIntoView().should('be.visible');
cy.get('button[title*="Reload Config "]').click();
// Reload Modal open
cy.get('.modal-dialog > .modal-content > .modal-footer > .btn-primary')
.filter(':visible')
.contains('Ok')
.should('be.visible')
.click();
// Alert is visible
cy.contains('Config reloaded successfully.').scrollIntoView().should('be.visible');
});
});

View File

@ -1,37 +0,0 @@
/// <reference types="cypress" />
// ***********************************************
// This example commands.ts shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
//
// declare global {
// namespace Cypress {
// interface Chainable {
// login(email: string, password: string): Chainable<void>
// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
// }
// }
// }

View File

@ -1,12 +0,0 @@
<!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">
<title>Components App</title>
</head>
<body>
<div data-cy-root></div>
</body>
</html>

View File

@ -1,41 +0,0 @@
// ***********************************************************
// This example support/component.ts is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands';
// Alternatively you can use CommonJS syntax:
// require('./commands')
import { mount } from 'cypress/vue';
declare global {
namespace Cypress {
interface Chainable {
mount: typeof mount;
}
}
}
// Augment the Cypress namespace to include type definitions for
// your custom command.
// Alternatively, can be defined in cypress/support/component.d.ts
// with a <reference path="./component" /> at the top of your spec.
// import '../../src/assets/main.css';
Cypress.Commands.add('mount', mount);
// Example use:
// cy.mount(MyComponent);s

View File

@ -1,20 +0,0 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands';
// Alternatively you can use CommonJS syntax:
// require('./commands')

View File

@ -2,9 +2,6 @@
"extends": "../tsconfig.json",
"compilerOptions": {
"sourceMap": false,
"types": [
"cypress",
],
},
"include": [
"e2e/*.ts",