diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000000000000000000000000000000000000..a988455b91ce00b0a2286f7a897daa382fc73639 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,8 @@ +version: '3' + +services: + boco-frontend: + build: . + container_name: boco-frontend + ports: + - 8080:8080 \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 31f3a6f043da624d9d3c6de7b4f9106a47b92f80..1ebfe65823ba1a2c3c0b6aef4ec85fc3fdf6b845 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,11 @@ "version": "0.1.0", "dependencies": { "@mdi/font": "5.9.55", +<<<<<<< HEAD +======= "@vuelidate/core": "^2.0.0-alpha.40", "@vuelidate/validators": "^2.0.0-alpha.28", +>>>>>>> main "axios": "^0.26.1", "core-js": "^3.8.3", "cssom": "^0.5.0", diff --git a/package.json b/package.json index 5ee7221e441487e60c51111e7f8105fb7f22f33e..a57e59f54735dbff9626df843f050b4aedb54fe2 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,11 @@ }, "dependencies": { "@mdi/font": "5.9.55", +<<<<<<< HEAD +======= "@vuelidate/core": "^2.0.0-alpha.40", "@vuelidate/validators": "^2.0.0-alpha.28", +>>>>>>> main "axios": "^0.26.1", "core-js": "^3.8.3", "cssom": "^0.5.0", diff --git a/src/components/RegisterFormComponent.vue b/src/components/RegisterFormComponent.vue new file mode 100644 index 0000000000000000000000000000000000000000..b69d38827a90245b00a8c961b4ef816511074bd6 --- /dev/null +++ b/src/components/RegisterFormComponent.vue @@ -0,0 +1,155 @@ +<template> + <v-form ref="form" v-model="valid" lazy-validation> + <v-text-field + v-model="email" + :rules="emailRules" + label="E-mail" + required + ></v-text-field> + + <v-text-field + v-model="password" + :counter="32" + :rules="passwordRules" + label="Passord" + :append-icon="passwordHidden ? 'mdi-eye' : 'mdi-eye-off'" + :type="passwordHidden ? 'text' : 'password'" + @click:append="passwordHidden = !passwordHidden" + required + ></v-text-field> + + <v-container class="grey lighten-5"> + <v-row> + <v-text-field + class="pr-2" + v-model="firstName" + :counter="32" + :rules="firstNameRules" + label="Fornavn" + required + ></v-text-field> + + <v-text-field + class="pl-2" + v-model="lastName" + :counter="32" + :rules="lastNameRules" + label="Etternavn" + required + ></v-text-field> + </v-row> + </v-container> + + <v-text-field + v-model="address" + :counter="32" + :rules="addressRules" + label="Addresse" + required + ></v-text-field> + + <!-- <v-text-field + v-model="confirmPassword" + :rules="confirmPasswordRules" + label="Bekreft passord" + :append-icon="confirmPasswordHidden ? 'mdi-eye' : 'mdi-eye-off'" + :type="confirmPasswordHidden ? 'text' : 'password'" + @click:append="confirmPasswordHidden = !confirmPasswordHidden" + required + ></v-text-field> --> + + <!-- <v-select + v-model="select" + :items="items" + :rules="[(v) => !!v || 'Item is required']" + label="Item" + required + ></v-select> --> + + <!-- <v-checkbox + v-model="checkbox" + :rules="[(v) => !!v || 'You must agree to continue!']" + label="Do you agree?" + required + ></v-checkbox> --> + + <v-btn :disabled="!valid" color="success" class="mr-4" @click="submit()" + >Registrer</v-btn + > + + <v-btn color="error" class="mr-4" @click="reset()">Tøm felter</v-btn> + </v-form> +</template> +<script> +import axios from "axios"; + +export default { + data: () => ({ + passwordHidden: false, + // confirmPasswordHidden: false, + valid: true, + firstName: "", + firstNameRules: [ + (v) => !!v || "Fornavn er påkrevd", + (v) => (v && v.length <= 32) || "Fornavn må være mindre enn 32 bokstaver", + ], + lastName: "", + lastNameRules: [ + (v) => !!v || "Etternavn er påkrevd", + (v) => + (v && v.length <= 32) || "Etternavn må være mindre enn 32 bokstaver", + ], + address: "", + addressRules: [ + (v) => !!v || "Addresse er påkrevd", + (v) => + (v && v.length <= 32) || "Addresse må være mindre enn 32 bokstaver", + ], + password: "", + passwordRules: [ + (v) => !!v || "Passord er påkrevd", + (v) => (v && v.length <= 32) || "Passord må være mindre enn 32 tegn", + (v) => (v && v.length >= 8) || "Passord må være større enn 8 tegn", + ], + // confirmPassword: "", + // confirmPasswordRules: [ + // (v) => !!v || "Passord er påkrevd", + // (v) => (v && v.length <= 32) || "Passord må være mindre enn 32 bokstaver", + // // (v) => v === this.password || "Passordene må være like", + // ], + email: "", + emailRules: [ + (v) => !!v || "E-mail is required", + (v) => /.+@.+\..+/.test(v) || "E-mail must be valid", + ], + // select: null, + // items: ["Item 1", "Item 2", "Item 3", "Item 4"], + // checkbox: false, + }), + + methods: { + submit() { + console.log("Attempting to register user"); + this.valid = this.$refs.form.validate(); + if (!this.valid) return; + this.valid = false; + console.log("User is validated"); + axios + .post("http://localhost:3000/api/register", { + email: this.email, + firstName: this.firstName, + lastname: this.lastName, + password: this.password, + address: this.address, + }) + .then(console.log("Sent")) + .catch((e) => console.log(e)); + }, + reset() { + this.$refs.form.reset(); + this.$refs.form.resetValidation(); + this.valid = true; + }, + }, +}; +</script> diff --git a/src/router/index.js b/src/router/index.js index 499849a932f5d5db6a9389fa270ee7bda4b03771..cf3844a9c1fffdda6bd0fe3375a0057fc7bc7abf 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -18,6 +18,15 @@ const routes = [ component: () => import(/* webpackChunkName: "about" */ "../views/AboutView.vue"), }, + { + path: "/register", + name: "register", + // route level code-splitting + // this generates a separate chunk (register.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => + import(/* webpackChunkName: "register" */ "../views/RegisterView.vue"), + }, { path: "/", name: "login", diff --git a/src/utils/apiutil.js b/src/utils/apiutil.js index 15809ca5993e2d95edf6e771e1eaef3892b35cbb..773bd8d67e484a1f42d371339b5a46ce757a9347 100644 --- a/src/utils/apiutil.js +++ b/src/utils/apiutil.js @@ -2,7 +2,7 @@ import axios from "axios"; export function doLogin(loginRequest) { return axios - .post(`http://localhost:8080/api/login/authentication`, loginRequest) + .post(`http://65.108.62.223:3000/api/login/authentication`, loginRequest) .then((response) => { return response.data; }); diff --git a/src/views/RegisterView.vue b/src/views/RegisterView.vue new file mode 100644 index 0000000000000000000000000000000000000000..9d2ee691f97a923ea3fde5a7d1881792a252b801 --- /dev/null +++ b/src/views/RegisterView.vue @@ -0,0 +1,20 @@ +<template> + <register-form-component id="form" class="pa-8" /> +</template> + +<script> +import RegisterFormComponent from "../components/RegisterFormComponent.vue"; + +export default { + components: { + RegisterFormComponent, + }, +}; +</script> + +<style scoped> +#form { + max-width: 600px; + margin: auto; +} +</style> diff --git a/tests/unit/LoginFormComponentTest.spec.js b/tests/unit/LoginFormComponentTest.spec.js deleted file mode 100644 index 1f892f5e720420f3aae91f6f3716955cd3b7daf2..0000000000000000000000000000000000000000 --- a/tests/unit/LoginFormComponentTest.spec.js +++ /dev/null @@ -1,16 +0,0 @@ -import { shallowMount } from "@vue/test-utils"; -import LoginForm from "@/components/LoginForm"; - -describe("Tests labels in LoginForm component", () => { - it("checks the E-post label", () => { - const wrapper = shallowMount(LoginForm); - - expect(wrapper.find('#emailLabelId').text()).toMatch("E-post"); - }); - - it("checks the password label", () => { - const wrapper = shallowMount(LoginForm); - - expect(wrapper.find('#passwordLabelId').text()).toMatch("Passord"); - }); -}); diff --git a/tests/unit/apiutil-login-mock.spec.js b/tests/unit/apiutil-login-mock.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..4d0764ecff86922419d816522cff259cb9b838cd --- /dev/null +++ b/tests/unit/apiutil-login-mock.spec.js @@ -0,0 +1,37 @@ +import { doLogin } from '@/utils/apiutil' +import axios from 'axios'; + +jest.mock('axios') + +describe('testing mocking of apiutil.js', () => { + it('check that login fails with wrong credentials - against mock', async () => { + + // mock api response on POST call (once) + const expectedLoginResponse = {response: 'Login failed'}; + axios.post.mockImplementation(() => Promise.resolve({data: expectedLoginResponse})); + + // do the call + const loginRequest = {email: "wrong@email.com", password: "thisiswrong123"}; + const loginResponse = await doLogin(loginRequest); + + // check response + // note that even if wrong username and password are used, mock is configured to return Success + expect(loginResponse).toEqual(expectedLoginResponse); + }); + it('check that login succeeds when correct credentials - against mock', async () => { + + // mock api response on POST call (once) + const apiResponse = {response: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'}; + const expectedLoginResponse = {response: 'Login failed'}; + axios.post.mockImplementation(() => Promise.resolve({data: apiResponse})); + + // do the call + const loginRequest = {email: "correct@email.com", password: "thisiscorrect123"}; + const loginResponse = await doLogin(loginRequest); + + // check response + // note that even if wrong username and password are used, mock is configured to return Success + expect(loginResponse).not.toEqual(expectedLoginResponse); + })}) + +