Moved v3 code from NginxProxyManager/nginx-proxy-manager-3 to NginxProxyManager/nginx-proxy-manager
This commit is contained in:
@ -1 +0,0 @@
|
||||
node_modules
|
6
test/.gitignore
vendored
6
test/.gitignore
vendored
@ -1,4 +1,2 @@
|
||||
.vscode
|
||||
node_modules
|
||||
results
|
||||
cypress/videos
|
||||
results/*
|
||||
cypress/results/*
|
||||
|
@ -1,11 +1,6 @@
|
||||
FROM cypress/included:5.6.0
|
||||
FROM cypress/included:9.4.1
|
||||
|
||||
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
|
||||
COPY --chown=1000 ./test /test
|
||||
|
||||
WORKDIR /test
|
||||
RUN yarn install
|
||||
|
119
test/cypress/integration/api/Certificates.spec.js
Normal file
119
test/cypress/integration/api/Certificates.spec.js
Normal file
@ -0,0 +1,119 @@
|
||||
/// <reference types="Cypress" />
|
||||
|
||||
describe('Certificates endpoints', () => {
|
||||
let token;
|
||||
let certID;
|
||||
|
||||
before(() => {
|
||||
cy.getToken().then((tok) => {
|
||||
token = tok;
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to create new certificate', function() {
|
||||
cy.task('backendApiPost', {
|
||||
token: token,
|
||||
path: '/api/certificates',
|
||||
data: {
|
||||
type: 'http',
|
||||
certificate_authority_id: 1,
|
||||
name: 'My First Cert',
|
||||
domain_names: [
|
||||
'jc21.com',
|
||||
'*.google.com'
|
||||
]
|
||||
}
|
||||
}).then((data) => {
|
||||
// Check the swagger schema:
|
||||
cy.validateSwaggerSchema('post', 201, '/certificates', data);
|
||||
expect(data.result).to.have.property('id');
|
||||
expect(data.result.id).to.be.greaterThan(0);
|
||||
expect(data.result.user_id).to.be.greaterThan(0);
|
||||
certID = data.result.id;
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to get a certificate', function() {
|
||||
cy.task('backendApiGet', {
|
||||
token: token,
|
||||
path: '/api/certificates/' + certID
|
||||
}).then((data) => {
|
||||
// Check the swagger schema:
|
||||
cy.validateSwaggerSchema('get', 200, '/certificates/{certificateID}', data);
|
||||
expect(data.result).to.have.property('id', certID);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to update a certificate', function() {
|
||||
cy.task('backendApiPut', {
|
||||
token: token,
|
||||
path: '/api/certificates/' + certID,
|
||||
data: {
|
||||
name: 'My Updated Cert'
|
||||
}
|
||||
}).then((data) => {
|
||||
// Check the swagger schema:
|
||||
cy.validateSwaggerSchema('put', 200, '/certificates/{certificateID}', data);
|
||||
expect(data.result).to.have.property('id', certID);
|
||||
expect(data.result).to.have.property('name', 'My Updated Cert');
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to get all certificates', function() {
|
||||
cy.task('backendApiGet', {
|
||||
token: token,
|
||||
path: '/api/certificates'
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('get', 200, '/certificates', data);
|
||||
expect(data).to.have.property('result');
|
||||
expect(data.result).to.have.property('items');
|
||||
expect(data.result.items.length).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to get all certificates with filters A', function() {
|
||||
cy.task('backendApiGet', {
|
||||
token: token,
|
||||
path: '/api/certificates?sort=name&name:starts=my&limit=1'
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('get', 200, '/certificates', data);
|
||||
expect(data).to.have.property('result');
|
||||
expect(data.result).to.have.property('items');
|
||||
expect(data.result.items.length).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to get all certificates with filters B', function() {
|
||||
cy.task('backendApiGet', {
|
||||
token: token,
|
||||
path: '/api/certificates?id:in=1,2,3,4,5&limit=1'
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('get', 200, '/certificates', data);
|
||||
expect(data).to.have.property('result');
|
||||
expect(data.result).to.have.property('items');
|
||||
expect(data.result.items.length).to.eq(1);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to get all certificates with filters C', function() {
|
||||
cy.task('backendApiGet', {
|
||||
token: token,
|
||||
path: '/api/certificates?name:starts=xxxxxxxxxxxxxxx'
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('get', 200, '/certificates', data);
|
||||
expect(data).to.have.property('result');
|
||||
expect(data.result).to.have.property('total', 0);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to delete a certificate', function() {
|
||||
cy.task('backendApiDelete', {
|
||||
token: token,
|
||||
path: '/api/certificates/' + certID
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('delete', 200, '/certificates/{certificateID}', data);
|
||||
expect(data).to.have.property('result', true);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
95
test/cypress/integration/api/FullCertProvision.spec.js
Normal file
95
test/cypress/integration/api/FullCertProvision.spec.js
Normal file
@ -0,0 +1,95 @@
|
||||
/// <reference types="Cypress" />
|
||||
|
||||
describe('Full Certificate Provisions', () => {
|
||||
let token;
|
||||
let caID;
|
||||
let dnsID;
|
||||
|
||||
before(() => {
|
||||
cy.getToken().then((tok) => {
|
||||
token = tok;
|
||||
|
||||
cy.task('backendApiPost', {
|
||||
token: token,
|
||||
path: '/api/certificate-authorities',
|
||||
data: {
|
||||
name: 'Test CA',
|
||||
acmesh_server: 'https://ca.internal/acme/acme/directory',
|
||||
ca_bundle: '/etc/ssl/certs/NginxProxyManager.crt',
|
||||
max_domains: 5,
|
||||
is_wildcard_supported: true
|
||||
}
|
||||
}).then((data) => {
|
||||
// cy.validateSwaggerSchema('post', 201, '/certificate-authorities', data);
|
||||
expect(data.result).to.have.property('id');
|
||||
expect(data.result.id).to.be.greaterThan(0);
|
||||
caID = data.result.id;
|
||||
});
|
||||
|
||||
cy.task('backendApiPost', {
|
||||
token: token,
|
||||
path: '/api/dns-providers',
|
||||
data: {
|
||||
acmesh_name: 'dns_pdns',
|
||||
name: 'PowerDNS - example.com',
|
||||
dns_sleep: 5,
|
||||
meta: {
|
||||
url: 'http://ns1.pdns:8081',
|
||||
server_id: 'localhost',
|
||||
token: 'npm',
|
||||
ttl: '5'
|
||||
}
|
||||
}
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('post', 201, '/dns-providers', data);
|
||||
expect(data.result).to.have.property('id');
|
||||
expect(data.result.id).to.be.greaterThan(0);
|
||||
dnsID = data.result.id;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to create new http certificate', function() {
|
||||
cy.task('backendApiPost', {
|
||||
token: token,
|
||||
path: '/api/certificates',
|
||||
data: {
|
||||
type: 'http',
|
||||
certificate_authority_id: caID,
|
||||
name: 'website1.example.com',
|
||||
domain_names: [
|
||||
'website1.example.com'
|
||||
]
|
||||
}
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('post', 201, '/certificates', data);
|
||||
expect(data.result).to.have.property('id');
|
||||
expect(data.result.id).to.be.greaterThan(0);
|
||||
expect(data.result.user_id).to.be.greaterThan(0);
|
||||
cy.waitForCertificateStatus(token, data.result.id, 'provided');
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to create new dns certificate', function() {
|
||||
cy.task('backendApiPost', {
|
||||
token: token,
|
||||
path: '/api/certificates',
|
||||
data: {
|
||||
type: 'dns',
|
||||
certificate_authority_id: caID,
|
||||
dns_provider_id: dnsID,
|
||||
name: 'dns: website2.example.com',
|
||||
domain_names: [
|
||||
'website2.example.com'
|
||||
]
|
||||
}
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('post', 201, '/certificates', data);
|
||||
expect(data.result).to.have.property('id');
|
||||
expect(data.result.id).to.be.greaterThan(0);
|
||||
expect(data.result.user_id).to.be.greaterThan(0);
|
||||
cy.waitForCertificateStatus(token, data.result.id, 'provided');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
@ -1,20 +1,12 @@
|
||||
/// <reference types="Cypress" />
|
||||
|
||||
describe('Basic API checks', () => {
|
||||
it('Should return a valid health payload', function () {
|
||||
it('Should return a valid health payload', function() {
|
||||
cy.task('backendApiGet', {
|
||||
path: '/api/',
|
||||
}).then((data) => {
|
||||
// Check the swagger schema:
|
||||
expect(data.result.healthy, 'healthy should equal true').to.equal(true);
|
||||
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');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
118
test/cypress/integration/api/Settings.spec.js
Normal file
118
test/cypress/integration/api/Settings.spec.js
Normal file
@ -0,0 +1,118 @@
|
||||
/// <reference types="Cypress" />
|
||||
|
||||
const generateRandomString = function (length) {
|
||||
var result = '';
|
||||
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
var charactersLength = characters.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
describe('Settings endpoints', () => {
|
||||
let token;
|
||||
let settingName = 'cypressSetting_' + generateRandomString(12);
|
||||
|
||||
before(() => {
|
||||
cy.getToken().then((tok) => {
|
||||
token = tok;
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to create new settting', function() {
|
||||
cy.task('backendApiPost', {
|
||||
token: token,
|
||||
path: '/api/settings',
|
||||
data: {
|
||||
name: settingName,
|
||||
value: {
|
||||
type: 'custom',
|
||||
html: '<p>not found</p>'
|
||||
}
|
||||
}
|
||||
}).then((data) => {
|
||||
// Check the swagger schema:
|
||||
cy.validateSwaggerSchema('post', 201, '/settings', data);
|
||||
expect(data.result).to.have.property('id');
|
||||
expect(data.result.id).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to get a settting', function() {
|
||||
cy.task('backendApiGet', {
|
||||
token: token,
|
||||
path: '/api/settings/' + settingName
|
||||
}).then((data) => {
|
||||
// Check the swagger schema:
|
||||
cy.validateSwaggerSchema('get', 200, '/settings/{name}', data);
|
||||
expect(data.result).to.have.property('id');
|
||||
expect(data.result).to.have.property('name', settingName);
|
||||
expect(data.result.id).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to update a settting', function() {
|
||||
cy.task('backendApiPut', {
|
||||
token: token,
|
||||
path: '/api/settings/' + settingName,
|
||||
data: {
|
||||
value: true
|
||||
}
|
||||
}).then((data) => {
|
||||
// Check the swagger schema:
|
||||
cy.validateSwaggerSchema('put', 200, '/settings/{name}', data);
|
||||
expect(data.result).to.have.property('id');
|
||||
expect(data.result).to.have.property('name', settingName);
|
||||
expect(data.result.id).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to get all settings', function() {
|
||||
cy.task('backendApiGet', {
|
||||
token: token,
|
||||
path: '/api/settings'
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('get', 200, '/settings', data);
|
||||
expect(data).to.have.property('result');
|
||||
expect(data.result).to.have.property('items');
|
||||
expect(data.result.items.length).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to get all settings with filters A', function() {
|
||||
cy.task('backendApiGet', {
|
||||
token: token,
|
||||
path: '/api/settings?sort=name&name:starts=e&limit=1'
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('get', 200, '/settings', data);
|
||||
expect(data).to.have.property('result');
|
||||
expect(data.result).to.have.property('items');
|
||||
expect(data.result.items.length).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to get all settings with filters B', function() {
|
||||
cy.task('backendApiGet', {
|
||||
token: token,
|
||||
path: '/api/settings?id:in=1,2,3,4,5&limit=1'
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('get', 200, '/settings', data);
|
||||
expect(data).to.have.property('result');
|
||||
expect(data.result).to.have.property('items');
|
||||
expect(data.result.items.length).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to get all settings with filters C', function() {
|
||||
cy.task('backendApiGet', {
|
||||
token: token,
|
||||
path: '/api/settings?name:starts=xxxxxxxxxxxxxxx'
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('get', 200, '/settings', data);
|
||||
expect(data).to.have.property('result');
|
||||
expect(data.result).to.have.property('total', 0);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
25
test/cypress/integration/api/SetupPhase.spec.js
Normal file
25
test/cypress/integration/api/SetupPhase.spec.js
Normal file
@ -0,0 +1,25 @@
|
||||
/// <reference types="Cypress" />
|
||||
|
||||
describe('Setup Phase', () => {
|
||||
|
||||
before(() => {
|
||||
cy.resetUsers();
|
||||
});
|
||||
|
||||
it('Should NOT be able to get a token', function() {
|
||||
cy.task('backendApiPost', {
|
||||
path: '/api/tokens',
|
||||
data: {
|
||||
type: 'password',
|
||||
identity: 'cypress@example.com',
|
||||
secret: 'changeme'
|
||||
},
|
||||
returnOnError: true
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('post', 403, '/tokens', data);
|
||||
expect(data.error).to.have.property('code', 403);
|
||||
expect(data.error).to.have.property('message', 'Not available during setup phase');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
9
test/cypress/integration/api/SwaggerSchema.spec.js
Normal file
9
test/cypress/integration/api/SwaggerSchema.spec.js
Normal file
@ -0,0 +1,9 @@
|
||||
/// <reference types="Cypress" />
|
||||
|
||||
describe('Swagger Schema Checks', () => {
|
||||
it('Should be valid with swagger-validator', function() {
|
||||
cy.task('validateSwaggerFile', {
|
||||
file: Cypress.env('swaggerBase')
|
||||
}).should('equal', null);
|
||||
});
|
||||
});
|
@ -1,7 +1,19 @@
|
||||
/// <reference types="Cypress" />
|
||||
|
||||
const generateRandomString = function (length) {
|
||||
var result = '';
|
||||
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
var charactersLength = characters.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
describe('Users endpoints', () => {
|
||||
let token;
|
||||
let uniqueEmail = 'jc_' + generateRandomString(10) + '@example.com';
|
||||
let myUserID = 0;
|
||||
|
||||
before(() => {
|
||||
cy.getToken().then((tok) => {
|
||||
@ -15,8 +27,10 @@ describe('Users endpoints', () => {
|
||||
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);
|
||||
expect(data).to.have.property('result');
|
||||
expect(data.result).to.have.property('id');
|
||||
expect(data.result.id).to.be.greaterThan(0);
|
||||
myUserID = data.result.id;
|
||||
});
|
||||
});
|
||||
|
||||
@ -26,7 +40,95 @@ describe('Users endpoints', () => {
|
||||
path: '/api/users'
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('get', 200, '/users', data);
|
||||
expect(data.length).to.be.greaterThan(0);
|
||||
expect(data).to.have.property('result');
|
||||
expect(data.result).to.have.property('items');
|
||||
expect(data.result.items.length).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to get all users with filters A', function() {
|
||||
cy.task('backendApiGet', {
|
||||
token: token,
|
||||
path: '/api/users?sort=id.desc&name:starts=c&name:ends=e'
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('get', 200, '/users', data);
|
||||
expect(data).to.have.property('result');
|
||||
expect(data.result).to.have.property('items');
|
||||
expect(data.result.items.length).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to get all users with filters B', function() {
|
||||
cy.task('backendApiGet', {
|
||||
token: token,
|
||||
path: '/api/users?sort=id&id:in=1,2,3,4,5'
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('get', 200, '/users', data);
|
||||
expect(data).to.have.property('result');
|
||||
expect(data.result).to.have.property('items');
|
||||
expect(data.result.items.length).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to get all users with filters C', function() {
|
||||
cy.task('backendApiGet', {
|
||||
token: token,
|
||||
path: '/api/users?sort=id&name:ends=xxxxxxxxxxxxx'
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('get', 200, '/users', data);
|
||||
expect(data).to.have.property('result');
|
||||
expect(data.result).to.have.property('total', 0);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should be able to create someone else', function() {
|
||||
cy.task('backendApiPost', {
|
||||
token: token,
|
||||
path: '/api/users',
|
||||
data: {
|
||||
name: 'Example user 1',
|
||||
nickname: 'User1',
|
||||
email: uniqueEmail,
|
||||
is_disabled: false,
|
||||
auth: {
|
||||
type: 'password',
|
||||
secret: 'changeme'
|
||||
},
|
||||
capabilities: [
|
||||
'hosts.manage'
|
||||
]
|
||||
}
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('post', 201, '/users', data);
|
||||
expect(data).to.have.property('result');
|
||||
expect(data.result).to.have.property('id');
|
||||
expect(data.result.id).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should not be able to create duplicate email', function() {
|
||||
cy.task('backendApiPost', {
|
||||
token: token,
|
||||
path: '/api/users',
|
||||
returnOnError: true,
|
||||
data: {
|
||||
name: 'Example user 2',
|
||||
nickname: 'User2',
|
||||
email: uniqueEmail,
|
||||
is_disabled: false,
|
||||
auth: {
|
||||
type: 'password',
|
||||
secret: 'changeme'
|
||||
},
|
||||
capabilities: [
|
||||
'hosts.manage'
|
||||
]
|
||||
}
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('post', 400, '/users', data);
|
||||
expect(data).to.have.property('result', null);
|
||||
expect(data).to.have.property('error');
|
||||
expect(data.error).to.have.property('code', 400);
|
||||
});
|
||||
});
|
||||
|
||||
@ -39,9 +141,55 @@ describe('Users endpoints', () => {
|
||||
}
|
||||
}).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');
|
||||
expect(data).to.have.property('result');
|
||||
expect(data.result).to.have.property('id');
|
||||
expect(data.result.id).to.be.greaterThan(0);
|
||||
expect(data.result.name).to.be.equal('changed name');
|
||||
});
|
||||
});
|
||||
|
||||
it('Should not be able to update email to another user', function() {
|
||||
cy.task('backendApiPut', {
|
||||
token: token,
|
||||
path: '/api/users/me',
|
||||
returnOnError: true,
|
||||
data: {
|
||||
email: uniqueEmail
|
||||
}
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('put', 400, '/users/{userID}', data);
|
||||
expect(data).to.have.property('result', null);
|
||||
expect(data).to.have.property('error');
|
||||
expect(data.error).to.have.property('code', 400);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should not be able to disable yourself', function() {
|
||||
cy.task('backendApiPut', {
|
||||
token: token,
|
||||
path: '/api/users/me',
|
||||
returnOnError: true,
|
||||
data: {
|
||||
is_disabled: true
|
||||
}
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('put', 400, '/users/{userID}', data);
|
||||
expect(data).to.have.property('result', null);
|
||||
expect(data).to.have.property('error');
|
||||
expect(data.error).to.have.property('code', 400);
|
||||
});
|
||||
});
|
||||
|
||||
it('Should not be able to delete yourself', function() {
|
||||
cy.task('backendApiDelete', {
|
||||
token: token,
|
||||
path: '/api/users/' + myUserID,
|
||||
returnOnError: true
|
||||
}).then((data) => {
|
||||
cy.validateSwaggerSchema('delete', 400, '/users/{userID}', data);
|
||||
expect(data).to.have.property('result', null);
|
||||
expect(data).to.have.property('error');
|
||||
expect(data.error).to.have.property('code', 400);
|
||||
});
|
||||
});
|
||||
|
||||
|
38
test/cypress/integration/ui/SetupLogin.spec.js
Normal file
38
test/cypress/integration/ui/SetupLogin.spec.js
Normal file
@ -0,0 +1,38 @@
|
||||
/// <reference types="Cypress" />
|
||||
|
||||
describe('UI Setup and Login', () => {
|
||||
|
||||
// Clear the users before runing this test
|
||||
before(() => {
|
||||
cy.resetUsers();
|
||||
});
|
||||
|
||||
it('Should be able to setup a new user', function() {
|
||||
cy.visit('/');
|
||||
cy.get('input[name="name"]').type('Cypress McGee');
|
||||
cy.get('input[name="nickname"]').type('Cypress');
|
||||
cy.get('input[name="email"]').type('cypress@example.com');
|
||||
cy.get('input[name="password"]').type('changeme');
|
||||
cy.get('form button:last').click();
|
||||
|
||||
// To fix after chakra change:
|
||||
// cy.get('.navbar-nav .avatar').should('be.visible');
|
||||
|
||||
// logout:
|
||||
cy.clearLocalStorage();
|
||||
});
|
||||
|
||||
it('Should be able to login', function() {
|
||||
cy.visit('/');
|
||||
cy.get('input[name="email"]').type('cypress@example.com');
|
||||
cy.get('input[name="password"]').type('changeme');
|
||||
cy.get('form button:last').click();
|
||||
|
||||
// To fix after chakra change:
|
||||
// cy.get('.navbar-nav .avatar').should('be.visible');
|
||||
|
||||
// logout:
|
||||
cy.clearLocalStorage();
|
||||
});
|
||||
|
||||
});
|
@ -19,22 +19,17 @@ BackendApi.prototype.setToken = function(token) {
|
||||
* @returns {Promise<object>}
|
||||
*/
|
||||
BackendApi.prototype.get = function(path, returnOnError) {
|
||||
logger('GET Request:', this.config.baseUrl + path);
|
||||
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,
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: 'Bearer ' + this.token,
|
||||
},
|
||||
})
|
||||
.on('complete', function(data, response) {
|
||||
logger('Response data:', data);
|
||||
logger('Response data:', JSON.stringify(data, null, 2));
|
||||
if (!returnOnError && data instanceof Error) {
|
||||
reject(data);
|
||||
} else if (!returnOnError && response.statusCode != 200) {
|
||||
@ -56,22 +51,17 @@ BackendApi.prototype.get = function(path, returnOnError) {
|
||||
* @returns {Promise<object>}
|
||||
*/
|
||||
BackendApi.prototype.delete = function(path, returnOnError) {
|
||||
logger('DELETE Request:', this.config.baseUrl + path);
|
||||
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,
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: 'Bearer ' + this.token,
|
||||
},
|
||||
})
|
||||
.on('complete', function(data, response) {
|
||||
logger('Response data:', data);
|
||||
logger('Response data:', JSON.stringify(data, null, 2));
|
||||
if (!returnOnError && data instanceof Error) {
|
||||
reject(data);
|
||||
} else if (!returnOnError && response.statusCode != 200) {
|
||||
@ -94,7 +84,7 @@ BackendApi.prototype.delete = function(path, returnOnError) {
|
||||
* @returns {Promise<object>}
|
||||
*/
|
||||
BackendApi.prototype.postJson = function(path, data, returnOnError) {
|
||||
logger('POST ', this.config.baseUrl + path);
|
||||
logger('POST Request:', this.config.baseUrl + path, JSON.stringify(data, null, 2));
|
||||
return this._putPostJson('postJson', path, data, returnOnError);
|
||||
};
|
||||
|
||||
@ -105,7 +95,7 @@ BackendApi.prototype.postJson = function(path, data, returnOnError) {
|
||||
* @returns {Promise<object>}
|
||||
*/
|
||||
BackendApi.prototype.putJson = function(path, data, returnOnError) {
|
||||
logger('PUT ', this.config.baseUrl + path);
|
||||
logger('PUT Request:', this.config.baseUrl + path, JSON.stringify(data, null, 2));
|
||||
return this._putPostJson('putJson', path, data, returnOnError);
|
||||
};
|
||||
|
||||
@ -123,7 +113,7 @@ BackendApi.prototype._putPostJson = function(fn, path, data, returnOnError) {
|
||||
Authorization: 'Bearer ' + this.token,
|
||||
},
|
||||
}).on('complete', function(data, response) {
|
||||
logger('Response data:', data);
|
||||
logger('Response data:', JSON.stringify(data, null, 2));
|
||||
if (!returnOnError && data instanceof Error) {
|
||||
reject(data);
|
||||
} else if (!returnOnError && response.statusCode != 200) {
|
||||
|
@ -9,8 +9,8 @@ module.exports = function (config) {
|
||||
|
||||
/**
|
||||
* @param {object} options
|
||||
* @param {string} options.token JWT
|
||||
* @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}
|
||||
*/
|
||||
|
@ -1,7 +1,7 @@
|
||||
const {SwaggerValidation} = require('@jc21/cypress-swagger-validation');
|
||||
|
||||
module.exports = (on, config) => {
|
||||
// Replace swaggerBase config var wildcard
|
||||
// Replace swaggerFile config var wildcard
|
||||
if (typeof config.env.swaggerBase !== 'undefined') {
|
||||
config.env.swaggerBase = config.env.swaggerBase.replace('{{baseUrl}}', config.baseUrl);
|
||||
}
|
||||
|
@ -9,34 +9,123 @@
|
||||
// ***********************************************
|
||||
//
|
||||
|
||||
import 'cypress-wait-until';
|
||||
|
||||
/**
|
||||
* 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 {integer} code Swagger doc endpoint response code, exactly as defined 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) => {
|
||||
Cypress.Commands.add('validateSwaggerSchema', (method, code, path, data) => {
|
||||
cy.task('validateSwaggerSchema', {
|
||||
file: Cypress.env('swaggerBase'),
|
||||
endpoint: path,
|
||||
method: method,
|
||||
statusCode: statusCode,
|
||||
statusCode: code,
|
||||
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'
|
||||
/**
|
||||
* @param {object} defaultUser
|
||||
* @param {object} defaultAuth
|
||||
*/
|
||||
Cypress.Commands.add('getToken', (defaultUser, defaultAuth) => {
|
||||
if (typeof defaultAuth === 'object' && defaultAuth) {
|
||||
if (!defaultUser) {
|
||||
defaultUser = {};
|
||||
}
|
||||
defaultUser.auth = defaultAuth;
|
||||
}
|
||||
|
||||
cy.task('backendApiGet', {
|
||||
path: '/api/',
|
||||
}).then((data) => {
|
||||
// Check the swagger schema:
|
||||
cy.validateSwaggerSchema('get', 200, '/', data);
|
||||
|
||||
if (!data.result.setup) {
|
||||
cy.log('Setup = false');
|
||||
// create a new user
|
||||
cy.createInitialUser(defaultUser).then(() => {
|
||||
return cy.getToken(defaultUser);
|
||||
});
|
||||
} else {
|
||||
let auth = {
|
||||
type: 'password',
|
||||
identity: 'cypress@example.com',
|
||||
secret: 'changeme',
|
||||
};
|
||||
|
||||
if (typeof defaultUser === 'object' && defaultUser && typeof defaultUser.auth === 'object' && defaultUser.auth) {
|
||||
auth = Object.assign({}, auth, defaultUser.auth);
|
||||
}
|
||||
|
||||
cy.log('Setup = true');
|
||||
// login with existing user
|
||||
cy.task('backendApiPost', {
|
||||
path: '/api/tokens',
|
||||
data: auth,
|
||||
}).then((res) => {
|
||||
cy.wrap(res.result.token);
|
||||
});
|
||||
}
|
||||
}).then(res => {
|
||||
cy.wrap(res.token);
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('createInitialUser', (defaultUser) => {
|
||||
let user = {
|
||||
name: 'Cypress McGee',
|
||||
nickname: 'Cypress',
|
||||
email: 'cypress@example.com',
|
||||
is_disabled: false,
|
||||
auth: {
|
||||
type: 'password',
|
||||
secret: 'changeme'
|
||||
},
|
||||
capabilities: ['full-admin']
|
||||
};
|
||||
|
||||
if (typeof defaultUser === 'object' && defaultUser) {
|
||||
user = Object.assign({}, user, defaultUser);
|
||||
}
|
||||
|
||||
return cy.task('backendApiPost', {
|
||||
path: '/api/users',
|
||||
data: user,
|
||||
}).then((data) => {
|
||||
// Check the swagger schema:
|
||||
cy.validateSwaggerSchema('post', 201, '/users', data);
|
||||
expect(data.result).to.have.property('id');
|
||||
expect(data.result.id).to.be.greaterThan(0);
|
||||
cy.wrap(data.result);
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('resetUsers', () => {
|
||||
cy.task('backendApiDelete', {
|
||||
path: '/api/users'
|
||||
}).then((data) => {
|
||||
expect(data).to.have.property('result', true);
|
||||
cy.wrap(data.result);
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('waitForCertificateStatus', (token, certID, expected, timeout = 60) => {
|
||||
cy.log(`Waiting for certificate (${certID}) status (${expected}) timeout (${timeout})`);
|
||||
|
||||
cy.waitUntil(() => cy.task('backendApiGet', {
|
||||
token: token,
|
||||
path: `/api/certificates/${certID}`
|
||||
}).then((data) => {
|
||||
return data.result.status === expected;
|
||||
}), {
|
||||
errorMsg: 'Waiting for certificate status failed',
|
||||
timeout: timeout * 1000,
|
||||
interval: 5000
|
||||
});
|
||||
});
|
||||
|
@ -1,5 +1,3 @@
|
||||
require('cypress-plugin-retries');
|
||||
|
||||
import './commands';
|
||||
|
||||
Cypress.on('uncaught:exception', (/*err, runnable*/) => {
|
||||
|
@ -4,18 +4,18 @@
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"@jc21/cypress-swagger-validation": "^0.0.9",
|
||||
"@jc21/cypress-swagger-validation": "^0.1.0",
|
||||
"@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",
|
||||
"chalk": "^4.1.1",
|
||||
"cypress": "^9.4.1",
|
||||
"cypress-multi-reporters": "^1.5.0",
|
||||
"cypress-wait-until": "^1.7.2",
|
||||
"eslint": "^7.28.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",
|
||||
"eslint-plugin-chai-friendly": "^0.7.1",
|
||||
"eslint-plugin-cypress": "^2.11.3",
|
||||
"lodash": "^4.17.21",
|
||||
"mocha": "^9.0.0",
|
||||
"mocha-junit-reporter": "^2.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
|
2091
test/yarn.lock
2091
test/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user