diff --git a/backend/package.json b/backend/package.json index 85a51fa14..e2ddfaa48 100644 --- a/backend/package.json +++ b/backend/package.json @@ -56,7 +56,7 @@ "debug": "~4.1.1", "dotenv": "~8.0.0", "express": "~4.17.1", - "faker": "~4.1.0", + "faker": "github:Marak/faker.js#master", "graphql": "~14.3.1", "graphql-custom-directives": "~0.2.14", "graphql-iso-date": "~3.6.1", diff --git a/backend/src/seed/factories/posts.js b/backend/src/seed/factories/posts.js index ea92f7d9f..4b098a62e 100644 --- a/backend/src/seed/factories/posts.js +++ b/backend/src/seed/factories/posts.js @@ -13,7 +13,7 @@ export default function(params) { faker.lorem.sentence(), faker.lorem.sentence(), ].join('. '), - image = faker.image.image(), + image = faker.image.unsplash.image(), visibility = 'public', deleted = false, } = params diff --git a/backend/src/seed/seed-db.js b/backend/src/seed/seed-db.js index 27af1106a..27c07868d 100644 --- a/backend/src/seed/seed-db.js +++ b/backend/src/seed/seed-db.js @@ -214,21 +214,21 @@ import Factory from './factories' 'Hey @jenny-rostock, here is another notification for you!' await Promise.all([ - asAdmin.create('Post', { id: 'p0' }), - asModerator.create('Post', { id: 'p1' }), + asAdmin.create('Post', { id: 'p0', image: faker.image.unsplash.food() }), + asModerator.create('Post', { id: 'p1', image: faker.image.unsplash.technology() }), asUser.create('Post', { id: 'p2' }), asTick.create('Post', { id: 'p3' }), asTrick.create('Post', { id: 'p4' }), asTrack.create('Post', { id: 'p5' }), - asAdmin.create('Post', { id: 'p6' }), + asAdmin.create('Post', { id: 'p6', image: faker.image.unsplash.buildings() }), asModerator.create('Post', { id: 'p7', content: `${mention1} ${faker.lorem.paragraph()}` }), - asUser.create('Post', { id: 'p8' }), + asUser.create('Post', { id: 'p8', image: faker.image.unsplash.nature() }), asTick.create('Post', { id: 'p9' }), asTrick.create('Post', { id: 'p10' }), - asTrack.create('Post', { id: 'p11' }), + asTrack.create('Post', { id: 'p11', image: faker.image.unsplash.people() }), asAdmin.create('Post', { id: 'p12', content: `${mention2} ${faker.lorem.paragraph()}` }), asModerator.create('Post', { id: 'p13' }), - asUser.create('Post', { id: 'p14' }), + asUser.create('Post', { id: 'p14', image: faker.image.unsplash.objects() }), asTick.create('Post', { id: 'p15' }), ]) diff --git a/backend/yarn.lock b/backend/yarn.lock index dee5b8d20..ab3025c03 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -3373,10 +3373,9 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= -faker@~4.1.0: +"faker@github:Marak/faker.js#master": version "4.1.0" - resolved "https://registry.yarnpkg.com/faker/-/faker-4.1.0.tgz#1e45bbbecc6774b3c195fad2835109c6d748cc3f" - integrity sha1-HkW7vsxndLPBlfrSg1EJxtdIzD8= + resolved "https://codeload.github.com/Marak/faker.js/tar.gz/10bfb9f467b0ac2b8912ffc15690b50ef3244f09" fast-deep-equal@^2.0.1: version "2.0.1" diff --git a/cypress/integration/common/steps.js b/cypress/integration/common/steps.js index 8f5bcc8ea..73313d331 100644 --- a/cypress/integration/common/steps.js +++ b/cypress/integration/common/steps.js @@ -1,347 +1,361 @@ -import { Given, When, Then } from 'cypress-cucumber-preprocessor/steps' -import { getLangByName } from '../../support/helpers' +import { Given, When, Then } from "cypress-cucumber-preprocessor/steps"; +import { getLangByName } from "../../support/helpers"; /* global cy */ -let lastPost = {} +let lastPost = {}; let loginCredentials = { - email: 'peterpan@example.org', - password: '1234' -} + email: "peterpan@example.org", + password: "1234" +}; const narratorParams = { - name: 'Peter Pan', - avatar: 'https://s3.amazonaws.com/uifaces/faces/twitter/nerrsoft/128.jpg', + name: "Peter Pan", + avatar: "https://s3.amazonaws.com/uifaces/faces/twitter/nerrsoft/128.jpg", ...loginCredentials -} +}; -Given('I am logged in', () => { - cy.login(loginCredentials) -}) +Given("I am logged in", () => { + cy.login(loginCredentials); +}); -Given('we have a selection of tags and categories as well as posts', () => { +Given("we have a selection of tags and categories as well as posts", () => { cy.factory() .authenticateAs(loginCredentials) - .create('Category', { - id: 'cat1', - name: 'Just For Fun', - slug: 'justforfun', - icon: 'smile' + .create("Category", { + id: "cat1", + name: "Just For Fun", + slug: "justforfun", + icon: "smile" }) - .create('Category', { - id: 'cat2', - name: 'Happyness & Values', - slug: 'happyness-values', - icon: 'heart-o' + .create("Category", { + id: "cat2", + name: "Happyness & Values", + slug: "happyness-values", + icon: "heart-o" }) - .create('Category', { - id: 'cat3', - name: 'Health & Wellbeing', - slug: 'health-wellbeing', - icon: 'medkit' + .create("Category", { + id: "cat3", + name: "Health & Wellbeing", + slug: "health-wellbeing", + icon: "medkit" }) - .create('Tag', { id: 't1', name: 'Ecology' }) - .create('Tag', { id: 't2', name: 'Nature' }) - .create('Tag', { id: 't3', name: 'Democracy' }) + .create("Tag", { id: "t1", name: "Ecology" }) + .create("Tag", { id: "t2", name: "Nature" }) + .create("Tag", { id: "t3", name: "Democracy" }); const someAuthor = { - id: 'authorId', - email: 'author@example.org', - password: '1234' - } + id: "authorId", + email: "author@example.org", + password: "1234" + }; const yetAnotherAuthor = { - id: 'yetAnotherAuthor', - email: 'yet-another-author@example.org', - password: '1234' - } + id: "yetAnotherAuthor", + email: "yet-another-author@example.org", + password: "1234" + }; cy.factory() - .create('User', someAuthor) + .create("User", someAuthor) .authenticateAs(someAuthor) - .create('Post', { id: 'p0' }) - .create('Post', { id: 'p1' }) + .create("Post", { id: "p0" }) + .create("Post", { id: "p1" }); cy.factory() - .create('User', yetAnotherAuthor) + .create("User", yetAnotherAuthor) .authenticateAs(yetAnotherAuthor) - .create('Post', { id: 'p2' }) + .create("Post", { id: "p2" }); cy.factory() .authenticateAs(loginCredentials) - .create('Post', { id: 'p3' }) - .relate('Post', 'Categories', { from: 'p0', to: 'cat1' }) - .relate('Post', 'Categories', { from: 'p1', to: 'cat2' }) - .relate('Post', 'Categories', { from: 'p2', to: 'cat1' }) - .relate('Post', 'Tags', { from: 'p0', to: 't1' }) - .relate('Post', 'Tags', { from: 'p0', to: 't2' }) - .relate('Post', 'Tags', { from: 'p0', to: 't3' }) - .relate('Post', 'Tags', { from: 'p1', to: 't2' }) - .relate('Post', 'Tags', { from: 'p1', to: 't3' }) - .relate('Post', 'Tags', { from: 'p2', to: 't2' }) - .relate('Post', 'Tags', { from: 'p2', to: 't3' }) - .relate('Post', 'Tags', { from: 'p3', to: 't3' }) -}) + .create("Post", { id: "p3" }) + .relate("Post", "Categories", { from: "p0", to: "cat1" }) + .relate("Post", "Categories", { from: "p1", to: "cat2" }) + .relate("Post", "Categories", { from: "p2", to: "cat1" }) + .relate("Post", "Tags", { from: "p0", to: "t1" }) + .relate("Post", "Tags", { from: "p0", to: "t2" }) + .relate("Post", "Tags", { from: "p0", to: "t3" }) + .relate("Post", "Tags", { from: "p1", to: "t2" }) + .relate("Post", "Tags", { from: "p1", to: "t3" }) + .relate("Post", "Tags", { from: "p2", to: "t2" }) + .relate("Post", "Tags", { from: "p2", to: "t3" }) + .relate("Post", "Tags", { from: "p3", to: "t3" }); +}); -Given('we have the following user accounts:', table => { +Given("we have the following user accounts:", table => { table.hashes().forEach(params => { - cy.factory().create('User', params) - }) -}) + cy.factory().create("User", params); + }); +}); -Given('I have a user account', () => { - cy.factory().create('User', narratorParams) -}) +Given("I have a user account", () => { + cy.factory().create("User", narratorParams); +}); -Given('my user account has the role {string}', role => { - cy.factory().create('User', { +Given("my user account has the role {string}", role => { + cy.factory().create("User", { role, ...loginCredentials - }) -}) + }); +}); -When('I log out', cy.logout) +When("I log out", cy.logout); -When('I visit {string}', page => { - cy.openPage(page) -}) +When("I visit {string}", page => { + cy.openPage(page); +}); -When('I visit the {string} page', page => { - cy.openPage(page) -}) +When("I visit the {string} page", page => { + cy.openPage(page); +}); -Given('I am on the {string} page', page => { - cy.openPage(page) -}) +Given("I am on the {string} page", page => { + cy.openPage(page); +}); -When('I fill in my email and password combination and click submit', () => { - cy.login(loginCredentials) -}) +When("I fill in my email and password combination and click submit", () => { + cy.login(loginCredentials); +}); When(/(?:when )?I refresh the page/, () => { - cy.reload() -}) + cy.reload(); +}); -When('I log out through the menu in the top right corner', () => { - cy.get('.avatar-menu').click() - cy.get('.avatar-menu-popover') +When("I log out through the menu in the top right corner", () => { + cy.get(".avatar-menu").click(); + cy.get(".avatar-menu-popover") .find('a[href="/logout"]') - .click() -}) + .click(); +}); -Then('I can see my name {string} in the dropdown menu', () => { - cy.get('.avatar-menu-popover').should('contain', narratorParams.name) -}) +Then("I can see my name {string} in the dropdown menu", () => { + cy.get(".avatar-menu-popover").should("contain", narratorParams.name); +}); -Then('I see the login screen again', () => { - cy.location('pathname').should('contain', '/login') -}) +Then("I see the login screen again", () => { + cy.location("pathname").should("contain", "/login"); +}); -Then('I can click on my profile picture in the top right corner', () => { - cy.get('.avatar-menu').click() - cy.get('.avatar-menu-popover') -}) +Then("I can click on my profile picture in the top right corner", () => { + cy.get(".avatar-menu").click(); + cy.get(".avatar-menu-popover"); +}); -Then('I am still logged in', () => { - cy.get('.avatar-menu').click() - cy.get('.avatar-menu-popover').contains(narratorParams.name) -}) +Then("I am still logged in", () => { + cy.get(".avatar-menu").click(); + cy.get(".avatar-menu-popover").contains(narratorParams.name); +}); -When('I select {string} in the language menu', name => { - cy.switchLanguage(name, true) -}) -Given('I previously switched the language to {string}', name => { - cy.switchLanguage(name, true) -}) -Then('the whole user interface appears in {string}', name => { - const lang = getLangByName(name) - cy.get(`html[lang=${lang.code}]`) - cy.getCookie('locale').should('have.property', 'value', lang.code) -}) -Then('I see a button with the label {string}', label => { - cy.contains('button', label) -}) +When("I select {string} in the language menu", name => { + cy.switchLanguage(name, true); +}); +Given("I previously switched the language to {string}", name => { + cy.switchLanguage(name, true); +}); +Then("the whole user interface appears in {string}", name => { + const lang = getLangByName(name); + cy.get(`html[lang=${lang.code}]`); + cy.getCookie("locale").should("have.property", "value", lang.code); +}); +Then("I see a button with the label {string}", label => { + cy.contains("button", label); +}); When(`I click on {string}`, linkOrButton => { - cy.contains(linkOrButton).click() -}) + cy.contains(linkOrButton).click(); +}); When(`I click on the menu item {string}`, linkOrButton => { - cy.contains('.ds-menu-item', linkOrButton).click() -}) + cy.contains(".ds-menu-item", linkOrButton).click(); +}); -When('I press {string}', label => { - cy.contains(label).click() -}) +When("I press {string}", label => { + cy.contains(label).click(); +}); -Given('we have the following posts in our database:', table => { +Given("we have the following posts in our database:", table => { table.hashes().forEach(({ Author, ...postAttributes }) => { const userAttributes = { name: Author, email: `${Author}@example.org`, - password: '1234' - } - postAttributes.deleted = Boolean(postAttributes.deleted) - const disabled = Boolean(postAttributes.disabled) + password: "1234" + }; + postAttributes.deleted = Boolean(postAttributes.deleted); + const disabled = Boolean(postAttributes.disabled); cy.factory() - .create('User', userAttributes) + .create("User", userAttributes) .authenticateAs(userAttributes) - .create('Post', postAttributes) + .create("Post", postAttributes); if (disabled) { const moderatorParams = { - email: 'moderator@example.org', - role: 'moderator', - password: '1234' - } + email: "moderator@example.org", + role: "moderator", + password: "1234" + }; cy.factory() - .create('User', moderatorParams) + .create("User", moderatorParams) .authenticateAs(moderatorParams) - .mutate('mutation($id: ID!) { disable(id: $id) }', postAttributes) + .mutate("mutation($id: ID!) { disable(id: $id) }", postAttributes); } - }) -}) + }); +}); -Then('I see a success message:', message => { - cy.contains(message) -}) +Then("I see a success message:", message => { + cy.contains(message); +}); -When('I click on the avatar menu in the top right corner', () => { - cy.get('.avatar-menu').click() -}) +When("I click on the avatar menu in the top right corner", () => { + cy.get(".avatar-menu").click(); +}); When( - 'I click on the big plus icon in the bottom right corner to create post', + "I click on the big plus icon in the bottom right corner to create post", () => { - cy.get('.post-add-button').click() + cy.get(".post-add-button").click(); } -) +); -Given('I previously created a post', () => { +Given("I previously created a post", () => { + lastPost.title = "previously created post"; + lastPost.content = "with some content"; cy.factory() .authenticateAs(loginCredentials) - .create('Post', lastPost) -}) + .create("Post", lastPost); +}); -When('I choose {string} as the title of the post', title => { - lastPost.title = title.replace('\n', ' ') - cy.get('input[name="title"]').type(lastPost.title) -}) +When("I choose {string} as the title of the post", title => { + lastPost.title = title.replace("\n", " "); + cy.get('input[name="title"]').type(lastPost.title); +}); -When('I type in the following text:', text => { - lastPost.content = text.replace('\n', ' ') - cy.get('.ProseMirror').type(lastPost.content) -}) +When("I type in the following text:", text => { + lastPost.content = text.replace("\n", " "); + cy.get(".ProseMirror").type(lastPost.content); +}); -Then('the post shows up on the landing page at position {int}', index => { - cy.openPage('landing') - const selector = `.post-card:nth-child(${index}) > .ds-card-content` - cy.get(selector).should('contain', lastPost.title) - cy.get(selector).should('contain', lastPost.content) -}) +Then("the post shows up on the landing page at position {int}", index => { + cy.openPage("landing"); + const selector = `.post-card:nth-child(${index}) > .ds-card-content`; + cy.get(selector).should("contain", lastPost.title); + cy.get(selector).should("contain", lastPost.content); +}); -Then('I get redirected to {string}', route => { - cy.location('pathname').should('contain', route.replace('...', '')) -}) +Then("I get redirected to {string}", route => { + cy.location("pathname").should("contain", route.replace("...", "")); +}); -Then('the post was saved successfully', () => { - cy.get('.ds-card-content > .ds-heading').should('contain', lastPost.title) - cy.get('.content').should('contain', lastPost.content) -}) +Then("the post was saved successfully", () => { + cy.get(".ds-card-content > .ds-heading").should("contain", lastPost.title); + cy.get(".content").should("contain", lastPost.content); +}); Then(/^I should see only ([0-9]+) posts? on the landing page/, postCount => { - cy.get('.post-card').should('have.length', postCount) -}) + cy.get(".post-card").should("have.length", postCount); +}); -Then('the first post on the landing page has the title:', title => { - cy.get('.post-card:first').should('contain', title) -}) +Then("the first post on the landing page has the title:", title => { + cy.get(".post-card:first").should("contain", title); +}); Then( - 'the page {string} returns a 404 error with a message:', + "the page {string} returns a 404 error with a message:", (route, message) => { // TODO: how can we check HTTP codes with cypress? - cy.visit(route, { failOnStatusCode: false }) - cy.get('.error').should('contain', message) + cy.visit(route, { failOnStatusCode: false }); + cy.get(".error").should("contain", message); } -) +); -Given('my user account has the following login credentials:', table => { - loginCredentials = table.hashes()[0] - cy.debug() - cy.factory().create('User', loginCredentials) -}) +Given("my user account has the following login credentials:", table => { + loginCredentials = table.hashes()[0]; + cy.debug(); + cy.factory().create("User", loginCredentials); +}); -When('I fill the password form with:', table => { - table = table.rowsHash() - cy.get('input[id=oldPassword]') - .type(table['Your old password']) - .get('input[id=newPassword]') - .type(table['Your new passsword']) - .get('input[id=confirmPassword]') - .type(table['Confirm new password']) -}) +When("I fill the password form with:", table => { + table = table.rowsHash(); + cy.get("input[id=oldPassword]") + .type(table["Your old password"]) + .get("input[id=newPassword]") + .type(table["Your new passsword"]) + .get("input[id=confirmPassword]") + .type(table["Confirm new password"]); +}); -When('submit the form', () => { - cy.get('form').submit() -}) +When("submit the form", () => { + cy.get("form").submit(); +}); -Then('I cannot login anymore with password {string}', password => { - cy.reload() - const { email } = loginCredentials - cy.visit(`/login`) - cy.get('input[name=email]') - .trigger('focus') - .type(email) - cy.get('input[name=password]') - .trigger('focus') - .type(password) - cy.get('button[name=submit]') - .as('submitButton') - .click() - cy.get('.iziToast-wrapper').should('contain', 'Incorrect email address or password.') -}) +Then("I cannot login anymore with password {string}", password => { + cy.reload(); + const { email } = loginCredentials; + cy.visit(`/login`); + cy.get("input[name=email]") + .trigger("focus") + .type(email); + cy.get("input[name=password]") + .trigger("focus") + .type(password); + cy.get("button[name=submit]") + .as("submitButton") + .click(); + cy.get(".iziToast-wrapper").should( + "contain", + "Incorrect email address or password." + ); +}); -Then('I can login successfully with password {string}', password => { - cy.reload() +Then("I can login successfully with password {string}", password => { + cy.reload(); cy.login({ ...loginCredentials, - ...{password} - }) - cy.get('.iziToast-wrapper').should('contain', "You are logged in!") -}) + ...{ password } + }); + cy.get(".iziToast-wrapper").should("contain", "You are logged in!"); +}); -When('I log in with the following credentials:', table => { - const { email, password } = table.hashes()[0] - cy.login({ email, password }) -}) +When("I log in with the following credentials:", table => { + const { email, password } = table.hashes()[0]; + cy.login({ email, password }); +}); -When('open the notification menu and click on the first item', () => { - cy.get('.notifications-menu').click() - cy.get('.notification-mention-post').first().click() -}) +When("open the notification menu and click on the first item", () => { + cy.get(".notifications-menu").click(); + cy.get(".notification-mention-post") + .first() + .click(); +}); -Then('see {int} unread notifications in the top menu', count => { - cy.get('.notifications-menu').should('contain', count) -}) +Then("see {int} unread notifications in the top menu", count => { + cy.get(".notifications-menu").should("contain", count); +}); -Then('I get to the post page of {string}', path => { - path = path.replace('...', '') - cy.url().should('contain', '/post/') - cy.url().should('contain', path) -}) +Then("I get to the post page of {string}", path => { + path = path.replace("...", ""); + cy.url().should("contain", "/post/"); + cy.url().should("contain", path); +}); -When('I start to write a new post with the title {string} beginning with:', (title, intro) => { - cy.get('.post-add-button').click() - cy.get('input[name="title"]').type(title) - cy.get('.ProseMirror').type(intro) -}) +When( + "I start to write a new post with the title {string} beginning with:", + (title, intro) => { + cy.get(".post-add-button").click(); + cy.get('input[name="title"]').type(title); + cy.get(".ProseMirror").type(intro); + } +); -When('mention {string} in the text', (mention) => { - cy.get('.ProseMirror').type(' @') - cy.get('.suggestion-list__item').contains(mention).click() - cy.debug() -}) +When("mention {string} in the text", mention => { + cy.get(".ProseMirror").type(" @"); + cy.get(".suggestion-list__item") + .contains(mention) + .click(); + cy.debug(); +}); -Then('the notification gets marked as read', () => { - cy.get('.notification').first().should('have.class', 'read') -}) +Then("the notification gets marked as read", () => { + cy.get(".notification") + .first() + .should("have.class", "read"); +}); -Then('there are no notifications in the top menu', () => { - cy.get('.notifications-menu').should('contain', '0') -}) +Then("there are no notifications in the top menu", () => { + cy.get(".notifications-menu").should("contain", "0"); +}); diff --git a/cypress/integration/post/WritePost.feature b/cypress/integration/post/WritePost.feature index fed1bbf2f..06ac4a175 100644 --- a/cypress/integration/post/WritePost.feature +++ b/cypress/integration/post/WritePost.feature @@ -12,10 +12,10 @@ Feature: Create a post When I click on the big plus icon in the bottom right corner to create post And I choose "My first post" as the title of the post And I type in the following text: - """ - Human Connection is a free and open-source social network - for active citizenship. - """ + """ + Human Connection is a free and open-source social network + for active citizenship. + """ And I click on "Save" Then I get redirected to ".../my-first-post" And the post was saved successfully diff --git a/webapp/components/Avatar/Avatar.spec.js b/webapp/components/Avatar/Avatar.spec.js index d3ebcb030..626e584c9 100644 --- a/webapp/components/Avatar/Avatar.spec.js +++ b/webapp/components/Avatar/Avatar.spec.js @@ -53,7 +53,7 @@ describe('Avatar.vue', () => { beforeEach(() => { propsData = { user: { - avatar: 'http://lorempixel.com/640/480/animals', + avatar: 'https://s3.amazonaws.com/uifaces/faces/twitter/sawalazar/128.jpg', }, } }) @@ -64,7 +64,7 @@ describe('Avatar.vue', () => { Wrapper() .find('img') .attributes('src'), - ).toBe('http://lorempixel.com/640/480/animals') + ).toBe('https://s3.amazonaws.com/uifaces/faces/twitter/sawalazar/128.jpg') }) }) })