mirror of
https://github.com/NginxProxyManager/nginx-proxy-manager.git
synced 2025-08-04 16:33:32 +00:00
@@ -1 +0,0 @@
|
||||
node_modules
|
@@ -1,76 +0,0 @@
|
||||
{
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"cypress/globals": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:cypress/recommended"
|
||||
],
|
||||
"globals": {
|
||||
"Atomics": "readonly",
|
||||
"SharedArrayBuffer": "readonly"
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"cypress",
|
||||
"chai-friendly",
|
||||
"align-assignments"
|
||||
],
|
||||
"rules": {
|
||||
"indent": [
|
||||
"error",
|
||||
"tab"
|
||||
],
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
"unix"
|
||||
],
|
||||
"quotes": [
|
||||
"error",
|
||||
"single"
|
||||
],
|
||||
"semi": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"key-spacing": [
|
||||
"error",
|
||||
{
|
||||
"align": "value"
|
||||
}
|
||||
],
|
||||
"comma-spacing": [
|
||||
"error",
|
||||
{
|
||||
"before": false,
|
||||
"after": true
|
||||
}
|
||||
],
|
||||
"func-call-spacing": [
|
||||
"error",
|
||||
"never"
|
||||
],
|
||||
"keyword-spacing": [
|
||||
"error",
|
||||
{
|
||||
"before": true
|
||||
}
|
||||
],
|
||||
"no-irregular-whitespace": "error",
|
||||
"cypress/no-assigning-return-values": "error",
|
||||
"cypress/no-unnecessary-waiting": "warn",
|
||||
"no-unused-expressions": 0,
|
||||
"chai-friendly/no-unused-expressions": 2,
|
||||
"align-assignments/align-assignments": [
|
||||
2,
|
||||
{
|
||||
"requiresOnly": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
4
test/.gitignore
vendored
4
test/.gitignore
vendored
@@ -1,4 +0,0 @@
|
||||
.vscode
|
||||
node_modules
|
||||
results
|
||||
cypress/videos
|
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"printWidth": 160,
|
||||
"tabWidth": 4,
|
||||
"useTabs": true,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"bracketSpacing": true,
|
||||
"jsxBracketSameLine": true,
|
||||
"trailingComma": "all",
|
||||
"proseWrap": "always"
|
||||
}
|
@@ -1,46 +0,0 @@
|
||||
# Cypress Test Suite
|
||||
|
||||
## Running Locally
|
||||
|
||||
```
|
||||
cd nginxproxymanager/test
|
||||
yarn install
|
||||
yarn run cypress
|
||||
```
|
||||
|
||||
## VS Code
|
||||
|
||||
Editor settings are not committed to the repository, typically because each developer has their own settings. Below is a list of common setting that may help,
|
||||
so feel free to try them or ignore them, you are a strong independent developer. You can add settings to either "user" or "workspace" but we recommend using
|
||||
"workspace" as each project is different.
|
||||
|
||||
### ESLint
|
||||
|
||||
The ESLint extension only works on JavaScript files by default, so add the following to your workspace settings and reload VSCode.
|
||||
|
||||
```
|
||||
"eslint.autoFixOnSave": true,
|
||||
"eslint.validate": [
|
||||
{ "language": "javascript", "autoFix": true },
|
||||
"html"
|
||||
]
|
||||
```
|
||||
|
||||
> NOTE: If you've also set the editor.formatOnSave option to true in your settings.json, you'll need to add the following config to prevent running 2 formatting
|
||||
> commands on save for JavaScript and TypeScript files:
|
||||
|
||||
```
|
||||
"editor.formatOnSave": true,
|
||||
"[javascript]": {
|
||||
"editor.formatOnSave": false,
|
||||
},
|
||||
"[javascriptreact]": {
|
||||
"editor.formatOnSave": false,
|
||||
},
|
||||
"[typescript]": {
|
||||
"editor.formatOnSave": false,
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.formatOnSave": false,
|
||||
},
|
||||
```
|
@@ -1,13 +0,0 @@
|
||||
FROM cypress/included:5.6.0
|
||||
|
||||
COPY --chown=1000 ./ /test
|
||||
|
||||
# mkcert
|
||||
ENV MKCERT=1.4.2
|
||||
RUN wget -O /usr/bin/mkcert "https://github.com/FiloSottile/mkcert/releases/download/v${MKCERT}/mkcert-v${MKCERT}-linux-amd64" \
|
||||
&& chmod +x /usr/bin/mkcert
|
||||
|
||||
WORKDIR /test
|
||||
RUN yarn install
|
||||
ENTRYPOINT []
|
||||
CMD ["cypress", "run"]
|
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"requestTimeout": 30000,
|
||||
"defaultCommandTimeout": 20000,
|
||||
"reporter": "cypress-multi-reporters",
|
||||
"reporterOptions": {
|
||||
"configFile": "multi-reporter.json"
|
||||
},
|
||||
"videosFolder": "results/videos",
|
||||
"screenshotsFolder": "results/screenshots",
|
||||
"env": {
|
||||
"swaggerBase": "{{baseUrl}}/api/schema",
|
||||
"RETRIES": 4
|
||||
}
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"requestTimeout": 30000,
|
||||
"defaultCommandTimeout": 20000,
|
||||
"reporter": "cypress-multi-reporters",
|
||||
"reporterOptions": {
|
||||
"configFile": "multi-reporter.json"
|
||||
},
|
||||
"videos": false,
|
||||
"screenshotsFolder": "results/screenshots",
|
||||
"env": {
|
||||
"swaggerBase": "{{baseUrl}}/api/schema",
|
||||
"RETRIES": 0
|
||||
}
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
/// <reference types="Cypress" />
|
||||
|
||||
describe('Basic API checks', () => {
|
||||
it('Should return a valid health payload', function () {
|
||||
cy.task('backendApiGet', {
|
||||
path: '/api/',
|
||||
}).then((data) => {
|
||||
// Check the swagger schema:
|
||||
cy.validateSwaggerSchema('get', 200, '/', data);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should return a valid schema payload', function () {
|
||||
cy.task('backendApiGet', {
|
||||
path: '/api/schema',
|
||||
}).then((data) => {
|
||||
expect(data.openapi).to.be.equal('3.0.0');
|
||||
});
|
||||
});
|
||||
});
|
@@ -1,48 +0,0 @@
|
||||
/// <reference types="Cypress" />
|
||||
|
||||
describe('Users endpoints', () => {
|
||||
let token;
|
||||
|
||||
before(() => {
|
||||
cy.getToken().then((tok) => {
|
||||
token = tok;
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to get yourself', function() {
|
||||
cy.task('backendApiGet', {
|
||||
token: token,
|
||||
path: '/api/users/me'
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('get', 200, '/users/{userID}', data);
|
||||
expect(data).to.have.property('id');
|
||||
expect(data.id).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to get all users', function() {
|
||||
cy.task('backendApiGet', {
|
||||
token: token,
|
||||
path: '/api/users'
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('get', 200, '/users', data);
|
||||
expect(data.length).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to update yourself', function() {
|
||||
cy.task('backendApiPut', {
|
||||
token: token,
|
||||
path: '/api/users/me',
|
||||
data: {
|
||||
name: 'changed name'
|
||||
}
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('put', 200, '/users/{userID}', data);
|
||||
expect(data).to.have.property('id');
|
||||
expect(data.id).to.be.greaterThan(0);
|
||||
expect(data.name).to.be.equal('changed name');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
@@ -1,142 +0,0 @@
|
||||
const logger = require('./logger');
|
||||
const restler = require('@jc21/restler');
|
||||
|
||||
const BackendApi = function(config, token) {
|
||||
this.config = config;
|
||||
this.token = token;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} token
|
||||
*/
|
||||
BackendApi.prototype.setToken = function(token) {
|
||||
this.token = token;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} path
|
||||
* @param {bool} [returnOnError]
|
||||
* @returns {Promise<object>}
|
||||
*/
|
||||
BackendApi.prototype.get = function(path, returnOnError) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let headers = {
|
||||
Accept: 'application/json'
|
||||
};
|
||||
if (this.token) {
|
||||
headers.Authorization = 'Bearer ' + this.token;
|
||||
}
|
||||
|
||||
logger('GET ', this.config.baseUrl + path);
|
||||
|
||||
restler
|
||||
.get(this.config.baseUrl + path, {
|
||||
headers: headers,
|
||||
})
|
||||
.on('complete', function(data, response) {
|
||||
logger('Response data:', data);
|
||||
if (!returnOnError && data instanceof Error) {
|
||||
reject(data);
|
||||
} else if (!returnOnError && response.statusCode != 200) {
|
||||
if (typeof data === 'object' && typeof data.error === 'object' && typeof data.error.message !== 'undefined') {
|
||||
reject(new Error(data.error.code + ': ' + data.error.message));
|
||||
} else {
|
||||
reject(new Error('Error ' + response.statusCode));
|
||||
}
|
||||
} else {
|
||||
resolve(data);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} path
|
||||
* @param {bool} [returnOnError]
|
||||
* @returns {Promise<object>}
|
||||
*/
|
||||
BackendApi.prototype.delete = function(path, returnOnError) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let headers = {
|
||||
Accept: 'application/json'
|
||||
};
|
||||
if (this.token) {
|
||||
headers.Authorization = 'Bearer ' + this.token;
|
||||
}
|
||||
|
||||
logger('DELETE ', this.config.baseUrl + path);
|
||||
|
||||
restler
|
||||
.del(this.config.baseUrl + path, {
|
||||
headers: headers,
|
||||
})
|
||||
.on('complete', function(data, response) {
|
||||
logger('Response data:', data);
|
||||
if (!returnOnError && data instanceof Error) {
|
||||
reject(data);
|
||||
} else if (!returnOnError && response.statusCode != 200) {
|
||||
if (typeof data === 'object' && typeof data.error === 'object' && typeof data.error.message !== 'undefined') {
|
||||
reject(new Error(data.error.code + ': ' + data.error.message));
|
||||
} else {
|
||||
reject(new Error('Error ' + response.statusCode));
|
||||
}
|
||||
} else {
|
||||
resolve(data);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} path
|
||||
* @param {object} data
|
||||
* @param {bool} [returnOnError]
|
||||
* @returns {Promise<object>}
|
||||
*/
|
||||
BackendApi.prototype.postJson = function(path, data, returnOnError) {
|
||||
logger('POST ', this.config.baseUrl + path);
|
||||
return this._putPostJson('postJson', path, data, returnOnError);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} path
|
||||
* @param {object} data
|
||||
* @param {bool} [returnOnError]
|
||||
* @returns {Promise<object>}
|
||||
*/
|
||||
BackendApi.prototype.putJson = function(path, data, returnOnError) {
|
||||
logger('PUT ', this.config.baseUrl + path);
|
||||
return this._putPostJson('putJson', path, data, returnOnError);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} path
|
||||
* @param {object} data
|
||||
* @param {bool} [returnOnError]
|
||||
* @returns {Promise<object>}
|
||||
*/
|
||||
BackendApi.prototype._putPostJson = function(fn, path, data, returnOnError) {
|
||||
return new Promise((resolve, reject) => {
|
||||
restler[fn](this.config.baseUrl + path, data, {
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: 'Bearer ' + this.token,
|
||||
},
|
||||
}).on('complete', function(data, response) {
|
||||
logger('Response data:', data);
|
||||
if (!returnOnError && data instanceof Error) {
|
||||
reject(data);
|
||||
} else if (!returnOnError && response.statusCode != 200) {
|
||||
if (typeof data === 'object' && typeof data.error === 'object' && typeof data.error.message !== 'undefined') {
|
||||
reject(new Error(data.error.code + ': ' + data.error.message));
|
||||
} else {
|
||||
reject(new Error('Error ' + response.statusCode));
|
||||
}
|
||||
} else {
|
||||
resolve(data);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = BackendApi;
|
@@ -1,8 +0,0 @@
|
||||
const _ = require('lodash');
|
||||
const chalk = require('chalk');
|
||||
|
||||
module.exports = function () {
|
||||
var arr = _.values(arguments);
|
||||
arr.unshift(chalk.blue.bold('[') + chalk.yellow.bold('Backend API') + chalk.blue.bold(']'));
|
||||
console.log.apply(null, arr);
|
||||
};
|
@@ -1,64 +0,0 @@
|
||||
const logger = require('./logger');
|
||||
const Client = require('./client');
|
||||
|
||||
module.exports = function (config) {
|
||||
|
||||
logger('Client Ready using', config.baseUrl);
|
||||
|
||||
return {
|
||||
|
||||
/**
|
||||
* @param {object} options
|
||||
* @param {string} options.path API path
|
||||
* @param {string} [options.token] JWT
|
||||
* @param {bool} [options.returnOnError] If true, will return instead of throwing errors
|
||||
* @returns {string}
|
||||
*/
|
||||
backendApiGet: (options) => {
|
||||
const api = new Client(config);
|
||||
api.setToken(options.token);
|
||||
return api.get(options.path, options.returnOnError || false);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {object} options
|
||||
* @param {string} options.token JWT
|
||||
* @param {string} options.path API path
|
||||
* @param {object} options.data
|
||||
* @param {bool} [options.returnOnError] If true, will return instead of throwing errors
|
||||
* @returns {string}
|
||||
*/
|
||||
backendApiPost: (options) => {
|
||||
const api = new Client(config);
|
||||
api.setToken(options.token);
|
||||
return api.postJson(options.path, options.data, options.returnOnError || false);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {object} options
|
||||
* @param {string} options.token JWT
|
||||
* @param {string} options.path API path
|
||||
* @param {object} options.data
|
||||
* @param {bool} [options.returnOnError] If true, will return instead of throwing errors
|
||||
* @returns {string}
|
||||
*/
|
||||
backendApiPut: (options) => {
|
||||
const api = new Client(config);
|
||||
api.setToken(options.token);
|
||||
return api.putJson(options.path, options.data, options.returnOnError || false);
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {object} options
|
||||
* @param {string} options.token JWT
|
||||
* @param {string} options.path API path
|
||||
* @param {bool} [options.returnOnError] If true, will return instead of throwing errors
|
||||
* @returns {string}
|
||||
*/
|
||||
backendApiDelete: (options) => {
|
||||
const api = new Client(config);
|
||||
api.setToken(options.token);
|
||||
return api.delete(options.path, options.returnOnError || false);
|
||||
}
|
||||
};
|
||||
};
|
@@ -1,20 +0,0 @@
|
||||
const {SwaggerValidation} = require('@jc21/cypress-swagger-validation');
|
||||
|
||||
module.exports = (on, config) => {
|
||||
// Replace swaggerBase config var wildcard
|
||||
if (typeof config.env.swaggerBase !== 'undefined') {
|
||||
config.env.swaggerBase = config.env.swaggerBase.replace('{{baseUrl}}', config.baseUrl);
|
||||
}
|
||||
|
||||
// Plugin Events
|
||||
on('task', SwaggerValidation(config));
|
||||
on('task', require('./backendApi/task')(config));
|
||||
on('task', {
|
||||
log(message) {
|
||||
console.log(message);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
return config;
|
||||
};
|
@@ -1,42 +0,0 @@
|
||||
// ***********************************************
|
||||
// This example commands.js 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
|
||||
// ***********************************************
|
||||
//
|
||||
|
||||
/**
|
||||
* Check the swagger schema:
|
||||
*
|
||||
* @param {string} method API Method in swagger doc, "get", "put", "post", "delete"
|
||||
* @param {number} statusCode API status code in swagger doc
|
||||
* @param {string} path Swagger doc endpoint path, exactly as defined in swagger doc
|
||||
* @param {*} data The API response data to check against the swagger schema
|
||||
*/
|
||||
Cypress.Commands.add('validateSwaggerSchema', (method, statusCode, path, data) => {
|
||||
cy.task('validateSwaggerSchema', {
|
||||
file: Cypress.env('swaggerBase'),
|
||||
endpoint: path,
|
||||
method: method,
|
||||
statusCode: statusCode,
|
||||
responseSchema: data,
|
||||
verbose: true
|
||||
}).should('equal', null);
|
||||
});
|
||||
|
||||
Cypress.Commands.add('getToken', () => {
|
||||
// login with existing user
|
||||
cy.task('backendApiPost', {
|
||||
path: '/api/tokens',
|
||||
data: {
|
||||
identity: 'admin@example.com',
|
||||
secret: 'changeme'
|
||||
}
|
||||
}).then(res => {
|
||||
cy.wrap(res.token);
|
||||
});
|
||||
});
|
@@ -1,9 +0,0 @@
|
||||
require('cypress-plugin-retries');
|
||||
|
||||
import './commands';
|
||||
|
||||
Cypress.on('uncaught:exception', (/*err, runnable*/) => {
|
||||
// returning false here prevents Cypress from
|
||||
// failing the test
|
||||
return false;
|
||||
});
|
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"include": [
|
||||
"./node_modules/cypress",
|
||||
"cypress/**/*.js"
|
||||
]
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"reporterEnabled": "spec, mocha-junit-reporter",
|
||||
"mochaJunitReporterReporterOptions": {
|
||||
"jenkinsMode": true,
|
||||
"rootSuiteTitle": "Cypress.npm",
|
||||
"jenkinsClassnamePrefix": "Cypress.npm.",
|
||||
"mochaFile": "results/junit/cypress.npm.[hash].xml"
|
||||
}
|
||||
}
|
@@ -1,27 +0,0 @@
|
||||
{
|
||||
"name": "test",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"@jc21/cypress-swagger-validation": "^0.0.9",
|
||||
"@jc21/restler": "^3.4.0",
|
||||
"chalk": "^4.1.0",
|
||||
"cypress": "^5.6.0",
|
||||
"cypress-multi-reporters": "^1.4.0",
|
||||
"cypress-plugin-retries": "^1.5.2",
|
||||
"eslint": "^7.6.0",
|
||||
"eslint-plugin-align-assignments": "^1.1.2",
|
||||
"eslint-plugin-chai-friendly": "^0.6.0",
|
||||
"eslint-plugin-cypress": "^2.11.1",
|
||||
"lodash": "^4.17.19",
|
||||
"mocha": "^8.1.1",
|
||||
"mocha-junit-reporter": "^2.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"cypress": "cypress open --config-file=cypress/config/dev.json --config baseUrl=${BASE_URL:-http://127.0.0.1:3081}",
|
||||
"cypress:headless": "cypress run --config-file=cypress/config/dev.json --config baseUrl=${BASE_URL:-http://127.0.0.1:3081}"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
2730
test/yarn.lock
2730
test/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user