Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Comments timestamp download infinite loop #2608

Merged
merged 2 commits into from
Sep 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ yalc.lock
.idea

cypress/videos
cypress/screenshots
cypress/screenshots
teste2e/cypress/downloads
5 changes: 4 additions & 1 deletion src/containers/Comments/Download/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ export function useDownloadCommentsTimestamps(recordToken) {
[recordToken]
);
const allCommentsBySection = useSelector(commentsSelector);
const comments = Object.values(allCommentsBySection).flat();
const comments = useMemo(
() => Object.values(allCommentsBySection).flat(),
[allCommentsBySection]
);
const commentsLength = comments?.length || 0;
const multiPage = commentsLength > TIMESTAMPS_PAGE_SIZE;
const onFetchCommentsTimestamps = useAction(act.onFetchCommentsTimestamps);
Expand Down
66 changes: 60 additions & 6 deletions teste2e/cypress/e2e/comments/comments.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { buildProposal, buildComment } from "../../support/generate";
import { shortRecordToken } from "../../utils";
import { shortRecordToken, getFirstShortProposalToken } from "../../utils";
import path from "path";

describe("User comments", () => {
it("Can not comment if hasn't paid the paywall", () => {
it("Shouldn't allow submitting new comments if paywall not paid", () => {
cy.server();
// create proposal
const user = {
Expand Down Expand Up @@ -37,8 +38,7 @@ describe("User comments", () => {
}
);
});

it("Can comment, vote and reply on others' comments if paid the paywall", () => {
it("Should allow user who paid the paywall to add new comments & vote or reply on others' comments", () => {
cy.server();
// create proposal
const user = {
Expand Down Expand Up @@ -95,8 +95,62 @@ describe("User comments", () => {
);
});
});

describe("Failed comments", () => {
describe.only("Comments downloads", () => {
let shortToken = "";
beforeEach(() => {
cy.server();
cy.intercept("/api/records/v1/records").as("records");
cy.intercept("/api/records/v1/details").as("details");
cy.visit("/");
cy.wait("@records").then(({ response: { body } }) => {
const { records } = body;
shortToken = getFirstShortProposalToken(records);
expect(shortToken, "You should have at least one record Under Review.").to
.exist;
// login paid user
const user1 = {
email: "user1@example.com",
username: "user1",
password: "password"
};
cy.login(user1);
cy.identity();
cy.visit(`record/${shortToken}`);
const { text } = buildComment();
cy.findByTestId(/text-area/i).type(text);
cy.route("POST", "/api/comments/v1/new").as("newComment");
cy.findByText(/add comment/i).click();
cy.wait("@newComment").its("status").should("eq", 200);
cy.intercept("/api/comments/v1/comments").as("comments");
cy.intercept("/api/comments/v1/votes").as("votes");
});
});
it("should publicly allow users to download comments bundle", () => {
cy.visit(`/record/${shortToken}`);
cy.wait("@details");
cy.wait("@comments");
cy.wait("@votes");
cy.findByTestId("record-links").click();
cy.findByText(/comments bundle/i).click();
const downloadsFolder = Cypress.config("downloadsFolder");
cy.readFile(
path.join(downloadsFolder, `${shortToken}-comments.json`)
).should("exist");
});
it("should publicly allow users to download comments timestamps", () => {
cy.visit(`/record/${shortToken}`);
cy.wait("@details");
cy.wait("@comments");
cy.wait("@votes");
cy.findByTestId("record-links").click();
cy.findByText(/comments timestamps/i).click();
const downloadsFolder = Cypress.config("downloadsFolder");
cy.readFile(
path.join(downloadsFolder, `${shortToken}-comments-timestamps.json`)
).should("exist");
});
});
describe("Comments error handling", () => {
let token = "";
beforeEach(() => {
const user = {
Expand Down
74 changes: 41 additions & 33 deletions teste2e/cypress/e2e/proposal/detail.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,5 @@
import {
PROPOSAL_METADATA_FILENAME,
VOTE_METADATA_FILENAME
} from "../../utils";
import compose from "lodash/fp/compose";
import filter from "lodash/fp/filter";
import keys from "lodash/fp/keys";
import first from "lodash/fp/first";
import get from "lodash/fp/get";
import find from "lodash/fp/find";

function findRecordFileByName(record, name) {
return compose(
find((file) => file.name === name),
get("files")
)(record);
}

function getShortProposalToken(records = {}) {
return compose(
first,
filter(
(token) =>
!findRecordFileByName(records[token], VOTE_METADATA_FILENAME) &&
findRecordFileByName(records[token], PROPOSAL_METADATA_FILENAME)
),
keys
)(records);
}
import { getFirstShortProposalToken } from "../../utils";
import path from "path";

describe("Record Details", () => {
describe("proposal details", () => {
Expand All @@ -40,19 +13,19 @@ describe("Record Details", () => {
cy.visit("/");
cy.wait("@records").then(({ response: { body } }) => {
const { records } = body;
shortToken = getShortProposalToken(records);
shortToken = getFirstShortProposalToken(records);
token = records[shortToken].censorshiprecord.token;
expect(
shortToken,
"You should have at least one record Under Review."
).to.exist;
});
});
it("can render proposal correctly by short token", () => {
it("should render a propsoal with a short token", () => {
cy.visit(`/record/${shortToken}`);
cy.wait("@details");
});
it("can render proposal correctly by full token", () => {
it("should render a proposal with a full token", () => {
cy.visit(`/record/${token}`);
cy.wait("@details");
});
Expand All @@ -77,6 +50,41 @@ describe("Record Details", () => {
.and("include.text", "End Date");
});
});
describe("proposal downloads", () => {
beforeEach(() => {
cy.visit("/");
cy.wait("@records").then(({ response: { body } }) => {
const { records } = body;
shortToken = getFirstShortProposalToken(records);
token = records[shortToken].censorshiprecord.token;
expect(
shortToken,
"You should have at least one record Under Review."
).to.exist;
});
});
it("should publicly allow to download proposal bundle", () => {
cy.visit(`/record/${shortToken}`);
cy.wait("@details");
cy.findByTestId("record-links").click();
cy.findByText(/proposal bundle/i).click();
const downloadsFolder = Cypress.config("downloadsFolder");
cy.readFile(path.join(downloadsFolder, `${shortToken}-v1.json`)).should(
"exist"
);
});
it("should publicly allow to download proposal timestamps", () => {
cy.visit(`/record/${shortToken}`);
cy.wait("@details");
cy.findByTestId("record-links").click();
cy.findByText(/proposal timestamps/i).click();
const config = Cypress.config();
const downloadsFolder = Cypress.config("downloadsFolder");
cy.readFile(
path.join(downloadsFolder, `${shortToken}-v1-timestamps.json`)
).should("exist");
});
});
describe("invalid proposal rendering", () => {
it("should dislpay not found message for nonexistent proposals", () => {
cy.visit("/record/invalidtoken");
Expand All @@ -94,7 +102,7 @@ describe("Record Details", () => {
cy.visit("/admin/records");
cy.wait("@records").then(({ response: { body } }) => {
const { records } = body;
shortToken = getShortProposalToken(records);
shortToken = getFirstShortProposalToken(records);
expect(shortToken, "You should have at least one unvetted record.").to
.exist;
});
Expand Down
25 changes: 24 additions & 1 deletion teste2e/cypress/utils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import CryptoJS from "crypto-js";
import get from "lodash/fp/get";
import * as pki from "./pki";
import MerkleTree from "./merkle";
import compose from "lodash/fp/compose";
import filter from "lodash/fp/filter";
import keys from "lodash/fp/keys";
import first from "lodash/fp/first";
import get from "lodash/fp/get";
import find from "lodash/fp/find";
import path from "path";

const PROPOSAL_TYPE_REGULAR = 1;
const PROPOSAL_TYPE_RFP = 2;
Expand Down Expand Up @@ -32,6 +38,23 @@ const PROPOSAL_STATUS_PUBLIC = 2;
const PROPOSAL_STATUS_CENSORED = 3;
const PROPOSAL_STATUS_ARCHIVED = 4;

const findRecordFileByName = (record, name) =>
compose(
find((file) => file.name === name),
get("files")
)(record);

export const getFirstShortProposalToken = (records = {}) =>
compose(
first,
filter(
(token) =>
!findRecordFileByName(records[token], VOTE_METADATA_FILENAME) &&
findRecordFileByName(records[token], PROPOSAL_METADATA_FILENAME)
),
keys
)(records);

export const requestWithCsrfToken = (url, body, failOnStatusCode = true) =>
cy.request("/api").then((res) =>
cy.request({
Expand Down