Compare commits
10 commits
178193bfd8
...
72cdd7dc4e
| Author | SHA1 | Date | |
|---|---|---|---|
| 72cdd7dc4e | |||
| d40efeec70 | |||
| db910c9431 | |||
| 6f160ddd4e | |||
| 66ad7b1a0f | |||
| 84ee24c2ee | |||
| 07f9746316 | |||
| 910bc98197 | |||
| 9db7920f80 | |||
| 75ada812bc |
9 changed files with 682 additions and 0 deletions
99
frontend/blog_portal/cypress/e2e/admin_actions.cy.ts
Normal file
99
frontend/blog_portal/cypress/e2e/admin_actions.cy.ts
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
describe("admin actions", function () {
|
||||
beforeEach(function () {
|
||||
cy.resetDb();
|
||||
cy.clearMail();
|
||||
cy.seedAdmin({
|
||||
email: "admin@example.com",
|
||||
displayName: "rootadmin",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
cy.seedConfirmedUser({
|
||||
email: "alice@example.com",
|
||||
displayName: "alice",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
cy.seedConfirmedUser({
|
||||
email: "bob@example.com",
|
||||
displayName: "bob",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
cy.seedPostAs({
|
||||
email: "alice@example.com",
|
||||
password: "longenoughpassword",
|
||||
title: "Alice post",
|
||||
body: "Body.",
|
||||
}).as("alicePost");
|
||||
});
|
||||
|
||||
it("admin promotes another user via the profile page", function () {
|
||||
cy.loginViaApi({
|
||||
email: "admin@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
|
||||
cy.visit("/users/alice");
|
||||
cy.contains("button", "Promote to admin").click();
|
||||
|
||||
cy.logoutViaApi();
|
||||
cy.loginViaApi({
|
||||
email: "alice@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
cy.get<{ id: number }>("@alicePost").then(function (post) {
|
||||
cy.visit(`/posts/${post.id}`);
|
||||
cy.contains("button", "Feature in slot 1").should("be.visible");
|
||||
});
|
||||
});
|
||||
|
||||
it("admin features a post and it shows up on the home page", function () {
|
||||
cy.loginViaApi({
|
||||
email: "admin@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
|
||||
cy.get<{ id: number }>("@alicePost").then(function (post) {
|
||||
cy.visit(`/posts/${post.id}`);
|
||||
cy.contains("button", "Feature in slot 1").click();
|
||||
cy.contains(".badge", "Featured (slot 1)").should("be.visible");
|
||||
});
|
||||
|
||||
cy.logoutViaApi();
|
||||
cy.visit("/");
|
||||
cy.contains("h2", "Featured").should("be.visible");
|
||||
cy.get(".featured .post-card").should("have.length", 1);
|
||||
cy.contains(".featured .post-card", "Alice post").should("be.visible");
|
||||
});
|
||||
|
||||
it("admin unfeaturing a post removes it from the home page", function () {
|
||||
cy.loginViaApi({
|
||||
email: "admin@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
|
||||
cy.get<{ id: number }>("@alicePost").then(function (post) {
|
||||
cy.visit(`/posts/${post.id}`);
|
||||
cy.contains("button", "Feature in slot 1").click();
|
||||
cy.contains(".badge", "Featured (slot 1)").should("be.visible");
|
||||
cy.contains("button", "Unfeature").click();
|
||||
cy.contains(".badge", "Featured").should("not.exist");
|
||||
});
|
||||
|
||||
cy.logoutViaApi();
|
||||
cy.visit("/");
|
||||
cy.contains("h2", "Featured").should("not.exist");
|
||||
});
|
||||
|
||||
it("a newly promoted admin can also feature posts", function () {
|
||||
cy.promoteAdmin("bob@example.com");
|
||||
cy.loginViaApi({
|
||||
email: "bob@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
|
||||
cy.get<{ id: number }>("@alicePost").then(function (post) {
|
||||
cy.visit(`/posts/${post.id}`);
|
||||
cy.contains("button", "Feature in slot 2").click();
|
||||
cy.contains(".badge", "Featured (slot 2)").should("be.visible");
|
||||
});
|
||||
});
|
||||
});
|
||||
48
frontend/blog_portal/cypress/e2e/confirm_email_page.cy.ts
Normal file
48
frontend/blog_portal/cypress/e2e/confirm_email_page.cy.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
describe("confirm email page", function () {
|
||||
beforeEach(function () {
|
||||
cy.resetDb();
|
||||
cy.clearMail();
|
||||
});
|
||||
|
||||
it("redirects to /login when no token is present", function () {
|
||||
cy.visit("/confirm-email");
|
||||
cy.location("pathname").should("eq", "/login");
|
||||
});
|
||||
|
||||
it("sets the password and redirects to /login on success", function () {
|
||||
cy.signupViaApi({
|
||||
email: "alice@example.com",
|
||||
displayName: "alice",
|
||||
});
|
||||
cy.fetchLatestConfirmToken("alice@example.com").then(function (token) {
|
||||
cy.visit(`/confirm-email?token=${token}`);
|
||||
cy.get('input[type="password"]').type("longenoughpassword");
|
||||
cy.contains("button", "Confirm").click();
|
||||
|
||||
cy.location("pathname").should("eq", "/login");
|
||||
|
||||
cy.loginViaApi({
|
||||
email: "alice@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("shows the backend error when password is too short", function () {
|
||||
cy.signupViaApi({
|
||||
email: "alice@example.com",
|
||||
displayName: "alice",
|
||||
});
|
||||
cy.fetchLatestConfirmToken("alice@example.com").then(function (token) {
|
||||
cy.visit(`/confirm-email?token=${token}`);
|
||||
cy.get('input[type="password"]')
|
||||
.invoke("removeAttr", "minlength")
|
||||
.type("short");
|
||||
cy.contains("button", "Confirm").click();
|
||||
|
||||
cy.contains(".error", "password must be at least 8").should(
|
||||
"be.visible",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
41
frontend/blog_portal/cypress/e2e/guest_routes.cy.ts
Normal file
41
frontend/blog_portal/cypress/e2e/guest_routes.cy.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
describe("guest route guards", function () {
|
||||
beforeEach(function () {
|
||||
cy.resetDb();
|
||||
cy.clearMail();
|
||||
});
|
||||
|
||||
it("redirects anonymous visitors away from /users/:displayName/posts/new", function () {
|
||||
cy.visit("/users/alice/posts/new");
|
||||
cy.location("pathname").should("eq", "/login");
|
||||
});
|
||||
|
||||
it("redirects authenticated visitors away from /login", function () {
|
||||
cy.seedConfirmedUser({
|
||||
email: "alice@example.com",
|
||||
displayName: "alice",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
cy.loginViaApi({
|
||||
email: "alice@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
|
||||
cy.visit("/login");
|
||||
cy.location("pathname").should("eq", "/");
|
||||
});
|
||||
|
||||
it("redirects authenticated visitors away from /signup", function () {
|
||||
cy.seedConfirmedUser({
|
||||
email: "alice@example.com",
|
||||
displayName: "alice",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
cy.loginViaApi({
|
||||
email: "alice@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
|
||||
cy.visit("/signup");
|
||||
cy.location("pathname").should("eq", "/");
|
||||
});
|
||||
});
|
||||
101
frontend/blog_portal/cypress/e2e/home_page.cy.ts
Normal file
101
frontend/blog_portal/cypress/e2e/home_page.cy.ts
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
describe("home page", function () {
|
||||
beforeEach(function () {
|
||||
cy.resetDb();
|
||||
cy.clearMail();
|
||||
cy.seedConfirmedUser({
|
||||
email: "alice@example.com",
|
||||
displayName: "alice",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
cy.seedConfirmedUser({
|
||||
email: "bob@example.com",
|
||||
displayName: "bob",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
cy.seedPostAs({
|
||||
email: "alice@example.com",
|
||||
password: "longenoughpassword",
|
||||
title: "Alice first",
|
||||
body: "Alice's first post.",
|
||||
});
|
||||
cy.seedPostAs({
|
||||
email: "bob@example.com",
|
||||
password: "longenoughpassword",
|
||||
title: "Bob says hi",
|
||||
body: "Bob's only post.",
|
||||
});
|
||||
cy.seedPostAs({
|
||||
email: "alice@example.com",
|
||||
password: "longenoughpassword",
|
||||
title: "Alice second",
|
||||
body: "Alice's second post.",
|
||||
});
|
||||
});
|
||||
|
||||
it("renders recent posts in newest-first order with author links", function () {
|
||||
cy.visit("/");
|
||||
cy.contains("h2", "Recent posts").should("be.visible");
|
||||
cy.get(".recent .post-card").should("have.length", 3);
|
||||
cy.get(".recent .post-card").first().within(function () {
|
||||
cy.contains("Alice second");
|
||||
cy.contains("a", "alice");
|
||||
});
|
||||
});
|
||||
|
||||
it("hides the featured section when no posts are featured", function () {
|
||||
cy.visit("/");
|
||||
cy.contains("h2", "Featured").should("not.exist");
|
||||
});
|
||||
|
||||
it("shows featured posts in slot order once an admin features them", function () {
|
||||
cy.seedAdmin({
|
||||
email: "admin@example.com",
|
||||
displayName: "rootadmin",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
cy.request("/api/posts").then(function (response) {
|
||||
const posts = response.body.posts as Array<{
|
||||
id: number;
|
||||
title: string;
|
||||
}>;
|
||||
const aliceSecond = posts.find(function (entry) {
|
||||
return entry.title === "Alice second";
|
||||
})!;
|
||||
const bobPost = posts.find(function (entry) {
|
||||
return entry.title === "Bob says hi";
|
||||
})!;
|
||||
cy.seedFeaturedPost({
|
||||
adminEmail: "admin@example.com",
|
||||
adminPassword: "longenoughpassword",
|
||||
postId: bobPost.id,
|
||||
slot: 2,
|
||||
});
|
||||
cy.seedFeaturedPost({
|
||||
adminEmail: "admin@example.com",
|
||||
adminPassword: "longenoughpassword",
|
||||
postId: aliceSecond.id,
|
||||
slot: 1,
|
||||
});
|
||||
});
|
||||
|
||||
cy.visit("/");
|
||||
cy.contains("h2", "Featured").should("be.visible");
|
||||
cy.get(".featured .post-card").should("have.length", 2);
|
||||
cy.get(".featured .post-card").eq(0).contains("Alice second");
|
||||
cy.get(".featured .post-card").eq(1).contains("Bob says hi");
|
||||
});
|
||||
|
||||
it("searches users by display name and email prefix", function () {
|
||||
cy.visit("/");
|
||||
cy.get('input[type="search"]').type("al");
|
||||
cy.get(".results li").should("have.length", 1);
|
||||
cy.get(".results li").contains("alice");
|
||||
|
||||
cy.get('input[type="search"]').clear().type("b");
|
||||
cy.get(".results li").should("have.length", 1);
|
||||
cy.get(".results li").contains("bob");
|
||||
|
||||
cy.get('input[type="search"]').clear().type("zzz");
|
||||
cy.get(".results li").should("have.length", 0);
|
||||
});
|
||||
});
|
||||
41
frontend/blog_portal/cypress/e2e/login_page.cy.ts
Normal file
41
frontend/blog_portal/cypress/e2e/login_page.cy.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
describe("login page", function () {
|
||||
beforeEach(function () {
|
||||
cy.resetDb();
|
||||
cy.clearMail();
|
||||
cy.seedConfirmedUser({
|
||||
email: "alice@example.com",
|
||||
displayName: "alice",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
});
|
||||
|
||||
it("logs in with valid credentials and shows the user in the header", function () {
|
||||
cy.visit("/login");
|
||||
cy.get('input[type="email"]').type("alice@example.com");
|
||||
cy.get('input[type="password"]').type("longenoughpassword");
|
||||
cy.contains("button", "Log in").click();
|
||||
|
||||
cy.location("pathname").should("eq", "/");
|
||||
cy.get(".app-header").contains("alice").should("be.visible");
|
||||
});
|
||||
|
||||
it("shows an error on wrong password", function () {
|
||||
cy.visit("/login");
|
||||
cy.get('input[type="email"]').type("alice@example.com");
|
||||
cy.get('input[type="password"]').type("wrongpassword");
|
||||
cy.contains("button", "Log in").click();
|
||||
|
||||
cy.location("pathname").should("eq", "/login");
|
||||
cy.contains(".error", "invalid credentials").should("be.visible");
|
||||
});
|
||||
|
||||
it("redirects authenticated users away from /login", function () {
|
||||
cy.loginViaApi({
|
||||
email: "alice@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
|
||||
cy.visit("/login");
|
||||
cy.location("pathname").should("eq", "/");
|
||||
});
|
||||
});
|
||||
63
frontend/blog_portal/cypress/e2e/new_post_page.cy.ts
Normal file
63
frontend/blog_portal/cypress/e2e/new_post_page.cy.ts
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
describe("new post page", function () {
|
||||
beforeEach(function () {
|
||||
cy.resetDb();
|
||||
cy.clearMail();
|
||||
cy.seedConfirmedUser({
|
||||
email: "alice@example.com",
|
||||
displayName: "alice",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
cy.seedConfirmedUser({
|
||||
email: "bob@example.com",
|
||||
displayName: "bob",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
});
|
||||
|
||||
it("redirects anonymous visitors to /login", function () {
|
||||
cy.visit("/users/alice/posts/new");
|
||||
cy.location("pathname").should("eq", "/login");
|
||||
});
|
||||
|
||||
it("redirects users away from another user's new-post page", function () {
|
||||
cy.loginViaApi({
|
||||
email: "alice@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
|
||||
cy.visit("/users/bob/posts/new");
|
||||
cy.location("pathname").should("eq", "/");
|
||||
});
|
||||
|
||||
it("publishes a post and redirects to the new post page", function () {
|
||||
cy.loginViaApi({
|
||||
email: "alice@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
|
||||
cy.visit("/users/alice/posts/new");
|
||||
cy.get('input[type="text"]').type("Hello world");
|
||||
cy.get("textarea").type("This is the body of my first post.");
|
||||
cy.contains("button", "Publish").click();
|
||||
|
||||
cy.location("pathname").should("match", /^\/posts\/\d+$/);
|
||||
cy.contains("h1", "Hello world").should("be.visible");
|
||||
cy.contains(".body", "This is the body of my first post.").should(
|
||||
"be.visible",
|
||||
);
|
||||
});
|
||||
|
||||
it("blocks submission when the title is empty (HTML5 validation)", function () {
|
||||
cy.loginViaApi({
|
||||
email: "alice@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
|
||||
cy.visit("/users/alice/posts/new");
|
||||
cy.get("textarea").type("body only");
|
||||
cy.contains("button", "Publish").click();
|
||||
|
||||
cy.location("pathname").should("eq", "/users/alice/posts/new");
|
||||
cy.get('input[type="text"]:invalid').should("exist");
|
||||
});
|
||||
});
|
||||
136
frontend/blog_portal/cypress/e2e/post_page.cy.ts
Normal file
136
frontend/blog_portal/cypress/e2e/post_page.cy.ts
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
describe("post page", function () {
|
||||
beforeEach(function () {
|
||||
cy.resetDb();
|
||||
cy.clearMail();
|
||||
cy.seedConfirmedUser({
|
||||
email: "alice@example.com",
|
||||
displayName: "alice",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
cy.seedConfirmedUser({
|
||||
email: "bob@example.com",
|
||||
displayName: "bob",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
cy.seedPostAs({
|
||||
email: "alice@example.com",
|
||||
password: "longenoughpassword",
|
||||
title: "Alice post",
|
||||
body: "Body of alice's post.",
|
||||
}).as("alicePost");
|
||||
});
|
||||
|
||||
it("renders the post for anonymous visitors with a login CTA", function () {
|
||||
cy.get<{ id: number }>("@alicePost").then(function (post) {
|
||||
cy.visit(`/posts/${post.id}`);
|
||||
cy.contains("h1", "Alice post").should("be.visible");
|
||||
cy.contains("a", "alice").should("be.visible");
|
||||
cy.contains("Comments (0)").should("be.visible");
|
||||
cy.contains("Log in").should("be.visible");
|
||||
cy.get(".comment-form").should("not.exist");
|
||||
});
|
||||
});
|
||||
|
||||
it("lets a signed-in user add a comment", function () {
|
||||
cy.loginViaApi({
|
||||
email: "bob@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
|
||||
cy.get<{ id: number }>("@alicePost").then(function (post) {
|
||||
cy.visit(`/posts/${post.id}`);
|
||||
cy.get(".comment-form textarea").type("nice post");
|
||||
cy.contains(".comment-form button", "Comment").click();
|
||||
|
||||
cy.contains(".comment-list li", "nice post").should("be.visible");
|
||||
cy.contains(".comment-list li", "bob").should("be.visible");
|
||||
cy.contains("Comments (1)").should("be.visible");
|
||||
});
|
||||
});
|
||||
|
||||
it("only shows the Delete control on comments you can delete", function () {
|
||||
cy.loginViaApi({
|
||||
email: "bob@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
|
||||
cy.get<{ id: number }>("@alicePost").then(function (post) {
|
||||
cy.request("POST", `/api/posts/${post.id}/comments`, {
|
||||
body: "bob's comment",
|
||||
});
|
||||
cy.logoutViaApi();
|
||||
cy.loginViaApi({
|
||||
email: "alice@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
cy.request("POST", `/api/posts/${post.id}/comments`, {
|
||||
body: "alice's comment",
|
||||
});
|
||||
|
||||
cy.visit(`/posts/${post.id}`);
|
||||
cy.contains(".comment-list li", "alice's comment")
|
||||
.find("button.delete")
|
||||
.should("exist");
|
||||
cy.contains(".comment-list li", "bob's comment")
|
||||
.find("button.delete")
|
||||
.should("not.exist");
|
||||
});
|
||||
});
|
||||
|
||||
it("hides the Delete post control for non-author non-admin users", function () {
|
||||
cy.loginViaApi({
|
||||
email: "bob@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
|
||||
cy.get<{ id: number }>("@alicePost").then(function (post) {
|
||||
cy.visit(`/posts/${post.id}`);
|
||||
cy.contains("button", "Delete post").should("not.exist");
|
||||
cy.contains("button", "Feature in slot 1").should("not.exist");
|
||||
});
|
||||
});
|
||||
|
||||
it("lets the author delete their post", function () {
|
||||
cy.loginViaApi({
|
||||
email: "alice@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
|
||||
cy.get<{ id: number }>("@alicePost").then(function (post) {
|
||||
cy.visit(`/posts/${post.id}`);
|
||||
cy.contains("button", "Delete post").click();
|
||||
cy.location("pathname").should("eq", "/");
|
||||
});
|
||||
});
|
||||
|
||||
it("shows admin controls (delete, feature, unfeature) to admins", function () {
|
||||
cy.seedAdmin({
|
||||
email: "admin@example.com",
|
||||
displayName: "rootadmin",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
cy.loginViaApi({
|
||||
email: "admin@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
|
||||
cy.get<{ id: number }>("@alicePost").then(function (post) {
|
||||
cy.visit(`/posts/${post.id}`);
|
||||
cy.contains("button", "Delete post").should("be.visible");
|
||||
cy.contains("button", "Feature in slot 1").should("be.visible");
|
||||
cy.contains("button", "Feature in slot 2").should("be.visible");
|
||||
|
||||
cy.contains("button", "Feature in slot 1").click();
|
||||
cy.contains(".badge", "Featured (slot 1)").should("be.visible");
|
||||
cy.contains("button", "Unfeature").should("be.visible");
|
||||
|
||||
cy.contains("button", "Unfeature").click();
|
||||
cy.contains(".badge", "Featured").should("not.exist");
|
||||
});
|
||||
});
|
||||
|
||||
it("shows a not-found panel for unknown post ids", function () {
|
||||
cy.visit("/posts/9999");
|
||||
cy.contains("h1", "Post not found").should("be.visible");
|
||||
});
|
||||
});
|
||||
86
frontend/blog_portal/cypress/e2e/profile_page.cy.ts
Normal file
86
frontend/blog_portal/cypress/e2e/profile_page.cy.ts
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
describe("profile page", function () {
|
||||
beforeEach(function () {
|
||||
cy.resetDb();
|
||||
cy.clearMail();
|
||||
cy.seedConfirmedUser({
|
||||
email: "alice@example.com",
|
||||
displayName: "alice",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
cy.seedConfirmedUser({
|
||||
email: "bob@example.com",
|
||||
displayName: "bob",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
cy.seedPostAs({
|
||||
email: "alice@example.com",
|
||||
password: "longenoughpassword",
|
||||
title: "Alice's only post",
|
||||
body: "Hello.",
|
||||
});
|
||||
});
|
||||
|
||||
it("shows posts to anonymous visitors without owner controls", function () {
|
||||
cy.visit("/users/alice");
|
||||
cy.contains("h1", "alice").should("be.visible");
|
||||
cy.contains(".post-card", "Alice's only post").should("be.visible");
|
||||
cy.contains("button", "New post").should("not.exist");
|
||||
cy.contains("button", "Promote to admin").should("not.exist");
|
||||
});
|
||||
|
||||
it("shows the New post button when viewing your own profile", function () {
|
||||
cy.loginViaApi({
|
||||
email: "alice@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
|
||||
cy.visit("/users/alice");
|
||||
cy.contains("button", "New post").should("be.visible");
|
||||
cy.contains("button", "Promote to admin").should("not.exist");
|
||||
});
|
||||
|
||||
it("hides the Promote button from non-admin viewers", function () {
|
||||
cy.loginViaApi({
|
||||
email: "bob@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
|
||||
cy.visit("/users/alice");
|
||||
cy.contains("button", "Promote to admin").should("not.exist");
|
||||
});
|
||||
|
||||
it("shows the Promote button to an admin viewing someone else", function () {
|
||||
cy.seedAdmin({
|
||||
email: "admin@example.com",
|
||||
displayName: "rootadmin",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
cy.loginViaApi({
|
||||
email: "admin@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
|
||||
cy.visit("/users/alice");
|
||||
cy.contains("button", "Promote to admin").should("be.visible");
|
||||
});
|
||||
|
||||
it("hides the Promote button when an admin views their own profile", function () {
|
||||
cy.seedAdmin({
|
||||
email: "admin@example.com",
|
||||
displayName: "rootadmin",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
cy.loginViaApi({
|
||||
email: "admin@example.com",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
|
||||
cy.visit("/users/rootadmin");
|
||||
cy.contains("button", "Promote to admin").should("not.exist");
|
||||
});
|
||||
|
||||
it("renders a not-found panel for unknown display names", function () {
|
||||
cy.visit("/users/nobody");
|
||||
cy.contains("h1", "User not found").should("be.visible");
|
||||
});
|
||||
});
|
||||
67
frontend/blog_portal/cypress/e2e/signup_page.cy.ts
Normal file
67
frontend/blog_portal/cypress/e2e/signup_page.cy.ts
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
describe("signup page", function () {
|
||||
beforeEach(function () {
|
||||
cy.resetDb();
|
||||
cy.clearMail();
|
||||
});
|
||||
|
||||
it("creates an unconfirmed user and redirects to check-email", function () {
|
||||
cy.visit("/signup");
|
||||
cy.get('input[type="email"]').type("alice@example.com");
|
||||
cy.get('input[autocomplete="username"]').type("alice");
|
||||
cy.contains("button", "Continue").click();
|
||||
|
||||
cy.location("pathname").should("eq", "/check-email");
|
||||
cy.contains("h1", "Check your email").should("be.visible");
|
||||
|
||||
cy.getMail().then(function (inbox) {
|
||||
expect(inbox.messages).to.have.length(1);
|
||||
expect(inbox.messages[0].To[0].Address).to.equal(
|
||||
"alice@example.com",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it("surfaces a 409 when the email is already registered", function () {
|
||||
cy.seedConfirmedUser({
|
||||
email: "alice@example.com",
|
||||
displayName: "alice",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
cy.clearMail();
|
||||
|
||||
cy.visit("/signup");
|
||||
cy.get('input[type="email"]').type("alice@example.com");
|
||||
cy.get('input[autocomplete="username"]').type("alice2");
|
||||
cy.contains("button", "Continue").click();
|
||||
|
||||
cy.location("pathname").should("eq", "/signup");
|
||||
cy.contains(".error", "email already registered").should("be.visible");
|
||||
});
|
||||
|
||||
it("surfaces a 409 when the display name is taken", function () {
|
||||
cy.seedConfirmedUser({
|
||||
email: "alice@example.com",
|
||||
displayName: "alice",
|
||||
password: "longenoughpassword",
|
||||
});
|
||||
cy.clearMail();
|
||||
|
||||
cy.visit("/signup");
|
||||
cy.get('input[type="email"]').type("other@example.com");
|
||||
cy.get('input[autocomplete="username"]').type("alice");
|
||||
cy.contains("button", "Continue").click();
|
||||
|
||||
cy.location("pathname").should("eq", "/signup");
|
||||
cy.contains(".error", "displayName already taken").should("be.visible");
|
||||
});
|
||||
|
||||
it("blocks invalid display name characters client-side", function () {
|
||||
cy.visit("/signup");
|
||||
cy.get('input[type="email"]').type("alice@example.com");
|
||||
cy.get('input[autocomplete="username"]').type("Has Spaces");
|
||||
cy.contains("button", "Continue").click();
|
||||
|
||||
cy.location("pathname").should("eq", "/signup");
|
||||
cy.get('input[autocomplete="username"]:invalid').should("exist");
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue