diff --git a/cypress/fixtures/01_setup/default-settings.yaml b/cypress/fixtures/01_setup/default-settings.yaml new file mode 100644 index 0000000..1957802 --- /dev/null +++ b/cypress/fixtures/01_setup/default-settings.yaml @@ -0,0 +1,3 @@ +setup: true +language: en +welcome: true diff --git a/cypress/integration/01_setup/01-system-setup-signup.spec.js b/cypress/integration/01_setup/01-system-setup-signup.spec.js new file mode 100644 index 0000000..3dbb6c5 --- /dev/null +++ b/cypress/integration/01_setup/01-system-setup-signup.spec.js @@ -0,0 +1,162 @@ +describe("Typemill Setup with Signup", function() { + it("validates form input", function() { + // reset users and settings + cy.task("resetSetup"); + // visit setup form + cy.visit("/setup"); + // cy.visit('/setup',{ onBeforeLoad: (_contentWindow) => { Object.defineProperty(navigator, 'language', { value: 'fr-FR' }) } }) + cy.url().should("include", "/setup"); + + // add data and check attributes + cy.get('input[name="username"]') + .type("?1") + .should("have.value", "?1") + .and("have.attr", "required"); + + cy.get('input[name="email"]') + .type("trendschau.net") + .should("have.value", "trendschau.net") + .and("have.attr", "required"); + + cy.get('input[name="password"]') + .type("pass") + .should("have.value", "pass") + .and("have.attr", "required"); + + // submit and get validation errors + cy.get("form").submit(); + cy.get("#flash-message").should( + "contain", + "Please check your input and try again" + ); + cy.get(".error").should("contain", "invalid characters"); + cy.get(".error").should("contain", "e-mail is invalid"); + cy.get(".error").should("contain", "Length between 5 - 20"); + }); + + /* + it('fails without CSRF-token', function () + { + cy.request({ + method: 'POST', + url: '/setup', // baseUrl is prepended to url + form: true, // indicates the body should be form urlencoded and sets Content-Type: application/x-www-form-urlencoded headers + failOnStatusCode: false, + body: { + username: 'trendschau', + email: 'trendschau@gmail.com', + password: 'password' + } + }) + .its('body') + .should('include', 'The form has a timeout') + }) +*/ + it("fails without CSRF-token", function() { + cy.visit("/setup"); + + // enter correct data + cy.get('input[name="username"]').clear().type("trendschau"); + cy.get('input[name="email"]').clear().type("trendschau@gmail.com"); + cy.get('input[name="password"]').clear().type("password"); + cy.get("#csrf_value").then((elem) => { + elem.val("wrongvalue"); + }); + + // submit and get validation errors + cy.get("form").submit(); + cy.get("#flash-message").should("contain", "form has a timeout"); + }); + + it("submits valid form data and visit welcome and settings page", function() { + cy.visit("/setup"); + + // enter correct data + cy.get('input[name="username"]').clear().type("trendschau"); + cy.get('input[name="email"]').clear().type("trendschau@gmail.com"); + cy.get('input[name="password"]').clear().type("password"); + + // submits valid form + cy.get("form").submit(); + cy.url().should("include", "/welcome"); + cy.getCookie("typemill-session").should("exist"); + Cypress.Cookies.preserveOnce("typemill-session"); + + // clicks link on welcome page to settings page + // cy.get('.button').should('contain', 'Configure your website') + cy.get(".button").click(); + cy.url().should("include", "/tm/settings"); + }); + + it("creates default settings data", function() { + cy.get('input[name="settings[title]"]') + .should("have.value", "TYPEMILL") + .and("have.attr", "required"); + cy.get('input[name="settings[author]"]'); + cy.get('select[name="settings[copyright]"]'); + cy.get('input[name="settings[year]"]').should("have.attr", "required"); + cy.get('select[name="settings[language]"]'); + // cy.get('select[name="settings[langattr]"]') + cy.get('input[name="settings[sitemap]"]') + .should("have.value", `${Cypress.config().baseUrl}/cache/sitemap.xml`) + .and("have.attr", "readonly"); + cy.get('input[name="settings[logo]"]'); + cy.get('input[name="settings[deletelogo]"]'); + cy.get('input[name="settings[favicon]"]'); + cy.get('input[name="settings[deletefav]"]'); + cy.get('input[name="settings[headlineanchors]"]'); + cy.get('input[name="settings[editor]"]'); + + cy.get('select[name="settings[language]"]') + .select("en") + .should("have.value", "en"); + + cy.get("form").submit(); + cy.get("#flash-message").should("contain", "Settings are stored"); + + Cypress.Cookies.preserveOnce("typemill-session"); + }); + + it("creates default user data", function() { + cy.visit("/tm/user/trendschau"); + cy.url().should("include", "/tm/user/trendschau"); + cy.get('input[name="user[username]"]').should("have.value", "trendschau"); + cy.get('input[name="user[firstname]"]') + .clear() + .type("Sebastian") + .should("have.value", "Sebastian"); + cy.get('input[name="user[lastname]"]') + .clear() + .type("Schürmanns") + .should("have.value", "Schürmanns"); + cy.get('input[name="user[email]"]').should( + "have.value", + "trendschau@gmail.com" + ); + cy.get('select[name="user[userrole]"]').should( + "have.value", + "administrator" + ); + cy.get('input[name="user[password]"]').should("have.value", ""); + cy.get('input[name="user[newpassword]"]').should("have.value", ""); + + cy.get("#userform").submit(); + cy.get("#flash-message").should("contain", "Saved all changes"); + }); + + it("logouts out", function() { + // visits logout link + cy.visit("/tm/logout"); + cy.url().should("include", "/tm/login"); + + // tries to open setup form again and gets redirected to login + cy.visit("/setup"); + cy.url().should("include", "/login"); + }); + + it("redirects when tries to setup again", function() { + // tries to open setup form again and gets redirected to login + cy.visit("/setup"); + cy.url().should("include", "/login"); + }); +}); \ No newline at end of file diff --git a/cypress/integration/01_setup/02-initial-frontend.spec.js b/cypress/integration/01_setup/02-initial-frontend.spec.js new file mode 100644 index 0000000..d9b64bf --- /dev/null +++ b/cypress/integration/01_setup/02-initial-frontend.spec.js @@ -0,0 +1,152 @@ +describe("Typemill Initial Frontend", function() { + it("has startpage with navigation", function() { + /* visit homepage */ + cy.visit("/"); + + /* has startpage with headline */ + cy.get("h1").contains("Typemill"); + + /* has start and setup button */ + cy.get("nav") + .find("a") + .should(($a) => { + expect($a).to.have.length(11); + expect($a[0].href).to.match(/welcome/); + expect($a[1].href).to.match(/welcome\/setup-your-website/); + expect($a[2].href).to.match(/welcome\/manage-access/); + expect($a[3].href).to.match(/welcome\/write-content/); + expect($a[4].href).to.match(/welcome\/get-help/); + expect($a[5].href).to.match(/welcome\/markdown-test/); + expect($a[6].href).to.match(/cyanine-theme/); + expect($a[7].href).to.match(/cyanine-theme\/landingpage/); + expect($a[8].href).to.match(/cyanine-theme\/colors-and-fonts/); + expect($a[9].href).to.match(/cyanine-theme\/footer/); + expect($a[10].href).to.match(/cyanine-theme\/content-elements/); + }); + }); + + it("has error page", function() { + cy.request({ + url: "/error", + failOnStatusCode: false, + }).then((resp) => { + /* should return 404 not found */ + expect(resp.status).to.eq(404); + }); + + cy.visit("/error", { failOnStatusCode: false }); + cy.url().should("include", "/error"); + + cy.get("h1").contains("Not Found"); + }); + + it("has no access to cache files", function() { + cy.request({ + url: "/cache/structure.txt", + failOnStatusCode: false, + }).then((resp) => { + // redirect status code is 302 + expect(resp.status).to.eq(403); + }); + }); + + it("has no access to dashboard", function() { + cy.visit("/tm/settings"); + cy.url().should("include", "/tm/login"); + }); + + it("has proper markdown test page", function() { + cy.visit("/welcome/markdown-test"); + cy.url().should("include", "/welcome/markdown-test"); + + /* has navigation element */ + cy.get("nav").should("exist"); + + /* check if toc exists */ + cy.get(".TOC").within(($toc) => { + /* check if a certain link in toc exists */ + cy.get("a").eq(2).should("have.attr", "href", "#h-headlines"); + }); + + /* check if corresponding anchor exists */ + cy.get("#h-headlines").should("exist"); + + /* soft linebreaks */ + cy.get("br").should("exist"); + + /* emphasis */ + cy.get("em").should("exist"); + + /* strong */ + cy.get("strong").should("exist"); + + /* ordered list */ + cy.get("ol").should("exist"); + + /* linebreak */ + cy.get("hr").should("exist"); + + /* links exists? hard to test, any idea? We need to wrap it in a div... */ + + /* images */ + cy.get("img").eq(0).should("have.attr", "alt", "alt"); + cy.get("img") + .eq(0) + .should("have.attr", "src") + .should("include", "media/files/markdown.png"); + cy.get("figure") + .eq(2) + .should("have.id", "myid") + .and("have.class", "otherclass"); + cy.get("img") + .eq(2) + .should("have.attr", "alt", "alt-text") + .and("have.attr", "title", "my title") + .and("have.attr", "width", "150px"); + + /* blockquote */ + cy.get("blockquote").should("exist"); + + /* has navigation element */ + cy.get(".notice1").should("exist"); + cy.get(".notice2").should("exist"); + cy.get(".notice3").should("exist"); + + /* footnote */ + cy.get("sup").eq(0).should("have.id", "fnref1:1"); + cy.get("sup") + .eq(0) + .within(($sup) => { + cy.get("a") + .eq(0) + .should("have.attr", "href", "#fn%3A1") + .and("have.class", "footnote-ref"); + }); + + /* abbreviation */ + cy.get("abbr").should("exist"); + + /* definition list */ + cy.get("dl").should("exist"); + + /* table */ + cy.get("table").should("exist"); + + /* code */ + cy.get("pre").should("exist"); + cy.get("code").should("exist"); + + /* math */ + cy.get(".math").should("exist"); + + /* footnote end */ + cy.get(".footnotes").within(($footnotes) => { + cy.get("li").eq(0).should("have.id", "fn:1"); + cy.get("a") + .eq(0) + .should("have.class", "footnote-backref") + .and("have.attr", "href", "#fnref1%3A1") + .and("have.attr", "rev", "footnote"); + }); + }); +}); \ No newline at end of file diff --git a/cypress/integration/03-system-settings.spec.js b/cypress/integration/03-system-settings.spec.js new file mode 100644 index 0000000..ba6ee61 --- /dev/null +++ b/cypress/integration/03-system-settings.spec.js @@ -0,0 +1,101 @@ +describe("Typemill System Settings", function() { + before(function() { + cy.visit("/tm/login"); + cy.url().should("include", "/tm/login"); + + cy.get('input[name="username"]').type("trendschau"); + cy.get('input[name="password"]').type("password"); + + cy.get("form").submit(); + cy.url().should("include", "/tm/content"); + cy.getCookie("typemill-session").should("exist"); + + cy.visit("/tm/settings"); + cy.url().should("include", "/tm/settings"); + }); + + beforeEach(function() { + Cypress.Cookies.preserveOnce("typemill-session"); + }); + + it("validates the form", function() { + // fill out valid data + cy.get('input[name="settings[title]"]') + .clear() + .type("Cypress a').eq(0).click() - - /* Check dublicates cannot be made */ - - /* Check new page can be created */ - cy.get('.addNaviForm').within(($naviform) =>{ - - /* add Testpage into input */ - cy.get('input') - .clear() - .type('Testpage') - .should('have.value', 'Testpage') - - cy.get('.b-left').click() - }) - - /* get Navilist */ - cy.get('.navi-list') - .should('contain', 'Testpage') - .eq(2).find('a').should(($a) => { - expect($a).to.have.length(6) - expect($a[5].href).to.include('/welcome\/testpage') - }) - }) - - it('edits default content', function() - { - cy.visit('/tm/content/visual/welcome/testpage') - cy.url().should('include','/tm\/content\/visual\/welcome\/testpage') - - cy.get('#blox').within(($blox) => { - - /* Change Title */ - cy.get('#blox-0').click() - cy.get("input") - .clear() - .type("This is my Testpage") - - cy.get(".edit").click() - cy.get('#blox-0').should("contain", "This is my Testpage") - - /* Change Text */ - cy.get('#blox-1').click() - cy.get("textarea") - .clear() - .type("This is the new paragraph for the first line with some text.") - - cy.get(".edit").click() - cy.get('#blox-1').should("contain", "new paragraph") - - }) - }) - - it('edits paragraph', function() - { - cy.get('#blox').within(($blox) => { - /* Get Format Bar */ - cy.get('.format-bar').within(($formats) => { - - /* Edit Table */ - cy.get("button").eq(0).click() - cy.get("textarea") - .type("This is a second paragraph.") - - /* save table */ - cy.get(".edit").click() - cy.get(".cancel").click() - - }) - - cy.get('#blox-2').should("contain", "second paragraph") - }) - }) - - it('edits headline', function() - { - cy.get('#blox').within(($blox) => { - /* Get Format Bar */ - cy.get('.format-bar').within(($formats) => { - - /* Edit Table */ - cy.get("button").eq(1).click() - cy.get("input") - .type("Second Level Headline") - - /* save block */ - cy.get(".edit").click() - - /* close new standard textarea */ - cy.get(".cancel").click() - - }) - - cy.get('#blox-3').should("contain", "Second Level Headline") - }) - }) - - it('edits unordered list', function() - { - cy.get('#blox').within(($blox) => { - /* Get Format Bar */ - cy.get('.format-bar').within(($formats) => { - - /* Edit Table */ - cy.get("button").eq(2).click() - cy.get("textarea") - .type("first list item{enter}second list item") - - /* save block */ - cy.get(".edit").click() - - /* close new standard textarea */ - cy.get(".cancel").click() - - }) - - cy.get('#blox-4').within(($block) => { - cy.get("li").should(($lis) => { - expect($lis).to.have.length(2) - expect($lis.eq(0)).to.contain('first list item') - }) - }) - }) - }) - - it('edits ordered list', function() - { - cy.get('#blox').within(($blox) => { - /* Get Format Bar */ - cy.get('.format-bar').within(($formats) => { - - /* Edit Table */ - cy.get("button").eq(3).click() - cy.get("textarea") - .type("first ordered item{enter}second ordered item") - - /* save block */ - cy.get(".edit").click() - - /* close new standard textarea */ - cy.get(".cancel").click() - - }) - - cy.get('#blox-5').within(($block) => { - cy.get("li").should(($lis) => { - expect($lis).to.have.length(2) - expect($lis.eq(0)).to.contain('first ordered item') - }) - }) - }) - }) - - it('edits table', function() - { - cy.get('#blox').within(($blox) => { - /* Get Format Bar */ - cy.get('.format-bar').within(($formats) => { - - /* Edit Table */ - cy.get("button").eq(4).click() - cy.get("table").within(($table) => { - - /* edit table head */ - cy.get("tr").eq(1).within(($row) => { - cy.get("th").eq(1).click() - .clear() - .type("first Headline") - cy.get("th").eq(2).click() - .clear() - .type("Second Headline") - }) - - /* edit first content row */ - cy.get("tr").eq(2).within(($row) => { - cy.get("td").eq(1).click() - .clear() - .type("Some") - cy.get("td").eq(2).click() - .clear() - .type("More") - }) - - /* edit second content row */ - cy.get("tr").eq(3).within(($row) => { - cy.get("td").eq(1).click() - .clear() - .type("Beautiful") - cy.get("td").eq(2).click() - .clear() - .type("Content") - }) - - /* add new column on the right */ - cy.get("tr").eq(0).within(($row) => { - cy.get("td").eq(2).click() - cy.get(".actionline").eq(0).click() - }) - }) - - cy.get("table").within(($table) => { - - /* edit second new column head */ - cy.get("tr").eq(1).within(($row) => { - cy.get("th").eq(3).click() - .clear() - .type("New Head") - }) - - /* edit second new column head */ - cy.get("tr").eq(2).within(($row) => { - cy.get("td").eq(3).click() - .clear() - .type("With") - }) - - /* edit second new column head */ - cy.get("tr").eq(3).within(($row) => { - cy.get("td").eq(3).click() - .clear() - .type("new Content") - }) - }) - - /* save table */ - cy.get(".edit").click() - - }) - - cy.get('#blox-6').should("contain", "Beautiful").click() - - cy.get('.editactive').within(($activeblock) => { - cy.get('.component').should("contain", "Beautiful") - }) - - }) - }) - - it('Publishes new page', function() - { - cy.visit('/tm/content/visual/welcome/testpage') - cy.url().should('include','/tm\/content\/visual\/welcome\/testpage') - - cy.get('#publish').click().wait(500) - - cy.visit('/welcome/testpage') - cy.url().should('include','/welcome/testpage') - - cy.get('.cy-nav') - .should('contain', 'Testpage') - }) - - it('has sitemap xml', function () - { - cy.request({ - url: '/cache/sitemap.xml', - }) - .then((resp) => { - /* should return xml-format */ - expect(resp.headers).to.have.property('content-type','application/xml') - }) - }) - - it('Deletes new page', function() - { - cy.visit('/tm/content/visual/welcome/testpage') - cy.url().should('include','/tm\/content\/visual\/welcome\/testpage') - - cy.get('.danger').click() - - cy.get('#modalWindow').within(($modal) => { - cy.get('button').click() - }) - - cy.visit('/tm/content/visual/welcome') - cy.get('.navi-list') - .not('contain', 'Testpage') - .eq(2).find('a').should(($a) => { - expect($a).to.have.length(5) - }) - }) +describe('Blox Editor', function() +{ + before(function () + { + cy.visit('/tm/login') + cy.url().should('include','/tm/login') + + cy.get('input[name="username"]').type('trendschau') + cy.get('input[name="password"]').type('password') + + cy.get('form').submit() + cy.url().should('include','/tm/content') + cy.getCookie('typemill-session').should('exist') + + cy.visit('/tm/content/visual') + cy.url().should('include','/tm\/content\/visual') + }) + + beforeEach(function () + { + Cypress.Cookies.preserveOnce('typemill-session') + }) + + it('creates new page', function() + { + // click on add element + cy.get('.addNaviItem > a').eq(0).click() + + /* Check dublicates cannot be made */ + + /* Check new page can be created */ + cy.get('.addNaviForm').within(($naviform) =>{ + + /* add Testpage into input */ + cy.get('input') + .clear() + .type('Testpage') + .should('have.value', 'Testpage') + + cy.get('.b-left').click() + }) + + /* get Navilist */ + cy.get('.navi-list') + .should('contain', 'Testpage') + .eq(2).find('a').should(($a) => { + expect($a).to.have.length(6) + expect($a[5].href).to.include('/welcome\/testpage') + }) + }) + + it('edits default content', function() + { + cy.visit('/tm/content/visual/welcome/testpage') + cy.url().should('include','/tm\/content\/visual\/welcome\/testpage') + + cy.get('#blox').within(($blox) => { + + /* Change Title */ + cy.get('#blox-0').click() + cy.get("input") + .clear() + .type("This is my Testpage") + + cy.get(".edit").click() + cy.get('#blox-0').should("contain", "This is my Testpage") + + /* Change Text */ + cy.get('#blox-1').click() + cy.get("textarea") + .clear() + .type("This is the new paragraph for the first line with some text.") + + cy.get(".edit").click() + cy.get('#blox-1').should("contain", "new paragraph") + + }) + }) + + it('edits paragraph', function() + { + cy.get('#blox').within(($blox) => { + /* Get Format Bar */ + cy.get('.format-bar').within(($formats) => { + + /* Edit Table */ + cy.get("button").eq(0).click() + cy.get("textarea") + .type("This is a second paragraph.") + + /* save table */ + cy.get(".edit").click() + cy.get(".cancel").click() + + }) + + cy.get('#blox-2').should("contain", "second paragraph") + }) + }) + + it('edits headline', function() + { + cy.get('#blox').within(($blox) => { + /* Get Format Bar */ + cy.get('.format-bar').within(($formats) => { + + /* Edit Table */ + cy.get("button").eq(1).click() + cy.get("input") + .type("Second Level Headline") + + /* save block */ + cy.get(".edit").click() + + /* close new standard textarea */ + cy.get(".cancel").click() + + }) + + cy.get('#blox-3').should("contain", "Second Level Headline") + }) + }) + + it('edits unordered list', function() + { + cy.get('#blox').within(($blox) => { + /* Get Format Bar */ + cy.get('.format-bar').within(($formats) => { + + /* Edit Table */ + cy.get("button").eq(2).click() + cy.get("textarea") + .type("first list item{enter}second list item") + + /* save block */ + cy.get(".edit").click() + + /* close new standard textarea */ + cy.get(".cancel").click() + + }) + + cy.get('#blox-4').within(($block) => { + cy.get("li").should(($lis) => { + expect($lis).to.have.length(2) + expect($lis.eq(0)).to.contain('first list item') + }) + }) + }) + }) + + it('edits ordered list', function() + { + cy.get('#blox').within(($blox) => { + /* Get Format Bar */ + cy.get('.format-bar').within(($formats) => { + + /* Edit Table */ + cy.get("button").eq(3).click() + cy.get("textarea") + .type("first ordered item{enter}second ordered item") + + /* save block */ + cy.get(".edit").click() + + /* close new standard textarea */ + cy.get(".cancel").click() + + }) + + cy.get('#blox-5').within(($block) => { + cy.get("li").should(($lis) => { + expect($lis).to.have.length(2) + expect($lis.eq(0)).to.contain('first ordered item') + }) + }) + }) + }) + + it('edits table', function() + { + cy.get('#blox').within(($blox) => { + /* Get Format Bar */ + cy.get('.format-bar').within(($formats) => { + + /* Edit Table */ + cy.get("button").eq(4).click() + cy.get("table").within(($table) => { + + /* edit table head */ + cy.get("tr").eq(1).within(($row) => { + cy.get("th").eq(1).click() + .clear() + .type("first Headline") + cy.get("th").eq(2).click() + .clear() + .type("Second Headline") + }) + + /* edit first content row */ + cy.get("tr").eq(2).within(($row) => { + cy.get("td").eq(1).click() + .clear() + .type("Some") + cy.get("td").eq(2).click() + .clear() + .type("More") + }) + + /* edit second content row */ + cy.get("tr").eq(3).within(($row) => { + cy.get("td").eq(1).click() + .clear() + .type("Beautiful") + cy.get("td").eq(2).click() + .clear() + .type("Content") + }) + + /* add new column on the right */ + cy.get("tr").eq(0).within(($row) => { + cy.get("td").eq(2).click() + cy.get(".actionline").eq(0).click() + }) + }) + + cy.get("table").within(($table) => { + + /* edit second new column head */ + cy.get("tr").eq(1).within(($row) => { + cy.get("th").eq(3).click() + .clear() + .type("New Head") + }) + + /* edit second new column head */ + cy.get("tr").eq(2).within(($row) => { + cy.get("td").eq(3).click() + .clear() + .type("With") + }) + + /* edit second new column head */ + cy.get("tr").eq(3).within(($row) => { + cy.get("td").eq(3).click() + .clear() + .type("new Content") + }) + }) + + /* save table */ + cy.get(".edit").click() + + }) + + cy.get('#blox-6').should("contain", "Beautiful").click() + + cy.get('.editactive').within(($activeblock) => { + cy.get('.component').should("contain", "Beautiful") + }) + + }) + }) + + it('Publishes new page', function() + { + cy.visit('/tm/content/visual/welcome/testpage') + cy.url().should('include','/tm\/content\/visual\/welcome\/testpage') + + cy.get('#publish').click().wait(500) + + cy.visit('/welcome/testpage') + cy.url().should('include','/welcome/testpage') + + cy.get('.cy-nav') + .should('contain', 'Testpage') + }) + + it('has sitemap xml', function () + { + cy.request({ + url: '/cache/sitemap.xml', + }) + .then((resp) => { + /* should return xml-format */ + expect(resp.headers).to.have.property('content-type','application/xml') + }) + }) + + it('Deletes new page', function() + { + cy.visit('/tm/content/visual/welcome/testpage') + cy.url().should('include','/tm\/content\/visual\/welcome\/testpage') + + cy.get('.danger').click() + + cy.get('#modalWindow').within(($modal) => { + cy.get('button').click() + }) + + cy.visit('/tm/content/visual/welcome') + cy.get('.navi-list') + .not('contain', 'Testpage') + .eq(2).find('a').should(($a) => { + expect($a).to.have.length(5) + }) + }) }) \ No newline at end of file diff --git a/cypress/integration/99-login.spec.js b/cypress/integration/99-login.spec.js new file mode 100644 index 0000000..6428ee5 --- /dev/null +++ b/cypress/integration/99-login.spec.js @@ -0,0 +1,67 @@ +describe("Typemill Login", function() { + before(function() { + cy.clearCookies(); + }); + it("redirects if visits dashboard without login", function() { + cy.visit("/tm/content"); + cy.url().should("include", "/tm/login"); + }); + + it("submits a valid form and logout", function() { + // visits login page and adds valid input + cy.visit("/tm/login"); + cy.url().should("include", "/tm/login"); + + cy.get('input[name="username"]') + .type("trendschau") + .should("have.value", "trendschau") + .and("have.attr", "required"); + + cy.get('input[name="password"]') + .type("password") + .should("have.value", "password") + .and("have.attr", "required"); + + // can login + cy.get("form").submit(); + cy.url().should("include", "/tm/content"); + cy.getCookie("typemill-session").should("exist"); + + Cypress.Cookies.preserveOnce("typemill-session"); + }); + + it("redirects if visits login form when logged in", function() { + cy.visit("/tm/login"); + cy.url().should("include", "/tm/content"); + + Cypress.Cookies.preserveOnce("typemill-session"); + }); + + it("logs out", function() { + cy.contains("Logout").click(); + cy.url().should("include", "/tm/login"); + }); + + it("captcha after 1 fail", function() { + cy.visit("/tm/login"); + + // validation fails first + cy.get('input[name="username"]').clear().type("wrong"); + cy.get('input[name="password"]').clear().type("pass"); + cy.get("form").submit(); + cy.get("#flash-message").should("contain", "wrong password or username"); + cy.get('input[name="username"]').should("have.value", "wrong"); + cy.get('input[name="password"]').should("have.value", ""); + cy.get('input[name="captcha"]').should("have.value", ""); + + // captcha fails first + cy.get('input[name="username"]').clear().type("trendschau"); + cy.get('input[name="password"]').clear().type("password"); + cy.get('input[name="captcha"]').clear().type("wrong"); + cy.get("form").submit(); + cy.get("#flash-message").should("contain", "Captcha is wrong"); + cy.get('input[name="username"]').should("have.value", "trendschau"); + cy.get('input[name="password"]').should("have.value", ""); + cy.get('input[name="captcha"]').should("have.value", ""); + }); +}); \ No newline at end of file diff --git a/cypress/plugins/index.js b/cypress/plugins/index.js new file mode 100644 index 0000000..5aaa3da --- /dev/null +++ b/cypress/plugins/index.js @@ -0,0 +1,34 @@ +const fs = require("fs"); + +/// +// *********************************************************** +// This example plugins/index.js can be used to load plugins +// +// You can change the location of this file or turn off loading +// the plugins file with the 'pluginsFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/plugins-guide +// *********************************************************** + +// This function is called when a project is opened or re-opened (e.g. due to +// the project's config changing) + +/** + * @type {Cypress.PluginConfig} + */ +// eslint-disable-next-line no-unused-vars +module.exports = (on, config) => { + on("task", { + resetSetup() { + fs.rmSync("settings/users", { recursive: true, force: true }); + fs.rmSync("settings/settings.yaml"); + fs.copyFileSync( + "cypress/fixtures/01_setup/default-settings.yaml", + "settings/settings.yaml" + ); + + return null; + }, + }); +}; \ No newline at end of file diff --git a/cypress/support/commands.js b/cypress/support/commands.js new file mode 100644 index 0000000..119ab03 --- /dev/null +++ b/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// 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 +// *********************************************** +// +// +// -- 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) => { ... }) diff --git a/cypress/support/index.js b/cypress/support/index.js new file mode 100644 index 0000000..d68db96 --- /dev/null +++ b/cypress/support/index.js @@ -0,0 +1,20 @@ +// *********************************************************** +// 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') diff --git a/cypress/test01-system-setup.spec.js b/cypress/test01-system-setup.spec.js deleted file mode 100644 index f0e3fba..0000000 --- a/cypress/test01-system-setup.spec.js +++ /dev/null @@ -1,167 +0,0 @@ -describe('Typemill Setup', function() -{ - it('validates form input', function () - { - // visit setup form - cy.visit('/setup') -// cy.visit('/setup',{ onBeforeLoad: (_contentWindow) => { Object.defineProperty(navigator, 'language', { value: 'fr-FR' }) } }) - cy.url().should('include','/setup') - - // add data and check attributes - cy.get('input[name="username"]') - .type('?1') - .should('have.value', '?1') - .and('have.attr', 'required') - - cy.get('input[name="email"]') - .type('trendschau.net') - .should('have.value', 'trendschau.net') - .and('have.attr', 'required') - - cy.get('input[name="password"]') - .type('pass') - .should('have.value', 'pass') - .and('have.attr', 'required') - - // submit and get validation errors - cy.get('form').submit() - cy.get('#flash-message').should('contain', 'Please check your input and try again') - cy.get('.error').should('contain', 'invalid characters') - cy.get('.error').should('contain', 'e-mail is invalid') - cy.get('.error').should('contain', 'Length between 5 - 20') - }) - -/* - it('fails without CSRF-token', function () - { - cy.request({ - method: 'POST', - url: '/setup', // baseUrl is prepended to url - form: true, // indicates the body should be form urlencoded and sets Content-Type: application/x-www-form-urlencoded headers - failOnStatusCode: false, - body: { - username: 'trendschau', - email: 'trendschau@gmail.com', - password: 'password' - } - }) - .its('body') - .should('include', 'The form has a timeout') - }) -*/ - it('fails without CSRF-token', function () - { - cy.visit('/setup') - - // enter correct data - cy.get('input[name="username"]').clear().type('trendschau') - cy.get('input[name="email"]').clear().type('trendschau@gmail.com') - cy.get('input[name="password"]').clear().type('password') - cy.get('#csrf_value').then(elem => { - elem.val('wrongvalue'); - }); - - // submit and get validation errors - cy.get('form').submit() - cy.get('#flash-message').should('contain', 'form has a timeout') - }) - - - it('submits valid form data and visit welcome and settings page', function () - { - cy.visit('/setup') - - // enter correct data - cy.get('input[name="username"]').clear().type('trendschau') - cy.get('input[name="email"]').clear().type('trendschau@gmail.com') - cy.get('input[name="password"]').clear().type('password') - - // submits valid form - cy.get('form').submit() - cy.url().should('include','/welcome') - cy.getCookie('typemill-session').should('exist') - Cypress.Cookies.preserveOnce('typemill-session') - - // clicks link on welcome page to settings page -// cy.get('.button').should('contain', 'Configure your website') - cy.get('.button').click() - cy.url().should('include', '/tm/settings') - }) - - it('creates default settings data', function() - { - cy.get('input[name="settings[title]"]') - .should('have.value', 'TYPEMILL') - .and('have.attr','required') - cy.get('input[name="settings[author]"]') - cy.get('select[name="settings[copyright]"]') - cy.get('input[name="settings[year]"]') - .should('have.attr', 'required') - cy.get('select[name="settings[language]"]') -// cy.get('select[name="settings[langattr]"]') - cy.get('input[name="settings[sitemap]"]') - .should('have.value', 'http://localhost/typemillTest/cache/sitemap.xml') - .and('have.attr','readonly') - cy.get('input[name="settings[logo]"]') - cy.get('input[name="settings[deletelogo]"]') - cy.get('input[name="settings[favicon]"]') - cy.get('input[name="settings[deletefav]"]') - cy.get('input[name="settings[headlineanchors]"]') - cy.get('input[name="settings[editor]"]') - - cy.get('select[name="settings[language]"]') - .select('en') - .should('have.value', 'en') - - cy.get('form').submit() - cy.get('#flash-message').should('contain', 'Settings are stored') - - Cypress.Cookies.preserveOnce('typemill-session') - }) - - it('creates default user data', function() - { - cy.visit('/tm/user/trendschau') - cy.url().should('include', '/tm/user/trendschau') - cy.get('input[name="user[username]"]') - .should('have.value', 'trendschau') - cy.get('input[name="user[firstname]"]') - .clear() - .type('Sebastian') - .should('have.value', 'Sebastian') - cy.get('input[name="user[lastname]"]') - .clear() - .type('Schürmanns') - .should('have.value', 'Schürmanns') - cy.get('input[name="user[email]"]') - .should('have.value', 'trendschau@gmail.com') - cy.get('select[name="user[userrole]"]') - .should('have.value','administrator') - cy.get('input[name="user[password]"]') - .should('have.value', '') - cy.get('input[name="user[newpassword]"]') - .should('have.value', '') - - cy.get('#userform').submit() - cy.get('#flash-message').should('contain', 'Saved all changes') - - }) - - it('logouts out', function() - { - // visits logout link - cy.visit('/tm/logout') - cy.url().should('include', '/tm/login') - - // tries to open setup form again and gets redirected to login - cy.visit('/setup') - cy.url().should('include','/login') - }) - - it('redirects when tries to setup again', function() - { - // tries to open setup form again and gets redirected to login - cy.visit('/setup') - cy.url().should('include','/login') - }) -}) \ No newline at end of file diff --git a/cypress/test02-initial-frontend.spec.js b/cypress/test02-initial-frontend.spec.js deleted file mode 100644 index 220f534..0000000 --- a/cypress/test02-initial-frontend.spec.js +++ /dev/null @@ -1,145 +0,0 @@ -describe('Typemill Initial Frontend', function() -{ - it('has startpage with navigation', function () - { - /* visit homepage */ - cy.visit('/') - - /* has startpage with headline */ - cy.get('h1').contains("Typemill") - - /* has start and setup button */ - cy.get('nav').find('a').should(($a) => { - expect($a).to.have.length(11) - expect($a[0].href).to.match(/welcome/) - expect($a[1].href).to.match(/welcome\/setup-your-website/) - expect($a[2].href).to.match(/welcome\/manage-access/) - expect($a[3].href).to.match(/welcome\/write-content/) - expect($a[4].href).to.match(/welcome\/get-help/) - expect($a[5].href).to.match(/welcome\/markdown-test/) - expect($a[6].href).to.match(/cyanine-theme/) - expect($a[7].href).to.match(/cyanine-theme\/landingpage/) - expect($a[8].href).to.match(/cyanine-theme\/colors-and-fonts/) - expect($a[9].href).to.match(/cyanine-theme\/footer/) - expect($a[10].href).to.match(/cyanine-theme\/content-elements/) - }) - }) - - it('has error page', function () - { - cy.request({ - url: '/error', - failOnStatusCode: false, - }) - .then((resp) => { - /* should return 404 not found */ - expect(resp.status).to.eq(404) - }) - - cy.visit('/error', { failOnStatusCode: false }) - cy.url().should('include','/error') - - cy.get('h1').contains('Not Found') - }) - - it('has no access to cache files', function () - { - cy.request({ - url: '/cache/structure.txt', - failOnStatusCode: false, - }) - .then((resp) => { - // redirect status code is 302 - expect(resp.status).to.eq(403) - }) - }) - - it('has no access to dashboard', function () - { - cy.visit('/tm/settings') - cy.url().should('include','/tm/login') - }) - - it('has proper markdown test page', function () - { - cy.visit('/welcome/markdown-test') - cy.url().should('include','/welcome/markdown-test') - - /* has navigation element */ - cy.get('nav').should('exist') - - /* check if toc exists */ - cy.get('.TOC').within(($toc) =>{ - /* check if a certain link in toc exists */ - cy.get('a').eq(2).should('have.attr', 'href', '#h-headlines') - }) - - /* check if corresponding anchor exists */ - cy.get('#h-headlines').should('exist') - - /* soft linebreaks */ - cy.get('br').should('exist') - - /* emphasis */ - cy.get('em').should('exist') - - /* strong */ - cy.get('strong').should('exist') - - /* ordered list */ - cy.get('ol').should('exist') - - /* linebreak */ - cy.get('hr').should('exist') - - /* links exists? hard to test, any idea? We need to wrap it in a div... */ - - /* images */ - cy.get('img').eq(0).should('have.attr', 'alt', 'alt') - cy.get('img').eq(0).should('have.attr', 'src').should('include','media/files/markdown.png') - cy.get('figure').eq(2).should('have.id', 'myid') - .and('have.class', 'otherclass') - cy.get('img').eq(2).should('have.attr', 'alt', 'alt-text') - .and('have.attr', 'title', 'my title') - .and('have.attr', 'width', '150px') - - /* blockquote */ - cy.get('blockquote').should('exist') - - /* has navigation element */ - cy.get('.notice1').should('exist') - cy.get('.notice2').should('exist') - cy.get('.notice3').should('exist') - - /* footnote */ - cy.get('sup').eq(0).should('have.id', 'fnref1:1') - cy.get('sup').eq(0).within(($sup) =>{ - cy.get('a').eq(0).should('have.attr', 'href', '#fn%3A1') - .and('have.class', 'footnote-ref') - }) - - /* abbreviation */ - cy.get('abbr').should('exist') - - /* definition list */ - cy.get('dl').should('exist') - - /* table */ - cy.get('table').should('exist') - - /* code */ - cy.get('pre').should('exist') - cy.get('code').should('exist') - - /* math */ - cy.get('.math').should('exist') - - /* footnote end */ - cy.get('.footnotes').within(($footnotes) => { - cy.get('li').eq(0).should('have.id', 'fn:1') - cy.get('a').eq(0).should('have.class', 'footnote-backref') - .and('have.attr', 'href', '#fnref1%3A1') - .and('have.attr', 'rev', 'footnote') - }) - }) -}) \ No newline at end of file diff --git a/cypress/test03-system-settings.spec.js b/cypress/test03-system-settings.spec.js deleted file mode 100644 index 4211609..0000000 --- a/cypress/test03-system-settings.spec.js +++ /dev/null @@ -1,109 +0,0 @@ -describe('Typemill System Settings', function() -{ - before(function () - { - cy.visit('/tm/login') - cy.url().should('include','/tm/login') - - cy.get('input[name="username"]').type('trendschau') - cy.get('input[name="password"]').type('password') - - cy.get('form').submit() - cy.url().should('include','/tm/content') - cy.getCookie('typemill-session').should('exist') - - cy.visit('/tm/settings') - cy.url().should('include','/tm/settings') - }) - - beforeEach(function () - { - Cypress.Cookies.preserveOnce('typemill-session') - }) - - it('validates the form', function() - { - // fill out valid data - cy.get('input[name="settings[title]"]') - .clear() - .type('Cypress