mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
Merge branch 'master' into i18n-pluralization
This commit is contained in:
commit
9de15879f3
@ -44,6 +44,19 @@ const logout = () => {
|
||||
cy.location('pathname').should('contain', '/login') // we're out
|
||||
}
|
||||
|
||||
const lastColumnIsSortedInDescendingOrder = () => {
|
||||
cy.get('tbody')
|
||||
.find('tr td:last-child')
|
||||
.then(last_column => {
|
||||
cy.wrap(last_column)
|
||||
const values = last_column
|
||||
.map((i, td) => parseInt(td.textContent))
|
||||
.toArray()
|
||||
const ordered_descending = values.slice(0).sort((a, b) => b - a)
|
||||
return cy.wrap(values).should('deep.eq', ordered_descending)
|
||||
})
|
||||
}
|
||||
|
||||
Given('I am logged in', () => {
|
||||
login('admin@example.org', 1234)
|
||||
})
|
||||
@ -52,11 +65,11 @@ Given('we have a selection of tags and categories as well as posts', () => {
|
||||
// TODO: use db factories instead of seed data
|
||||
})
|
||||
|
||||
Given('my account has the following details:', (table) => {
|
||||
Given('my account has the following details:', table => {
|
||||
// TODO: use db factories instead of seed data
|
||||
})
|
||||
|
||||
Given('my user account has the role {string}', (role) => {
|
||||
Given('my user account has the role {string}', role => {
|
||||
// TODO: use db factories instead of seed data
|
||||
})
|
||||
|
||||
@ -127,28 +140,22 @@ When('I navigate to the administration dashboard', () => {
|
||||
.click()
|
||||
})
|
||||
|
||||
When('I click on {string}', linkOrButton => {
|
||||
When(`I click on {string}`, linkOrButton => {
|
||||
cy.contains(linkOrButton).click()
|
||||
})
|
||||
|
||||
Then('I can see a list of categories ordered by post count:', table => {
|
||||
// TODO: match the table in the feature with the html table
|
||||
cy.get('thead').find('tr th').should('have.length', 3)
|
||||
const last_column = cy.get('tbody').find('tr td:last-child').then((last_column) => {
|
||||
cy.wrap(last_column)
|
||||
const values = last_column.map((i, td) => parseInt(td.textContent)).toArray()
|
||||
const ordered_descending = values.slice(0).sort((a,b) => b - a)
|
||||
return cy.wrap(values).should('deep.eq', ordered_descending)
|
||||
})
|
||||
cy.get('thead')
|
||||
.find('tr th')
|
||||
.should('have.length', 3)
|
||||
lastColumnIsSortedInDescendingOrder()
|
||||
})
|
||||
|
||||
Then('I can see a list of tags ordered by user and post count:', table => {
|
||||
// TODO: match the table in the feature with the html table
|
||||
cy.get('thead').find('tr th').should('have.length', 4)
|
||||
const last_column = cy.get('tbody').find('tr td:last-child').then((last_column) => {
|
||||
cy.wrap(last_column)
|
||||
const values = last_column.map((i, td) => parseInt(td.textContent)).toArray()
|
||||
const ordered_descending = values.slice(0).sort((a,b) => b - a)
|
||||
return cy.wrap(values).should('deep.eq', ordered_descending)
|
||||
})
|
||||
cy.get('thead')
|
||||
.find('tr th')
|
||||
.should('have.length', 4)
|
||||
lastColumnIsSortedInDescendingOrder()
|
||||
})
|
||||
|
||||
10
package.json
10
package.json
@ -54,20 +54,20 @@
|
||||
"v-tooltip": "^2.0.0-rc.33",
|
||||
"vue-count-to": "^1.0.13",
|
||||
"vue-izitoast": "1.1.2",
|
||||
"vuex-i18n": "^1.10.5"
|
||||
"vuex-i18n": "^1.10.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/eslint-config-prettier": "^4.0.1",
|
||||
"@vue/server-test-utils": "^1.0.0-beta.27",
|
||||
"@vue/test-utils": "^1.0.0-beta.27",
|
||||
"@vue/server-test-utils": "^1.0.0-beta.28",
|
||||
"@vue/test-utils": "^1.0.0-beta.28",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"babel-jest": "^23.6.0",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"cypress-cucumber-preprocessor": "^1.9.1",
|
||||
"eslint": "^5.10.0",
|
||||
"eslint": "^5.11.1",
|
||||
"eslint-config-prettier": "^3.1.0",
|
||||
"eslint-loader": "^2.0.0",
|
||||
"eslint-plugin-prettier": "3.0.0",
|
||||
"eslint-plugin-prettier": "3.0.1",
|
||||
"eslint-plugin-vue": "^5.0.0",
|
||||
"jest": "^23.6.0",
|
||||
"node-sass": "^4.11.0",
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 220 KiB After Width: | Height: | Size: 130 KiB |
@ -13,11 +13,6 @@ export const mutations = {
|
||||
SET_USER(state, user) {
|
||||
state.user = user || null
|
||||
},
|
||||
SET_USER_SETTINGS(state, userSettings) {
|
||||
// state.user = Object.assign(state.user, {
|
||||
// userSettings: Object.assign(this.getters['auth/userSettings'], userSettings)
|
||||
// })
|
||||
},
|
||||
SET_TOKEN(state, token) {
|
||||
state.token = token || null
|
||||
},
|
||||
@ -27,15 +22,15 @@ export const mutations = {
|
||||
}
|
||||
|
||||
export const getters = {
|
||||
isAuthenticated(state) {
|
||||
return !!state.token
|
||||
},
|
||||
isLoggedIn(state) {
|
||||
return !!(state.user && state.token)
|
||||
},
|
||||
pending(state) {
|
||||
return !!state.pending
|
||||
},
|
||||
isVerified(state) {
|
||||
return !!state.user && state.user.isVerified && !!state.user.name
|
||||
},
|
||||
isAdmin(state) {
|
||||
return !!state.user && state.user.role === 'admin'
|
||||
},
|
||||
@ -51,20 +46,6 @@ export const getters = {
|
||||
token(state) {
|
||||
return state.token
|
||||
}
|
||||
// userSettings(state, getters, rootState, rootGetters) {
|
||||
// const userSettings = (state.user && state.user.userSettings) ? state.user.userSettings : {}
|
||||
//
|
||||
// const defaultLanguage = (state.user && state.user.language) ? state.user.language : rootGetters['i18n/locale']
|
||||
// let contentLanguages = !isEmpty(userSettings.contentLanguages) ? userSettings.contentLanguages : []
|
||||
// if (isEmpty(contentLanguages)) {
|
||||
// contentLanguages = userSettings.uiLanguage ? [userSettings.uiLanguage] : [defaultLanguage]
|
||||
// }
|
||||
//
|
||||
// return Object.assign({
|
||||
// uiLanguage: defaultLanguage,
|
||||
// contentLanguages: contentLanguages
|
||||
// }, userSettings)
|
||||
// }
|
||||
}
|
||||
|
||||
export const actions = {
|
||||
@ -97,10 +78,8 @@ export const actions = {
|
||||
return getters.isLoggedIn
|
||||
},
|
||||
async login({ commit }, { email, password }) {
|
||||
commit('SET_PENDING', true)
|
||||
try {
|
||||
commit('SET_PENDING', true)
|
||||
commit('SET_USER', null)
|
||||
commit('SET_TOKEN', null)
|
||||
const res = await this.app.apolloProvider.defaultClient
|
||||
.mutate({
|
||||
mutation: gql(`
|
||||
@ -120,22 +99,15 @@ export const actions = {
|
||||
})
|
||||
.then(({ data }) => data && data.login)
|
||||
|
||||
if (res && res.token) {
|
||||
await this.app.$apolloHelpers.onLogin(res.token)
|
||||
commit('SET_TOKEN', res.token)
|
||||
delete res.token
|
||||
commit('SET_USER', res)
|
||||
commit('SET_PENDING', false)
|
||||
return true
|
||||
} else {
|
||||
commit('SET_PENDING', false)
|
||||
throw new Error('THERE IS AN ERROR')
|
||||
}
|
||||
await this.app.$apolloHelpers.onLogin(res.token)
|
||||
commit('SET_TOKEN', res.token)
|
||||
const userData = Object.assign({}, res)
|
||||
delete userData.token
|
||||
commit('SET_USER', userData)
|
||||
} catch (err) {
|
||||
commit('SET_USER', null)
|
||||
commit('SET_TOKEN', null)
|
||||
commit('SET_PENDING', false)
|
||||
throw new Error(err)
|
||||
} finally {
|
||||
commit('SET_PENDING', false)
|
||||
}
|
||||
},
|
||||
async logout({ commit }) {
|
||||
|
||||
160
store/auth.test.js
Normal file
160
store/auth.test.js
Normal file
@ -0,0 +1,160 @@
|
||||
import { getters, mutations, actions } from './auth.js'
|
||||
|
||||
let state
|
||||
let commit
|
||||
|
||||
const token =
|
||||
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6InUzIiwic2x1ZyI6Implbm55LXJvc3RvY2siLCJuYW1lIjoiSmVubnkgUm9zdG9jayIsImF2YXRhciI6Imh0dHBzOi8vczMuYW1hem9uYXdzLmNvbS91aWZhY2VzL2ZhY2VzL3R3aXR0ZXIvbXV0dV9rcmlzaC8xMjguanBnIiwiZW1haWwiOiJ1c2VyQGV4YW1wbGUub3JnIiwicm9sZSI6InVzZXIiLCJpYXQiOjE1NDUxNDQ2ODgsImV4cCI6MTYzMTU0NDY4OCwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo0MDAwIiwic3ViIjoidTMifQ.s5_JeQN9TaUPfymAXPOpbMAwhmTIg9cnOvNEcj4z75k'
|
||||
const successfulLoginResponse = {
|
||||
data: {
|
||||
login: {
|
||||
id: 'u3',
|
||||
name: 'Jenny Rostock',
|
||||
slug: 'jenny-rostock',
|
||||
email: 'user@example.org',
|
||||
avatar:
|
||||
'https://s3.amazonaws.com/uifaces/faces/twitter/mutu_krish/128.jpg',
|
||||
role: 'user',
|
||||
token
|
||||
}
|
||||
}
|
||||
}
|
||||
const incorrectPasswordResponse = {
|
||||
data: {
|
||||
login: null
|
||||
},
|
||||
errors: [
|
||||
{
|
||||
message: 'Incorrect password.',
|
||||
locations: [
|
||||
{
|
||||
line: 2,
|
||||
column: 3
|
||||
}
|
||||
],
|
||||
path: ['login']
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
commit = jest.fn()
|
||||
})
|
||||
|
||||
describe('getters', () => {
|
||||
describe('isAuthenticated', () => {
|
||||
describe('given JWT Bearer token', () => {
|
||||
test('true', () => {
|
||||
state = { token }
|
||||
expect(getters.isAuthenticated(state)).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('actions', () => {
|
||||
let action
|
||||
|
||||
describe('login', () => {
|
||||
describe('given valid credentials and a successful response', () => {
|
||||
beforeEach(async () => {
|
||||
const response = Object.assign({}, successfulLoginResponse)
|
||||
const mutate = jest.fn(() => Promise.resolve(response))
|
||||
const onLogin = jest.fn(() => Promise.resolve())
|
||||
const module = {
|
||||
app: {
|
||||
apolloProvider: { defaultClient: { mutate } },
|
||||
$apolloHelpers: { onLogin }
|
||||
}
|
||||
}
|
||||
action = actions.login.bind(module)
|
||||
await action(
|
||||
{ commit },
|
||||
{ email: 'user@example.org', password: '1234' }
|
||||
)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
action = null
|
||||
})
|
||||
|
||||
it('saves the JWT Bearer token', () => {
|
||||
expect(commit.mock.calls).toEqual(
|
||||
expect.arrayContaining([['SET_TOKEN', token]])
|
||||
)
|
||||
})
|
||||
|
||||
it('saves user data without token', () => {
|
||||
expect(commit.mock.calls).toEqual(
|
||||
expect.arrayContaining([
|
||||
[
|
||||
'SET_USER',
|
||||
{
|
||||
id: 'u3',
|
||||
name: 'Jenny Rostock',
|
||||
slug: 'jenny-rostock',
|
||||
email: 'user@example.org',
|
||||
avatar:
|
||||
'https://s3.amazonaws.com/uifaces/faces/twitter/mutu_krish/128.jpg',
|
||||
role: 'user'
|
||||
}
|
||||
]
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it('saves pending flags in order', () => {
|
||||
expect(commit.mock.calls).toEqual(
|
||||
expect.arrayContaining([
|
||||
['SET_PENDING', true],
|
||||
['SET_PENDING', false]
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('given invalid credentials and incorrect password response', () => {
|
||||
let onLogin
|
||||
let mutate
|
||||
|
||||
beforeEach(() => {
|
||||
mutate = jest.fn(() => Promise.reject('This error is expected.'))
|
||||
onLogin = jest.fn(() => Promise.resolve())
|
||||
const module = {
|
||||
app: {
|
||||
apolloProvider: { defaultClient: { mutate } },
|
||||
$apolloHelpers: { onLogin }
|
||||
}
|
||||
}
|
||||
action = actions.login.bind(module)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
action = null
|
||||
})
|
||||
|
||||
it('populates error messages', async () => {
|
||||
expect(
|
||||
action({ commit }, { email: 'user@example.org', password: 'wrong' })
|
||||
).rejects.toThrowError('This error is expected.')
|
||||
expect(mutate).toHaveBeenCalled()
|
||||
expect(onLogin).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('saves pending flags in order', async () => {
|
||||
try {
|
||||
await action(
|
||||
{ commit },
|
||||
{ email: 'user@example.org', password: 'wrong' }
|
||||
)
|
||||
} catch (err) {} // ignore
|
||||
expect(commit.mock.calls).toEqual(
|
||||
expect.arrayContaining([
|
||||
['SET_PENDING', true],
|
||||
['SET_PENDING', false]
|
||||
])
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
40
yarn.lock
40
yarn.lock
@ -1344,17 +1344,17 @@
|
||||
eslint-plugin-prettier "^3.0.0"
|
||||
prettier "^1.15.2"
|
||||
|
||||
"@vue/server-test-utils@^1.0.0-beta.27":
|
||||
version "1.0.0-beta.27"
|
||||
resolved "https://registry.yarnpkg.com/@vue/server-test-utils/-/server-test-utils-1.0.0-beta.27.tgz#0c61cb724d04bf44c70938b4a6054e73e914492a"
|
||||
integrity sha512-HKwm1Nw180qNgknPyok/XWJF4ojBZC5vSANPf+f1WR2jYsSc0vvAxUyX2Qeq4F7KLXrfsFwdkfH3a5BxdrA9tg==
|
||||
"@vue/server-test-utils@^1.0.0-beta.28":
|
||||
version "1.0.0-beta.28"
|
||||
resolved "https://registry.yarnpkg.com/@vue/server-test-utils/-/server-test-utils-1.0.0-beta.28.tgz#40adb6a6c05e8970cc5e5f0869eb490fa00d9cf3"
|
||||
integrity sha512-CrXQ2ISmLvye4HC4sIHqqR3Gyg02i8XcTwMAyIh+UY7fh1Nz4f9XE4LDsxg0B9uSGsSiR0lwphjlGtbUJjGl4A==
|
||||
dependencies:
|
||||
cheerio "^1.0.0-rc.2"
|
||||
|
||||
"@vue/test-utils@^1.0.0-beta.27":
|
||||
version "1.0.0-beta.27"
|
||||
resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.0.0-beta.27.tgz#7e5f7b7180c00e28a4ca55c0ff0a7e754377fdb2"
|
||||
integrity sha512-Lzrd4ZBkS70Tl8JbXbDrN/NcSaH9aZT6+7emU3QhTJ+CrorJpyFDA1dkvSIhH+rDTs8sHFbGeXjXV/qorXxtRw==
|
||||
"@vue/test-utils@^1.0.0-beta.28":
|
||||
version "1.0.0-beta.28"
|
||||
resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.0.0-beta.28.tgz#767c43413df8cde86128735e58923803e444b9a5"
|
||||
integrity sha512-uVbFJG0g/H9hf2pgWUdhvQYItRGzQ44cMFf00wp0YEo85pxuvM9e3mx8QLQfx6R2CogxbK4CvV7qvkLblehXeQ==
|
||||
dependencies:
|
||||
dom-event-types "^1.0.0"
|
||||
lodash "^4.17.4"
|
||||
@ -4875,10 +4875,10 @@ eslint-loader@^2.0.0:
|
||||
object-hash "^1.1.4"
|
||||
rimraf "^2.6.1"
|
||||
|
||||
eslint-plugin-prettier@3.0.0, eslint-plugin-prettier@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.0.0.tgz#f6b823e065f8c36529918cdb766d7a0e975ec30c"
|
||||
integrity sha512-4g11opzhqq/8+AMmo5Vc2Gn7z9alZ4JqrbZ+D4i8KlSyxeQhZHlmIrY8U9Akf514MoEhogPa87Jgkq87aZ2Ohw==
|
||||
eslint-plugin-prettier@3.0.1, eslint-plugin-prettier@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.0.1.tgz#19d521e3981f69dd6d14f64aec8c6a6ac6eb0b0d"
|
||||
integrity sha512-/PMttrarPAY78PLvV3xfWibMOdMDl57hmlQ2XqFeA37wd+CJ7WSxV7txqjVPHi/AAFKd2lX0ZqfsOc/i5yFCSQ==
|
||||
dependencies:
|
||||
prettier-linter-helpers "^1.0.0"
|
||||
|
||||
@ -4915,10 +4915,10 @@ eslint-visitor-keys@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d"
|
||||
integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==
|
||||
|
||||
eslint@^5.10.0:
|
||||
version "5.10.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.10.0.tgz#24adcbe92bf5eb1fc2d2f2b1eebe0c5e0713903a"
|
||||
integrity sha512-HpqzC+BHULKlnPwWae9MaVZ5AXJKpkxCVXQHrFaRw3hbDj26V/9ArYM4Rr/SQ8pi6qUPLXSSXC4RBJlyq2Z2OQ==
|
||||
eslint@^5.11.1:
|
||||
version "5.11.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.11.1.tgz#8deda83db9f354bf9d3f53f9677af7e0e13eadda"
|
||||
integrity sha512-gOKhM8JwlFOc2acbOrkYR05NW8M6DCMSvfcJiBB5NDxRE1gv8kbvxKaC9u69e6ZGEMWXcswA/7eKR229cEIpvg==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.0.0"
|
||||
ajv "^6.5.3"
|
||||
@ -11682,10 +11682,10 @@ vue@^2.5.17:
|
||||
resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.17.tgz#0f8789ad718be68ca1872629832ed533589c6ada"
|
||||
integrity sha512-mFbcWoDIJi0w0Za4emyLiW72Jae0yjANHbCVquMKijcavBGypqlF7zHRgMa5k4sesdv7hv2rB4JPdZfR+TPfhQ==
|
||||
|
||||
vuex-i18n@^1.10.5:
|
||||
version "1.10.5"
|
||||
resolved "https://registry.yarnpkg.com/vuex-i18n/-/vuex-i18n-1.10.5.tgz#635ea2204e0aa3f8fd512f0fab7f6b994d3f666c"
|
||||
integrity sha1-Y16iIE4Ko/j9US8Pq39rmU0/Zmw=
|
||||
vuex-i18n@^1.10.9:
|
||||
version "1.10.9"
|
||||
resolved "https://registry.yarnpkg.com/vuex-i18n/-/vuex-i18n-1.10.9.tgz#5d5dc551f33b1d229b9bbff45deec29d9be93143"
|
||||
integrity sha512-9JECE4I9VG0ZDCTV7kAldLdZN7FXJi/wjGi7DP/gosFyiye9jKBuIWO1djxkenl1ablTLfu/O6oTWBZuOIUsbQ==
|
||||
|
||||
vuex@^3.0.1:
|
||||
version "3.0.1"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user