Skip to content
Snippets Groups Projects
Commit e3cf2fda authored by Zara Mudassar's avatar Zara Mudassar
Browse files

Merge remote-tracking branch 'origin/main'

parents fb7c148b 401bd0b5
No related branches found
No related tags found
1 merge request!14Create group view
...@@ -4,6 +4,7 @@ node_modules ...@@ -4,6 +4,7 @@ node_modules
# local env files # local env files
.env
.env.local .env.local
.env.*.local .env.*.local
......
This diff is collapsed.
...@@ -10,11 +10,8 @@ ...@@ -10,11 +10,8 @@
}, },
"dependencies": { "dependencies": {
"@mdi/font": "5.9.55", "@mdi/font": "5.9.55",
<<<<<<< HEAD
=======
"@vuelidate/core": "^2.0.0-alpha.40", "@vuelidate/core": "^2.0.0-alpha.40",
"@vuelidate/validators": "^2.0.0-alpha.28", "@vuelidate/validators": "^2.0.0-alpha.28",
>>>>>>> main
"axios": "^0.26.1", "axios": "^0.26.1",
"core-js": "^3.8.3", "core-js": "^3.8.3",
"cssom": "^0.5.0", "cssom": "^0.5.0",
...@@ -22,7 +19,6 @@ ...@@ -22,7 +19,6 @@
"vue": "^3.2.13", "vue": "^3.2.13",
"vue-router": "^4.0.3", "vue-router": "^4.0.3",
"vuelidate": "^0.7.7", "vuelidate": "^0.7.7",
"vuetify": "^3.0.0-beta.0",
"vuex": "^4.0.0", "vuex": "^4.0.0",
"vuex-persistedstate": "^4.1.0", "vuex-persistedstate": "^4.1.0",
"webfontloader": "^1.0.0" "webfontloader": "^1.0.0"
...@@ -38,16 +34,15 @@ ...@@ -38,16 +34,15 @@
"@vue/cli-service": "~5.0.0", "@vue/cli-service": "~5.0.0",
"@vue/test-utils": "^2.0.0-0", "@vue/test-utils": "^2.0.0-0",
"@vue/vue3-jest": "^27.0.0-alpha.1", "@vue/vue3-jest": "^27.0.0-alpha.1",
"autoprefixer": "^10.4.4",
"babel-jest": "^27.0.6", "babel-jest": "^27.0.6",
"eslint": "^7.32.0", "eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-vue": "^8.0.3", "eslint-plugin-vue": "^8.0.3",
"jest": "^27.0.5", "jest": "^27.0.5",
"postcss": "^8.4.12",
"prettier": "^2.4.1", "prettier": "^2.4.1",
"sass": "^1.38.0", "tailwindcss": "^3.0.24"
"sass-loader": "^10.0.0",
"vue-cli-plugin-vuetify": "~2.4.8",
"vuetify-loader": "^2.0.0-alpha.0"
} }
} }
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
<template> <template>
<v-app> <router-view />
<v-main>
<router-view />
</v-main>
</v-app>
</template> </template>
<script>
export default {
name: "App",
data: () => ({
//
}),
};
</script>
<!--suppress HtmlDeprecatedAttribute -->
<template> <template>
<div> <div class="App">
<v-col align="center" justify="space-around" class="mt-16"> <div id="logoField" class="flex justify-center m-6">
<v-img <img src="../assets/logo3.svg" alt="BoCo logo" />
max-width="45%" </div>
:src="require('../assets/logo3.svg')"
align="center" <div
></v-img> id="emailField"
</v-col> class="m-6"
:class="{ error: v$.user.email.$errors.length }"
<v-form ref="form" v-model="valid" lazy-validation> >
<v-col> <div class="mb-6">
<v-text-field <label
v-model="user.email" for="email"
:rules="[rules.email]" class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300"
label="Epost" >E-post</label
>
<input
type="email"
id="email"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="eksempel@eksempel.no"
v-model="v$.user.email.$model"
required required
></v-text-field> />
</v-col> <!-- error message -->
<div v-for="(error, index) of v$.user.email.$errors" :key="index">
<v-col align="right"> <div
<v-text-field class="text-red-600 text-sm"
v-model="user.password" v-show="showError"
:append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'" id="emailErrorId"
:rules="[rules.required, rules.min]" >
:type="showPassword ? 'text' : 'password'" {{ error.$message }}
name="input-10-1" </div>
label="Passord" </div>
counter </div>
@click:append="showPassword = !showPassword" </div>
></v-text-field>
<div
<div class="text-decoration-underline mt-n4 mr-10">Glemt passord</div> id="passwordField"
</v-col> class="m-6"
:class="{ error: v$.user.password.$errors.length }"
<v-col align="center" justify="space-around"> >
<v-btn <label
:disabled="!valid" for="password"
color="success" class="block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300"
class="mb-4 mt-4" >Passord</label
width="50%" >
height="40px" <input
@click="loginClicked" type="password"
id="password"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
v-model="v$.user.password.$model"
required
/>
<!-- error message -->
<div
class="text-red"
v-for="(error, index) of v$.user.password.$errors"
:key="index"
>
<div
class="text-red-600 text-sm"
v-show="showError"
id="passwordErrorId"
> >
Logg inn {{ error.$message }}
</v-btn> </div>
</div>
</div>
<div> <div id="buttonsField" class="m-6">
<a href="/" class="text-decoration-none">Ny bruker</a> <div class="align-items: flex-end; mb-6">
<div class="ml-3 text-sm">
<router-link to="about" class="text-blue-600"
>Glemt passord</router-link
>
</div>
</div>
<button
@click="loginClicked"
class="flex justify-center align-items: flex-end; text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
>
Logg inn
</button>
<div class="flex justify-center align-items: flex-end; mb-6 mt-6">
<div class="ml-3 text-sm">
<router-link to="register" class="text-blue-600"
>Ny bruker</router-link
>
</div> </div>
</v-col> </div>
</v-form> <div class="flex flex-row min-h-screen justify-center items-center">
<label>{{ message }}</label>
</div>
</div>
</div> </div>
</template> </template>
<script> <script>
import useVuelidate from "@vuelidate/core";
import { required, email, helpers } from "@vuelidate/validators";
import { doLogin } from "@/utils/apiutil"; import { doLogin } from "@/utils/apiutil";
import { mapState } from "vuex";
export default { export default {
name: "LoginForm.vue", name: "LoginForm.vue",
computed: mapState({ setup() {
token: (state) => state.user.token, return { v$: useVuelidate() };
}), },
validations() {
return {
user: {
email: {
required,
email: helpers.withMessage(`E-posten er ugyldig`, email),
},
password: {
required,
},
},
};
},
data() { data() {
return { return {
...@@ -73,33 +131,34 @@ export default { ...@@ -73,33 +131,34 @@ export default {
password: "", password: "",
}, },
showPassword: false, showError: false,
valid: true,
rules: {
required: (value) => !!value || "Feltet er påkrevd",
min: (v) => v.length >= 8 || "Minimum 8 tegn",
email: (v) => /.+@.+\..+/.test(v) || "Epost adressen må være gyldig",
},
}; };
}, },
methods: { methods: {
async loginClicked() { async loginClicked() {
console.log(this.user.email + " " + this.user.password); this.showError = true;
this.v$.user.email.$touch();
if (this.v$.user.email.$invalid) {
console.log("Ugyldig, avslutter...");
return;
}
const loginRequest = { const loginRequest = {
email: this.user.email, email: this.user.email,
password: this.user.password, password: this.user.password,
}; };
const loginResponse = await doLogin(loginRequest); const loginResponse = await doLogin(loginRequest);
if (loginResponse === "Failed login") { if (loginResponse.data === "Login failed") {
this.message = "Feil brukernavn/passord"; this.message = "Feil e-post/passord";
this.$store.commit("logout"); this.$store.commit("logout");
return; } else {
this.$store.commit("saveToken", loginResponse);
} }
this.$store.commit("saveToken", loginResponse);
console.log(loginResponse);
}, },
validate() { validate() {
......
@tailwind base;
@tailwind components;
@tailwind utilities;
\ No newline at end of file
...@@ -2,9 +2,6 @@ import { createApp } from "vue"; ...@@ -2,9 +2,6 @@ import { createApp } from "vue";
import App from "./App.vue"; import App from "./App.vue";
import router from "./router"; import router from "./router";
import store from "./store"; import store from "./store";
import vuetify from "./plugins/vuetify"; import "./index.css";
import { loadFonts } from "./plugins/webfontloader";
loadFonts(); createApp(App).use(router).use(store).mount("#app");
createApp(App).use(router).use(store).use(vuetify).mount("#app");
// Styles
import "@mdi/font/css/materialdesignicons.css";
import "vuetify/styles";
// Vuetify
import { createVuetify } from "vuetify";
export default createVuetify();
// https://vuetifyjs.com/en/introduction/why-vuetify/#feature-guides
/**
* plugins/webfontloader.js
*
* webfontloader documentation: https://github.com/typekit/webfontloader
*/
export async function loadFonts() {
const webFontLoader = await import(
/* webpackChunkName: "webfontloader" */ "webfontloader"
);
webFontLoader.load({
google: {
families: ["Roboto:100,300,400,500,700,900&display=swap"],
},
});
}
...@@ -2,8 +2,12 @@ import axios from "axios"; ...@@ -2,8 +2,12 @@ import axios from "axios";
export function doLogin(loginRequest) { export function doLogin(loginRequest) {
return axios return axios
.post(`http://65.108.62.223:3000/api/login/authentication`, loginRequest) .post(process.env.VUE_APP_BASEURL + "login/authentication", loginRequest)
.then((response) => { .then((response) => {
return response.data; return response.data;
})
.catch((error) => {
console.log(error.response);
return error.response;
}); });
} }
module.exports = {
content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
theme: {
extend: {},
},
plugins: [],
};
import { doLogin } from '@/utils/apiutil' import { doLogin } from "@/utils/apiutil";
import axios from 'axios'; import axios from "axios";
jest.mock('axios') jest.mock("axios");
describe('testing mocking of apiutil.js', () => {
it('check that login fails with wrong credentials - against mock', async () => {
describe("testing mocking of apiutil.js", () => {
it("check that login fails with wrong credentials - against mock", async () => {
// mock api response on POST call (once) // mock api response on POST call (once)
const expectedLoginResponse = {response: 'Login failed'}; const expectedLoginResponse = { response: "Login failed" };
axios.post.mockImplementation(() => Promise.resolve({data: expectedLoginResponse})); axios.post.mockImplementation(() =>
Promise.resolve({ data: expectedLoginResponse })
);
// do the call // do the call
const loginRequest = {email: "wrong@email.com", password: "thisiswrong123"}; const loginRequest = {
email: "wrong@email.com",
password: "thisiswrong123",
};
const loginResponse = await doLogin(loginRequest); const loginResponse = await doLogin(loginRequest);
// check response // check response
// note that even if wrong username and password are used, mock is configured to return Success // note that even if wrong username and password are used, mock is configured to return Success
expect(loginResponse).toEqual(expectedLoginResponse); expect(loginResponse).toEqual(expectedLoginResponse);
}); });
it('check that login succeeds when correct credentials - against mock', async () => { it("check that login succeeds when correct credentials - against mock", async () => {
// mock api response on POST call (once) // mock api response on POST call (once)
const apiResponse = {response: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'}; const apiResponse = {
const expectedLoginResponse = {response: 'Login failed'}; response:
axios.post.mockImplementation(() => Promise.resolve({data: apiResponse})); "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
};
const expectedLoginResponse = { response: "Login failed" };
axios.post.mockImplementation(() => Promise.resolve({ data: apiResponse }));
// do the call // do the call
const loginRequest = {email: "correct@email.com", password: "thisiscorrect123"}; const loginRequest = {
email: "correct@email.com",
password: "thisiscorrect123",
};
const loginResponse = await doLogin(loginRequest); const loginResponse = await doLogin(loginRequest);
// check response // check response
// note that even if wrong username and password are used, mock is configured to return Success // note that even if wrong username and password are used, mock is configured to return Success
expect(loginResponse).not.toEqual(expectedLoginResponse); expect(loginResponse).not.toEqual(expectedLoginResponse);
})}) });
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment