Merge branch 'master' into feature/next-js

This commit is contained in:
Aarni Halinen
2021-01-15 00:44:23 +02:00
22 changed files with 3365 additions and 1841 deletions
+4 -7
View File
@@ -1,11 +1,8 @@
/**
* TestCafé test fixtures.
* This file is used by TestCafé to run end-to-end tests with chrome against the site.
* Tests are grouped into fixtures and fixtures into files.
*/
import { Selector } from "testcafe";
fixture`404 page renders and functions correctly`.page("http://localhost:3000/404");
import { Selector } from "testcafe";
import { getSiteRoot } from "./utils";
fixture`404 page renders and functions correctly`.page(`${getSiteRoot()}/404`);
test("Page contains the text 404", async t => {
/**
+88
View File
@@ -0,0 +1,88 @@
import { Selector } from "testcafe";
import { getSiteRoot, getPageUrl, generateTestForm, deleteEvent, deleteForm, doLogin, generateToken, getPostRequestLogger } from "../utils";
const LOGGER = getPostRequestLogger("events/");
fixture`Admin events`.page(`${getSiteRoot()}/admin/events`)
.requestHooks(LOGGER)
.before(async (ctx) => {
const token = await generateToken();
const form = await generateTestForm(token);
ctx.formId = form.id;
})
.after(async (ctx) => {
const token = await generateToken();
const eResp = await deleteEvent(ctx.eventId, token);
await deleteForm(ctx.formId, token);
console.error(eResp);
});
test("Logged in user can create event", async t => {
const loginForm = Selector("form.admin-login-form");
await t.expect(loginForm.exists).ok();
await doLogin(t);
await t.expect(await getPageUrl() === "/admin/events").ok();
const newButton = Selector("[data-e2e=\"create-event\"]");
await t.click(newButton);
await t.expect(await getPageUrl() === "/admin/events/create").ok();
const titleFi = Selector("#rjsf_title_fi");
const titleEn = Selector("#rjsf_title_en");
const descFi = Selector("#rjsf_description_fi");
const descEn = Selector("#rjsf_description_en");
const contentFi = Selector("[data-testid=\"text-area\"]").nth(0);
const contentEn = Selector("[data-testid=\"text-area\"]").nth(1);
const locationFi = Selector("#rjsf_location_fi");
const locationEn = Selector("#rjsf_location_en");
const tagSelect = Selector("#rjsf_tags");
const signupSelect = Selector("#rjsf_signupForm");
// const tagOption = tagSelect.find("option").withExactText("Testi");
// const signupOption = signupSelect.find("option").withExactText("Testi");
// TODO: Testcafe bug https://github.com/DevExpress/testcafe/issues/5339
// https://stackoverflow.com/questions/62932588/unable-to-select-drop-down-list-in-testcafe
// so use keyboard for selection...
await t
.click(tagSelect)
.pressKey("down")
.pressKey("down")
.pressKey("space")
// .pressKey("tab");
// .click(tagOption, { modifiers: { ctrl: true } });
await t
.click(signupSelect)
.pressKey("down")
.pressKey("down")
.pressKey("space")
// .pressKey("tab");
// .click(signupOption, { modifiers: { ctrl: true } });
await t
.typeText(titleFi, "title_fi")
.typeText(descFi, "desc_fi")
.typeText(contentFi, "content_fi")
.typeText(locationFi, "location_fi")
.typeText(titleEn, "title_en")
.typeText(descEn, "desc_en")
.typeText(contentEn, "content_en")
.typeText(locationEn, "location_en");
const submit = Selector("button[type=\"submit\"]");
await t.click(submit);
const parsed = JSON.parse(LOGGER.requests[0].response.body);
t.fixtureCtx.eventId = parsed.id;
const statusMessage = Selector("[data-e2e=\"admin-form-status-message\"]");
await t
.hover(statusMessage)
.expect(
statusMessage.innerText
).eql("Event created successfully");
})
@@ -0,0 +1,90 @@
import { Selector } from "testcafe";
import { getSiteRoot, getPageUrl, deleteForm, doLogin, generateToken, getPostRequestLogger } from "../utils";
const LOGGER = getPostRequestLogger("signupForm/");
fixture`Admin signup form`.page(`${getSiteRoot()}/admin/signups`)
.requestHooks(LOGGER)
.after(async (ctx) => {
const token = await generateToken();
await deleteForm(ctx.formId, token);
});
test("Logged in user can create signup", async t => {
const loginForm = Selector("form.admin-login-form");
await t.expect(loginForm.exists).ok();
await doLogin(t);
await t.expect(await getPageUrl() === "/admin/signups").ok();
const newButton = Selector("[data-e2e=\"create-signup\"]");
await t.click(newButton);
await t.expect(await getPageUrl() === "/admin/signups/create").ok();
const titleFi = Selector("#rjsf_title_fi");
const titleEn = Selector("#rjsf_title_en");
const visible = Selector("#rjsf_visible");
await t
.typeText(titleFi, "Testi Ilmo")
.typeText(titleEn, "Test Signup")
.click(visible);
const newQuestionButton = Selector("[data-e2e=\"admin-signup-new-question\"]");
const lastQuestion = () => Selector("[data-e2e=\"admin-signup-question\"]").child("div").child("div").nth(-1);
await t.click(newQuestionButton);
let question = lastQuestion();
let questionName = question.child("input");
let questionTypeSelect = question.child("select");
let requiredBox = question.child("label")
await t
.selectText(questionName)
.pressKey("delete")
.typeText(questionName, "Nimi")
.click(questionTypeSelect)
.click(questionTypeSelect.find("option").withExactText("name"))
.click(requiredBox);
await t.click(newQuestionButton);
question = lastQuestion();
questionName = question.child("input");
questionTypeSelect = question.child("select");
requiredBox = question.child("label");
await t
.selectText(questionName)
.pressKey("delete")
.typeText(questionName, "S-Posti")
.click(questionTypeSelect)
.click(questionTypeSelect.find("option").withExactText("email"))
.click(requiredBox);
await t.click(newQuestionButton);
question = lastQuestion();
questionName = question.child("input");
questionTypeSelect = question.child("select");
const radioOptions = question.child("input").nth(-1);
await t
.selectText(questionName)
.pressKey("delete")
.typeText(questionName, "Olen")
.click(questionTypeSelect)
.click(questionTypeSelect.find("option").withExactText("radiobutton"))
.typeText(radioOptions, "Nuori,Vanha,Testaaja");
const submit = Selector("button[type=\"submit\"]");
await t.click(submit);
const parsed = JSON.parse(LOGGER.requests[0].response.body);
t.fixtureCtx.formId = parsed.id;
const statusMessage = Selector("[data-e2e=\"admin-form-status-message\"]");
await t
.hover(statusMessage)
.expect(
statusMessage.innerText
).eql("Sign-up created successfully");
})
@@ -1,11 +1,7 @@
/**
* TestCafé test fixtures.
* This file is used by TestCafé to run end-to-end tests with chrome against the site.
* Tests are grouped into fixtures and fixtures into files.
*/
import { Selector, ClientFunction } from "testcafe";
import { getSiteRoot, doLogin } from "../utils";
fixture`Admin login page functions correctly`.page("http://localhost:3000/admin/login");
fixture`Admin login page functions correctly`.page(`${getSiteRoot()}/admin/login`);
test("Login form exists", async t => {
/**
@@ -19,14 +15,9 @@ test("User can log in with default credentials", async t => {
/**
* Test if the user can log in with default credentials.
*/
const USERNAME = "admin";
const PASSWORD = "password123";
await doLogin(t);
await t.typeText(Selector("#login-username"), USERNAME);
await t.typeText(Selector("#login-password"), PASSWORD);
await t.click(Selector("#login-submit"));
const frontPage = Selector(`[data-e2e="admin-front-page"]`);
const frontPage = Selector("[data-e2e=\"admin-front-page\"]");
await t.expect(frontPage.exists).ok();
});
@@ -43,7 +34,7 @@ test("User can log out and is redirected to login", async t => {
await t.expect(loginForm.exists).ok();
});
test.skip("User is redirected to login when JWT token is invalid", async t => {
test("User is redirected to login when JWT token is invalid", async t => {
/**
* Test if the user is redirected to login when JWT token is invalid.
*/
+3 -7
View File
@@ -1,11 +1,7 @@
/**
* TestCafé test fixtures.
* This file is used by TestCafé to run end-to-end tests with chrome against the site.
* Tests are grouped into fixtures and fixtures into files.
*/
import { Selector } from "testcafe";
import { getSiteRoot } from "./utils";
fixture`Front page renders and functions correctly`.page("http://localhost:3000");
fixture`Front page renders and functions correctly`.page(`${getSiteRoot()}`);
test("Favicon exists", async t => {
/**
@@ -21,5 +17,5 @@ test("Header contains text \"Aalto-yliopiston Sähköinsinöörikilta\"", async
*/
const header = Selector("h1");
await t.expect(header.textContent)
.contains("Aalto-yliopiston Sähköinsinöörikilta");
.contains("Aalto-yliopiston Sähköinsinöörikilta");
});
+51
View File
@@ -0,0 +1,51 @@
import { Selector } from "testcafe";
import { getSiteRoot, getPageUrl, generateTestEvent, generateTestForm, deleteEvent, deleteForm, generateToken } from "./utils";
fixture`Event signup`.page(getSiteRoot())
.before(async (ctx) => {
const token = await generateToken();
const form = await generateTestForm(token);
const event = await generateTestEvent([form.id], token);
ctx.eventId = event.id;
ctx.formId = form.id;
})
.after(async (ctx) => {
const token = await generateToken();
await deleteEvent(ctx.eventId, token);
await deleteForm(ctx.formId, token);
});
test("User signups to event from front page", async t => {
const CardSelector = Selector("[data-e2e=\"event-card\"]").withText("title_fi").nth(0);
await t
.click(CardSelector.child("a"));
let url = await getPageUrl();
await t.expect(url).match(/\/events\/\d{1,4}/, "URL isn't /events/<id>");
const SignupButton = Selector("button");
await t
.click(SignupButton);
url = await getPageUrl();
await t.expect(url).match(/\/signup\/\d{1,4}/, "URL isn't /signup/<id>");
const nameField = Selector("input").nth(0);
const emailField = Selector("input").nth(1);
const typeField = Selector("fieldset").child(-1).child("div").child("div").child("label").nth(-1);
await t
.typeText(nameField, "Testi Testeri")
.typeText(emailField, "e2e@sahkoinsinoorikilta.fi")
.click(typeField);
await t.click(Selector("button").nth(-1));
const statusMessage = Selector(".sign-up-statusmessage");
await t
.hover(statusMessage)
.expect(
statusMessage.innerText
).eql("Sign-up submitted successfully");
});
+137
View File
@@ -0,0 +1,137 @@
import { Selector, ClientFunction, RequestLogger } from "testcafe";
import axios from "axios";
const API_URL = "https://api.dev.sik.party/api"
export const getSiteRoot = (): string => process.env.SITE_URL || "http://localhost:3000";
// export const getPageUrl = ClientFunction(() => window.location.href.toString());
export const getPageUrl = ClientFunction(() => window.location.pathname);
export const getPostRequestLogger = (url: string) => RequestLogger({ url: `${API_URL}/${url}`, method: "post" }, {
// logResponseHeaders: true,
logResponseBody: true,
stringifyResponseBody: true
});
const openTime = new Date("1994-01-14T22:51:00+02:00");
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
const USERNAME = "admin";
const PASSWORD = "password123";
export const doLogin = async (t: TestController) => {
await t.typeText(Selector("#login-username"), USERNAME);
await t.typeText(Selector("#login-password"), PASSWORD);
await t.click(Selector("#login-submit"));
}
export async function generateToken(): Promise<string> {
const tokenUrl = `${API_URL}/api-token-auth/`;
try {
const resp = await axios.post(tokenUrl, {
username: USERNAME,
password: PASSWORD
});
return resp.data["token"];
} catch (err) {
console.error(err);
throw err;
}
}
export const generateTestForm = async (jwt: string) => (
await createForm({
"title_fi": "Testi Ilmo",
"title_en": "Test Signup",
"visible": true,
"quota": 0,
"start_time": openTime,
"end_time": tomorrow,
"email_content": "E2E Test",
"questions": [{ "id": "XS_Ox5Rry", "name": "Nimi", "type": "name", "options": [], "required": true }, { "id": "Ve02XSEEx", "name": "S-Posti", "type": "email", "options": [], "required": true }, { "id": "luMqnz5y9", "name": "Olen", "type": "radiobutton", "options": ["Nuori", "Vanha", "Testaaja"] }], "id": 14, "isOpen": true, "schema": { "type": "object", "required": ["XS_Ox5Rry", "Ve02XSEEx"], "properties": { "XS_Ox5Rry": { "type": "string", "title": "Nimi" }, "Ve02XSEEx": { "type": ["string"], "title": "S-Posti", "format": "email", "pattern": "^[a-zA-Z0-9.!#$%&*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*$", "default": null }, "luMqnz5y9": { "type": "string", "title": "Olen", "pattern": "^Nuori$|^Vanha$|^Testaaja$", "enum": ["Nuori", "Vanha", "Testaaja"] } } }
}, jwt)
)
const formURL = `${API_URL}/signupForm/`;
export async function createForm(data, jwt: string) {
try {
const resp = await axios.post(formURL, data, {
headers: {
"Authorization": `JWT ${jwt}`,
},
});
return resp.data;
} catch (err) {
console.error(err);
throw err;
}
}
export async function deleteForm(id: string, jwt: string) {
try {
const resp = await axios.delete(`${formURL}${id}/`, {
headers: {
"Authorization": `JWT ${jwt}`
},
});
return resp.data;
} catch (err) {
console.error(err);
throw err;
}
}
export const generateTestEvent = async (formIds = [], jwt: string) => (
await createEvent({
"tags":[1],
"visible":true,
"start_time": openTime,
"end_time": tomorrow,
"title_fi":"title_fi",
"description_fi":"desc_fi",
"content_fi":"content_fi",
"location_fi":"location_fi",
"title_en":"title_en",
"description_en":"desc_en",
"content_en":"content_en",
"location_en":"location_en",
"image":null,
"signupForm": formIds,
"signup_id": formIds,
"tag_id":[1]
}, jwt)
)
const eventURL = `${API_URL}/events/`;
export async function createEvent(data, jwt: string) {
try {
const resp = await axios.post(eventURL, data, {
headers: {
"Authorization": `JWT ${jwt}`,
},
});
return resp.data;
} catch (err) {
console.error(err);
throw err;
}
}
export async function deleteEvent(id: string, jwt: string) {
try {
const resp = await axios.delete(`${eventURL}${id}/`, {
headers: {
"Authorization": `JWT ${jwt}`
},
});
return resp.data;
} catch (err) {
console.error(err);
throw err;
}
}