Robert Schäfer 72edf78889 Meld a chaotic commit history into one commit
Some important commit messages:

```
    Fix youtu.be not being embedded

    And also try to maintain the old behaviour matching
    `provider.provider_url`.
```

```
    Remove confusing code comments and obsolete code

    I discovered that the behaviour of no duplicate notifications being send
    out is caused by the frontend: When the editor reads html from the
    backend, it will parse hashtags and mentions as ordinary links, not as
    their respective nodes during editing. Also, we don't have to worry
    about duplicate ids being found: The cypher statement will implicitly
    suppress duplicate notification nodes for the same user.

    So let's remove the code to avoid confusing the next developer.
```

```
    Test editor.getHTML()

    I do this because I'm not able to test the content of `this.editor` from
    a wrapper of `vue-test-utils`. If I call `this.editor.getHTML` directly
    and use it as a computed property `renderedContent` to populate a `<div
    v-html="renderedContent" />` this will not work for the embeds. So, my
    current best bet is to test the editor object isolated from a real
    component. ;(
```

```
    Add core-js as explicit dependency

    Because of build errors on Travis.

    See: https://stackoverflow.com/a/55313456

    Remove as soon as this issue is resolved:
    https://github.com/storybookjs/storybook/issues/7591

```

```
    Refactor: Keep Runtime-only builds

    See: https://vuejs.org/v2/guide/installation.html#Runtime-Compiler-vs-Runtime-only
```
2019-08-01 00:28:22 +02:00

365 lines
9.9 KiB
JavaScript

import { Given, When, Then } from "cypress-cucumber-preprocessor/steps";
import { getLangByName } from "../../support/helpers";
import slugify from 'slug'
/* global cy */
let lastPost = {};
let loginCredentials = {
email: "peterpan@example.org",
password: "1234"
};
const narratorParams = {
name: "Peter Pan",
slug: 'peter-pan',
avatar: "https://s3.amazonaws.com/uifaces/faces/twitter/nerrsoft/128.jpg",
...loginCredentials
};
Given("I am logged in", () => {
cy.login(loginCredentials);
});
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: "cat2",
name: "Happyness & Values",
slug: "happyness-values",
icon: "heart-o"
})
.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" });
const someAuthor = {
id: "authorId",
email: "author@example.org",
password: "1234"
};
const yetAnotherAuthor = {
id: "yetAnotherAuthor",
email: "yet-another-author@example.org",
password: "1234"
};
cy.factory()
.create("User", someAuthor)
.authenticateAs(someAuthor)
.create("Post", { id: "p0" })
.create("Post", { id: "p1" });
cy.factory()
.create("User", yetAnotherAuthor)
.authenticateAs(yetAnotherAuthor)
.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" });
});
Given("we have the following user accounts:", table => {
table.hashes().forEach(params => {
cy.factory().create("User", params);
});
});
Given("I have a user account", () => {
cy.factory().create("User", narratorParams);
});
Given("my user account has the role {string}", role => {
cy.factory().create("User", {
role,
...loginCredentials
});
});
When("I log out", cy.logout);
When("I visit {string}", 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);
});
When("I fill in my email and password combination and click submit", () => {
cy.login(loginCredentials);
});
When(/(?:when )?I refresh the page/, () => {
cy.reload();
});
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();
});
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 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);
});
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();
});
When(`I click on the menu item {string}`, linkOrButton => {
cy.contains(".ds-menu-item", linkOrButton).click();
});
When("I press {string}", label => {
cy.contains(label).click();
});
Given("we have the following posts in our database:", table => {
table.hashes().forEach(({ Author, ...postAttributes }, i) => {
Author = Author || `author-${i}`
const userAttributes = {
name: Author,
email: `${slugify(Author, {lower: true})}@example.org`,
password: "1234"
};
postAttributes.deleted = Boolean(postAttributes.deleted);
const disabled = Boolean(postAttributes.disabled);
cy.factory()
.create("User", userAttributes)
.authenticateAs(userAttributes)
.create("Post", postAttributes);
if (disabled) {
const moderatorParams = {
email: "moderator@example.org",
role: "moderator",
password: "1234"
};
cy.factory()
.create("User", moderatorParams)
.authenticateAs(moderatorParams)
.mutate("mutation($id: ID!) { disable(id: $id) }", postAttributes);
}
});
});
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 big plus icon in the bottom right corner to create post",
() => {
cy.get(".post-add-button").click();
}
);
Given("I previously created a post", () => {
lastPost.title = "previously created post";
lastPost.content = "with some content";
cy.factory()
.authenticateAs(loginCredentials)
.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 type in the following text:", text => {
lastPost.content = text.replace("\n", " ");
cy.get(".editor .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("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(/^I should see only ([0-9]+) posts? on the landing page/, 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 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);
}
);
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=password]")
.type(table["Your new passsword"])
.get("input[id=passwordConfirmation]")
.type(table["Confirm new password"]);
});
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 can login successfully with password {string}", password => {
cy.reload();
cy.login({
...loginCredentials,
...{ 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("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("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("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("there are no notifications in the top menu", () => {
cy.get(".notifications-menu").should("contain", "0");
});