Skip to content
Snippets Groups Projects
Commit f941966e authored by Sondre Malerud's avatar Sondre Malerud :coffee:
Browse files

Merge branch 'registrer-profil' into 'main'

Registrer profil

See merge request !7
parents 61808572 d40e98e6
No related branches found
No related tags found
1 merge request!7Registrer profil
Pipeline #220702 passed
describe('Cannot register with wrong fields', () => {
it('passes', () => {
cy.visit('http://localhost:4173/registerAccount')
cy.get('#register-button').trigger('click')
cy.get('#error-message').contains("Vennligst fyll inn alle feltene")
cy.get('#email-input').type('en ugyldig epost')
cy.get('#register-button').trigger('click')
cy.get('#error-message').contains("Vennligst fyll inn alle feltene")
cy.get('#password-input').type('hei')
cy.get('#register-button').trigger('click')
cy.get('#error-message').contains("Vennligst fyll inn alle feltene")
})
})
\ No newline at end of file
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
}, },
"devDependencies": { "devDependencies": {
"@iconify/vue": "^4.1.1", "@iconify/vue": "^4.1.1",
"@pinia/testing": "^0.0.16",
"@vitejs/plugin-vue": "^4.0.0", "@vitejs/plugin-vue": "^4.0.0",
"@vue/test-utils": "^2.2.6", "@vue/test-utils": "^2.2.6",
"cypress": "^12.0.2", "cypress": "^12.0.2",
...@@ -690,6 +691,47 @@ ...@@ -690,6 +691,47 @@
"node": "^12.13.0 || ^14.15.0 || >=16.0.0" "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
} }
}, },
"node_modules/@pinia/testing": {
"version": "0.0.16",
"resolved": "https://registry.npmjs.org/@pinia/testing/-/testing-0.0.16.tgz",
"integrity": "sha512-oa5kO82hzWekqMq1HTnS/b+ZM+ZKEcEApuuCTelvKK79jTxg7P026Qw8/2RbVn5eUGAvRWQu4ubObrshVqCRjQ==",
"dev": true,
"dependencies": {
"vue-demi": "*"
},
"funding": {
"url": "https://github.com/sponsors/posva"
},
"peerDependencies": {
"pinia": ">=2.0.34"
}
},
"node_modules/@pinia/testing/node_modules/vue-demi": {
"version": "0.14.0",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.0.tgz",
"integrity": "sha512-gt58r2ogsNQeVoQ3EhoUAvUsH9xviydl0dWJj7dabBC/2L4uBId7ujtCwDRD0JhkGsV1i0CtfLAeyYKBht9oWg==",
"dev": true,
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/@sideway/address": { "node_modules/@sideway/address": {
"version": "4.1.4", "version": "4.1.4",
"resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz",
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
}, },
"devDependencies": { "devDependencies": {
"@iconify/vue": "^4.1.1", "@iconify/vue": "^4.1.1",
"@pinia/testing": "^0.0.16",
"@vitejs/plugin-vue": "^4.0.0", "@vitejs/plugin-vue": "^4.0.0",
"@vue/test-utils": "^2.2.6", "@vue/test-utils": "^2.2.6",
"cypress": "^12.0.2", "cypress": "^12.0.2",
......
...@@ -2,6 +2,7 @@ import { createRouter, createWebHistory } from 'vue-router' ...@@ -2,6 +2,7 @@ import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue' import HomeView from '../views/HomeView.vue'
import LoginView from '../views/LoginView.vue' import LoginView from '../views/LoginView.vue'
import SelectProfileView from '../views/SelectProfileView.vue' import SelectProfileView from '../views/SelectProfileView.vue'
import RegisterAccountView from '../views/RegisterAccountView.vue'
const router = createRouter({ const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL), history: createWebHistory(import.meta.env.BASE_URL),
...@@ -20,6 +21,11 @@ const router = createRouter({ ...@@ -20,6 +21,11 @@ const router = createRouter({
path: '/selectProfile', path: '/selectProfile',
name: "selectProfile", name: "selectProfile",
component: SelectProfileView component: SelectProfileView
},
{
path: '/registerAccount',
name: 'registerAccount',
component: RegisterAccountView
} }
] ]
}) })
......
...@@ -3,8 +3,9 @@ export const useAuthStore = defineStore("auth", { ...@@ -3,8 +3,9 @@ export const useAuthStore = defineStore("auth", {
state: () => { state: () => {
return { return {
token: "", token: "",
user: {}, account: {},
profile: {}, profile: {},
profiles: []
}; };
}, },
persist: { persist: {
...@@ -19,14 +20,17 @@ export const useAuthStore = defineStore("auth", { ...@@ -19,14 +20,17 @@ export const useAuthStore = defineStore("auth", {
setToken(token) { setToken(token) {
this.token = token; this.token = token;
}, },
setUser(user) { setAccount(account) {
this.user = user; this.account = account;
}, },
logout() { logout() {
this.$reset(); this.$reset();
}, },
setProfile(profile) { setProfile(profile) {
this.profile = profile; this.profile = profile;
},
setProfiles(profiles) {
this.profiles = profiles;
} }
} }
}); });
...@@ -17,6 +17,7 @@ export const API = { ...@@ -17,6 +17,7 @@ export const API = {
login: async (request) => { login: async (request) => {
const authStore = useAuthStore(); const authStore = useAuthStore();
let token; let token;
authStore.logout(); //in case someone for some reason is logged in
return axios.post( return axios.post(
`${import.meta.env.VITE_BACKEND_URL}/login`, `${import.meta.env.VITE_BACKEND_URL}/login`,
...@@ -28,8 +29,11 @@ export const API = { ...@@ -28,8 +29,11 @@ export const API = {
return API.getAccount(id, token) return API.getAccount(id, token)
.then((user) => { .then((user) => {
authStore.setUser(user); authStore.setAccount(user);
authStore.setToken(token); authStore.setToken(token);
API.getProfiles()
.then(response => {authStore.setProfiles(response)})
.catch(() => {throw new Error()})
return; return;
}) })
.catch(() => { .catch(() => {
...@@ -90,17 +94,26 @@ export const API = { ...@@ -90,17 +94,26 @@ export const API = {
throw new Error(); throw new Error();
} }
return axios.get(import.meta.env.VITE_BACKEND_URL + '/profile', { return axios.get(import.meta.env.VITE_BACKEND_URL + '/profile', {
headers: { Authorization: "Bearer " + authStore.token }, headers: { Authorization: "Bearer " + authStore.token },
}, },
) )
.then(response => { .then(response => {
console.log(response.data)
return response.data return response.data
}).catch(() => { }).catch(() => {
throw new Error(); throw new Error();
}); });
},
// Registers a new account and logs into it
addAccount: async (request) => {
const authStore = useAuthStore();
axios.post(import.meta.env.VITE_BACKEND_URL + '/account', request)
.then(() => {
API.login({email: request.email, password: request.password})
.catch(err => {console.log(err)})
})
.catch(() => {throw new Error()})
} }
} }
\ No newline at end of file
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
<div class="login-container"> <div class="login-container">
<img id="logo" src="../components/icons/logo.png" alt="Logo"> <img id="logo" src="../components/icons/logo.png" alt="Logo">
<h1>{{ welcomemsg }}</h1> <h1>{{ welcomemsg }}</h1>
<form @submit.prevent="login"> <form @submit.prevent>
<div class="field-container"> <div class="field-container">
<label for="email">E-post</label> <label for="email">E-post</label>
<input id="email-input" name="email" type="text" v-model="email" /> <input id="email-input" name="email" type="text" v-model="email" />
...@@ -46,12 +46,12 @@ ...@@ -46,12 +46,12 @@
<button @click="login" id="login-button">Logg inn</button> <button @click="login" id="login-button">Logg inn</button>
</form> </form>
<p><RouterLink to="/newuser">Ny bruker</RouterLink> - <a href="#">Glemt passord?</a></p> <p><RouterLink to="/registerAccount">Ny bruker</RouterLink> - <a href="#">Glemt passord?</a></p>
</div> </div>
</main> </main>
</template> </template>
<style lang="scss"> <style lang="scss" scoped>
.login-container { .login-container {
display: flex; display: flex;
......
<template>
<div class="content">
<img id="logo" src="../components/icons/logo.png" alt="Logo">
<h1>Registrer konto</h1>
<form @submit.prevent>
<div class="field-container">
<label for="name">Navn</label>
<input id="input" name="name" type="text" v-model="name" />
</div>
<div class="field-container">
<label for="email">E-post</label>
<input id="email-input" name="email" type="email" v-model="email" />
</div>
<div class="field-container">
<label for="password">Passord</label>
<input id="password-input" name="password" type="password" v-model="password" />
</div>
<p id="error-message">{{ errormsg }}</p>
<button @click="register" id="register-button">Registrer</button>
</form>
</div>
</template>
<script>
import { API } from '@/util/API.js';
import router from '@/router/index.js';
export default {
data() {
return {
email: "",
name: "",
password: "",
errormsg: ""
}
},
methods: {
register() {
if (this.name === "" || this.password === "") {
this.errormsg = "Vennligst fyll inn alle feltene"
}
else {
API.addAccount({firstname: this.name, email: this.email, password: this.password}).then(() => {
router.push("/selectProfile")
})
.catch(() => {
throw new Error()
});
}
}
}
}
</script>
<style scoped>
.content {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
min-width: 300px;
margin-top: 40px;
}
form {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.field-container {
padding: 10px;
display: flex;
flex-direction: column;
}
input {
height: 40px;
font-size: 16px;
padding-left: 10px;
}
label {
font-size: 18px;
}
#register-button {
background-color: #00663C;
color: #FFFFFF;
border-radius: 5px;
border-style: none;
width: 150px;
height: 40px;
font-size: 18px;
font-weight: bold;
margin: 20px;
}
#register-button:hover {
background-color: #04be80;
}
#logo {
width: 100px;
height: 100px;
}
@media (min-width: 1024px) {
.login-container {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
}
}
</style>
\ No newline at end of file
<script> <script>
import { API } from '@/util/API.js'; import { API } from '@/util/API.js';
import { useAuthStore } from "@/stores/authStore.js";
import { mapState } from 'pinia'
export default { export default {
data() { data() {
return { return {
profiles: []
} }
}, },
computed: {
...mapState(useAuthStore, ['profiles'])
},
methods: { methods: {
// Sends the user into the home page logged in as the profile they clicked on // Sends the user into the home page logged in as the profile they clicked on
selectProfile(id) { selectProfile(id) {
...@@ -21,7 +28,6 @@ ...@@ -21,7 +28,6 @@
// Receives all profiles from this user // Receives all profiles from this user
async getProfiles() { async getProfiles() {
await API.getProfiles() await API.getProfiles()
.then(response => {this.profiles = response})
.catch(() => new Error()); .catch(() => new Error());
} }
}, },
...@@ -95,6 +101,7 @@ ...@@ -95,6 +101,7 @@
height: 130px; height: 130px;
width: 130px; width: 130px;
border-radius: 50%; border-radius: 50%;
padding: 10px;
} }
......
...@@ -7,10 +7,11 @@ describe('Login', () => { ...@@ -7,10 +7,11 @@ describe('Login', () => {
it('renders properly', () => { it('renders properly', () => {
const wrapper = mount(LoginView) const wrapper = mount(LoginView)
expect(wrapper.text()).toContain('E-post') expect(wrapper.text()).toContain('E-post')
expect(wrapper.text()).toContain('Passord')
}) })
it('login button exists', () => { it('login button exists', () => {
const wrapper = mount(LoginView) const wrapper = mount(LoginView)
wrapper.find('#login-button').exists() expect(wrapper.find('#login-button').exists()).toBe(true);
}) })
}) })
\ No newline at end of file
import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils'
import RegisterAccountView from '../RegisterAccountView.vue'
describe('Login', () => {
it('renders properly', () => {
const wrapper = mount(RegisterAccountView)
expect(wrapper.text()).toContain('E-post')
expect(wrapper.text()).toContain('Navn')
expect(wrapper.text()).toContain('Passord')
})
it('register button exists', () => {
const wrapper = mount(RegisterAccountView)
expect(wrapper.find('#register-button').exists()).toBe(true)
})
})
\ No newline at end of file
import { describe, it, expect } from 'vitest' import { describe, it, expect, vi } from 'vitest'
import { createTestingPinia } from '@pinia/testing'
import { mount } from '@vue/test-utils' import { mount } from '@vue/test-utils'
import SelectProfileView from '../SelectProfileView.vue' import SelectProfileView from '../SelectProfileView.vue'
describe('Select profile', () => { describe('Select profile', () => {
it('renders properly', () => { it('renders properly', () => {
const wrapper = mount(SelectProfileView) const wrapper = mount(SelectProfileView, {
global: {
plugins: [createTestingPinia({
createSpy: vi.fn,
})],
},
})
expect(wrapper.text()).toContain('Hvem bruker appen?') expect(wrapper.text()).toContain('Hvem bruker appen?')
expect(wrapper.text()).toContain('+') expect(wrapper.text()).toContain('+')
}) })
it('loads with one profile', () => { it('loads with one profile', () => {
const wrapper = mount(SelectProfileView, { const wrapper = mount(SelectProfileView, {
global: {
plugins: [createTestingPinia({
createSpy: vi.fn,
})],
},
data() { data() {
return { return {
profiles: [{ profiles: [{
......
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