Compare commits

...

7 Commits

Author SHA1 Message Date
Aarni Halinen 8abbca1b41 Install playwright 2023-10-03 20:59:42 +03:00
Aarni Halinen d62ce26759 npm audit fix 2023-10-03 19:30:18 +03:00
Ojakoo faf5269eba set defult value for formSent to disable form hiding in edit view 2023-09-26 14:32:40 +03:00
Ojakoo 9a20cc009d quick fix #42 2023-09-26 13:53:40 +03:00
Tommi S 6891f87447 add new words 2023-08-08 19:44:03 +03:00
Tommi S 17633f3345 Add english page international telegram group link 2023-08-02 22:55:10 +03:00
Tommi S 59e7194cf7 Add english page international telegram group link 2023-08-02 22:52:41 +03:00
25 changed files with 906 additions and 515 deletions
+3
View File
@@ -44,3 +44,6 @@ public/sitemap-0.xml
# Sentry
.sentryclirc
/test-results/
/playwright-report/
/playwright/.cache/
+1 -1
View File
@@ -25,5 +25,5 @@ module.exports = withBundleAnalyzer(withSentryConfig({
},
sentry: {
hideSourceMaps: true, // Hide source maps, see: https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/#configure-source-maps
}
},
}, sentryWebpackPluginOptions));
+690 -494
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -28,12 +28,13 @@
"start-prod": "next start --port ${SERVER_PORT:=80}",
"serve": "next start --port 3000",
"test:unit": "jest --coverage",
"test": "npm run testcafe",
"test": "playwright test",
"testcafe": "testcafe --config-file testcafe.json",
"build-analyze": "ANALYZE=true npm run build",
"prepare": "husky install"
},
"devDependencies": {
"@playwright/test": "^1.38.1",
"@types/jest": "^27.4.1",
"@types/js-cookie": "^3.0.1",
"@types/node": "^16.11.36",
+104
View File
@@ -0,0 +1,104 @@
import { defineConfig, devices } from "@playwright/test";
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: "./tests/playwright",
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: "html",
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: "https://dev.sahkoinsinoorikilta.fi",
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry",
},
/* Configure projects for major browsers */
projects: [
{
name: "event setup",
testMatch: /event-setup\.test\.ts/,
},
{
name: "test teardown",
testMatch: /event-teardown\.test\.ts/,
},
{
name: "tests",
testIgnore: /admin\//,
dependencies: ["event setup"],
teardown: "test teardown",
use: { ...devices["Desktop Chrome"] },
},
{
name: "admin setup",
testMatch: /admin\/setup\.test\.ts/,
},
{
name: "admin tests",
testDir: "/tests/playwright/admin",
testIgnore: /admin\/setup\.test\.ts/,
dependencies: ["admin setup"],
use: { ...devices["Desktop Chrome"] },
},
// {
// name: "chromium",
// use: { ...devices["Desktop Chrome"] },
// },
// {
// name: "firefox",
// use: { ...devices["Desktop Firefox"] },
// },
// {
// name: "webkit",
// use: { ...devices["Desktop Safari"] },
// },
// /* Test against mobile viewports. */
// {
// name: "Mobile Chrome",
// use: { ...devices["Pixel 5"] },
// },
// {
// name: "Mobile Safari",
// use: { ...devices["iPhone 12"] },
// },
// /* Test against branded browsers. */
// {
// name: "Microsoft Edge",
// use: { ...devices["Desktop Edge"], channel: "msedge" },
// },
// {
// name: "Google Chrome",
// use: { ...devices["Desktop Chrome"], channel: "chrome" },
// },
],
/* Run your local dev server before starting the tests */
// webServer: {
// command: 'npm run start',
// url: 'http://127.0.0.1:3000',
// reuseExistingServer: !process.env.CI,
// },
});
+5
View File
@@ -15,6 +15,8 @@
"ja hallitukset kuulumiset": "and what the board has been up to",
"Kuvia tapahtumista": "Photos from events",
"kuvagalleriassa": "in the photo gallery",
"Lisää killan": "Add guild's",
"Google-kalenteri": "Google-calendar",
"Hakemaasi sivua":
"Page",
@@ -51,6 +53,9 @@
"Ilmoittautuminen sulkeutuu":
"Signup closes at",
"Ilmoittautuminen onnistui!":
"Signup successful!",
"Ilmoittauminen on umpeutunut!":
"Signup has been closed!",
+14 -3
View File
@@ -1,11 +1,11 @@
import React from "react";
import React, { useState } from "react";
import { NextPage, GetStaticProps, GetStaticPaths } from "next";
import Head from "next/head";
import { useRouter } from "next/router";
import { ISubmitEvent } from "@rjsf/core";
import { toast } from "react-toastify";
import axios from "axios";
import useSWR, { mutate } from "swr";
import useSWR from "swr";
import { Signup, SignupForm } from "@models/Signup";
import SignupApi from "@api/signupApi";
import SignUpPageView from "@views/SignUpPage/SignUpPageView";
@@ -25,6 +25,8 @@ const SignUpPage: NextPage<InitialProps> = ({ initialForm }) => {
const id = String(initialForm?.id ?? "");
const URL = `${FORM_URL}${id}/`;
const { data: signupForm, error } = useSWR<SignupForm>(URL, (url) => axios.get(url).then((res) => res.data), { fallbackData: initialForm });
const [isSending, setIsSending] = useState(false);
const [formSent, setFormSent] = useState(false);
if (error) {
console.error(error);
@@ -42,18 +44,26 @@ const SignUpPage: NextPage<InitialProps> = ({ initialForm }) => {
}
const onSubmit = async ({ formData }: ISubmitEvent<string>) => {
setIsSending(true);
const payload: Signup = {
signupForm_id: signupForm.id,
answer: formData,
};
if (isSending === true) {
toast.error("Sign-up form already submitted! No need to spam send. 😟");
return;
}
try {
await SignupApi.createSignup(payload);
toast.success("Sign-up submitted successfully 😎");
mutate(URL);
setFormSent(true);
} catch (err) {
console.error(err);
toast.error("Uh oh! Sign-up failed! 😟");
setIsSending(false);
}
};
@@ -68,6 +78,7 @@ const SignUpPage: NextPage<InitialProps> = ({ initialForm }) => {
formData={{}}
onChange={noop}
onSubmit={onSubmit}
formSent={formSent}
/>
</PageWrapper>
</>
@@ -186,6 +186,8 @@ const InEnglishPageView: React.FC<InEnglishPageViewProps> = ({ events, feed }) =
<h3 id="freshmen">For exchange student</h3>
<div>
<div>
<h6>Telegram group 2023-2024</h6>
<p>For starters, we recommend you join the <Link to="https://t.me/+ewiOhvuTXAcwODRk">Telegram-channel</Link> made for new exchange and master&apos;s students.</p>
<h6>Freshman points</h6>
<p>What is student life like in Finland? What are the unique cool things to experience? To find out we recommend collecting the fuksi points (freshman points) to your fuksi point card. It&apos;s fun! The point card gives you a guideline to experiencing the student life and allows you to get a diploma with the privilege to wear the teekkari cap. Note that internationals are also fuksis on their first year in Aalto even though they are not really freshmen. Even Finns who change to a different study program get to be a fuksi again.</p>
<h6>Overalls</h6>
+3 -1
View File
@@ -23,6 +23,7 @@ interface SignUpPageViewProps {
formData: any;
onChange: (e: IChangeEvent<unknown>, es?: ErrorSchema) => unknown;
onSubmit: (e: ISubmitEvent<unknown>) => unknown;
formSent?: boolean;
}
const StyledSection = styled(TextSection)`
@@ -59,6 +60,7 @@ const SignUpPageView: React.FC<SignUpPageViewProps> = ({
formData,
onChange,
onSubmit,
formSent = false,
}) => {
const { i18n, t } = useTranslation();
const startDate = new Date(signUpForm?.start_time);
@@ -136,7 +138,7 @@ const SignUpPageView: React.FC<SignUpPageViewProps> = ({
</h1>
<div>
{form}
{ formSent ? <p>{`${t("Ilmoittautuminen onnistui!")}`}</p> : form }
</div>
{signups}
</StyledSection>
+11
View File
@@ -0,0 +1,11 @@
import { test as setup } from "@playwright/test";
import { generateAccessToken, generateTestEvent, generateTestForm } from "../utils";
setup("create events", async () => {
const token = await generateAccessToken();
const form = await generateTestForm(token);
const event = await generateTestEvent([form.id], token);
process.env.FORM_ID = form.id;
process.env.EVENT_ID = event.id;
});
+10
View File
@@ -0,0 +1,10 @@
import { test as teardown } from "@playwright/test";
import { deleteEvent, deleteForm, generateAccessToken } from "../utils";
teardown("delete events", async () => {
const token = await generateAccessToken();
const { FORM_ID: formId, EVENT_ID: eventId } = process.env;
await deleteEvent(eventId, token);
await deleteForm(formId, token);
});
+24
View File
@@ -0,0 +1,24 @@
import { test, expect } from "@playwright/test";
// import fs from "fs";
// const sitemap = fs.readFileSync("../../public/sitemap-0.xml");
// const pages = sitemap.;
// test("favicon exists", async ({ page }) => {
// await page.goto("/");
// });
// Page
// const pagePath = "/";
test("landing page renders correctly", async ({ page }) => {
await page.goto("/");
await expect(page).toHaveTitle("Aalto-yliopiston Sähköinsinöörikilta ry");
await expect(page).toHaveScreenshot("index-page.png");
});
test("404 page renders correctly", async ({ page }) => {
await page.goto("/404");
await expect(page).toHaveScreenshot("404 page.png");
});
Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

+19
View File
@@ -0,0 +1,19 @@
import {
test, expect,
} from "@playwright/test";
const NAME = "Testi Testeri";
const EMAIL = "e2e@sahkoinsinoorikilta.fi";
test("signup to event", async ({ page }) => {
await page.goto("/");
await page.locator("[id=\"\\#events\"]").getByRole("button", { name: "Lue lisää " }).first().click();
await page.locator("button").filter({ hasText: "Finland flag" }).click();
await page.getByRole("button", { name: "Test" }).click();
await page.getByLabel("Nimi*").fill(NAME);
await page.getByLabel("S-Posti*").fill(EMAIL);
await page.locator("label").filter({ hasText: "Testaaja" }).locator("span").click();
await page.getByRole("button", { name: "Submit" }).click();
// await expect(page.getByText("Sign-up submitted successfully 😎")).toBeVisible();
await expect(page.getByRole("list")).toHaveText(NAME);
});
+1 -1
View File
@@ -1,5 +1,5 @@
import { Selector } from "testcafe";
import { getSiteRoot } from "./utils";
import { getSiteRoot } from "../utils";
fixture`404 page renders and functions correctly`.page(`${getSiteRoot()}/404`);
+1 -1
View File
@@ -1,7 +1,7 @@
import { Selector } from "testcafe";
import {
getSiteRoot, getPageUrl, generateTestForm, deleteEvent, deleteForm, doLogin, generateAccessToken, getPostRequestLogger, waitForLogger,
} from "../utils";
} from "../../utils";
const LOGGER = getPostRequestLogger("events/");
+1 -1
View File
@@ -1,7 +1,7 @@
import { Selector } from "testcafe";
import {
getSiteRoot, getPageUrl, deleteForm, doLogin, generateAccessToken, getPostRequestLogger, waitForLogger
} from "../utils";
} from "../../utils";
const LOGGER = getPostRequestLogger("signupForm/");
+1 -1
View File
@@ -1,5 +1,5 @@
import { Selector, ClientFunction } from "testcafe";
import { getSiteRoot, doLogin } from "../utils";
import { getSiteRoot, doLogin } from "../../utils";
fixture`Admin login page functions correctly`.page(`${getSiteRoot()}/admin/login`);
+1 -1
View File
@@ -1,5 +1,5 @@
import { Selector } from "testcafe";
import { getSiteRoot } from "./utils";
import { getSiteRoot } from "../utils";
fixture`Front page renders and functions correctly`.page(`${getSiteRoot()}`);
+1 -1
View File
@@ -1,7 +1,7 @@
import { Selector } from "testcafe";
import {
getSiteRoot, getPageUrl, generateTestEvent, generateTestForm, deleteEvent, deleteForm, generateAccessToken,
} from "./utils";
} from "../utils";
fixture`Event signup`.page(getSiteRoot())
.before(async (ctx) => {
+8 -6
View File
@@ -156,13 +156,15 @@ export const generateTestEvent = async (formIds = [], jwt_access: string) => (
}, jwt_access)
);
export const sleep = async (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
export const sleep = async (ms: number) => new Promise((resolve) => { setTimeout(resolve, ms); });
export const waitForLogger = async (logger: RequestLogger) => {
for (let i = 0; i < 50; i++) {
await sleep(100);
if (logger.requests.length > 0 ) {
return;
let i = 0;
while (i < 50) {
await sleep(100); // eslint-disable-line no-await-in-loop
if (logger.requests.length > 0) {
return;
}
i += 1;
}
}
};
+4 -3
View File
@@ -58,11 +58,12 @@
"include": [
"./src/**/*",
"./types/**/*",
"./tests/testcafe/**/*",
"./tests/**/*",
".eslintrc.js",
"jest.config.js",
"next-sitemap.config.js",
"next.config.js",
"jest.config.js",
".eslintrc.js",
"playwright.config.ts",
"sentry.client.config.js",
"sentry.server.config.js"
],