Commit 1ec19b09 authored by Jure's avatar Jure

test: fix e2e tests

parent 8e648c4e
......@@ -4,7 +4,7 @@ import { Route, Switch } from 'react-router-dom'
// Authentication
import Login from 'pubsweet-component-login'
import Signup from 'pubsweet-component-signup'
import PasswordReset from 'pubsweet-component-password-reset-frontend/PasswordReset'
import PasswordReset from '@pubsweet/component-password-reset-client'
import App from './components/App'
......
const { pickBy } = require('lodash')
class AuthsomeMode {
/**
* Creates a new instance of AuthsomeMode
*
* @param {string} userId A user's UUID
* @param {string} operation The operation you're authorizing for
* @param {any} object The object of authorization
* @param {any} context Context for authorization, e.g. database access
* @returns {string}
*/
constructor(userId, operation, object, context) {
this.userId = userId
this.operation = AuthsomeMode.mapOperation(operation)
this.object = object
this.context = context
}
/**
* Maps operations from HTTP verbs to semantic verbs
*
* @param {any} operation
* @returns {string}
*/
static mapOperation(operation) {
const operationMap = {
GET: 'read',
POST: 'create',
PATCH: 'update',
DELETE: 'delete',
}
return operationMap[operation] ? operationMap[operation] : operation
}
async isTeamMember(teamType, object) {
let membershipCondition
if (object) {
membershipCondition = team =>
team.teamType === teamType &&
team.object &&
team.object.id === object.id
} else {
membershipCondition = team => team.teamType === teamType
}
const memberships = await Promise.all(
this.user.teams.map(async teamId => {
const teamFound = await this.context.models.Team.find(teamId)
if (teamFound) {
return membershipCondition(teamFound)
}
return false
}),
)
return memberships.includes(true)
}
isAuthor(object) {
return this.isTeamMember('author', object)
}
async findCollectionByObject(object) {
const { type, id, book, object: collection } = object
let collectionId
switch (type) {
case 'fragment':
collectionId = book
break
case 'team':
collectionId = collection.id
break
default:
collectionId = id
break
}
if (id) {
return this.context.models.Collection.find(collectionId)
}
return undefined
}
async canRead() {
this.user = await this.context.models.User.find(this.userId)
// const collection = await this.findCollectionByObject(this.object)
// const permission = await this.isAuthor(collection)
return true
}
async canListCollections() {
this.user = await this.context.models.User.find(this.userId)
return {
filter: async collections => {
const filteredCollections = await Promise.all(
collections.map(async collection => {
const condition = await this.isAuthor(collection)
return condition ? collection : undefined
}, this),
)
return filteredCollections.filter(collection => collection)
},
}
}
async canReadUser() {
this.user = await this.context.models.User.find(this.userId)
if (this.user.id === this.object.id) {
return true
}
return {
filter: user =>
pickBy(user, (_, key) => ['id', 'username', 'type'].includes(key)),
}
}
async canListTeams() {
this.user = await this.context.models.User.find(this.userId)
return {
filter: async teams => {
const filteredTeams = await Promise.all(
teams.map(async team => {
const condition = this.belongsToTeam(team.id)
return condition ? team : undefined
}, this),
)
return filteredTeams.filter(team => team)
},
}
}
belongsToTeam(teamId) {
return this.user.teams.includes(teamId)
}
async canReadTeam() {
this.user = await this.context.models.User.find(this.userId)
return true
}
async canCreateTeam() {
this.user = await this.context.models.User.find(this.userId)
return true
}
async canUpdateTeam() {
this.user = await this.context.models.User.find(this.userId)
return true
}
async canCreateCollection() {
this.user = await this.context.models.User.find(this.userId)
return true
}
}
module.exports = {
before: async (userId, operation, object, context) => {
const user = userId && (await context.models.User.find(userId))
return user && user.admin
},
GET: (userId, operation, object, context) => {
// const mode = new AuthsomeMode(userId, operation, object, context)
// GET /api/collections
if (object && object.path === '/api/collections') {
return true
}
// GET /api/collection
if (object && object.type === 'collection') {
return true
}
// GET /api/collections/:collectionId/fragments
if (object && object.path === '/api/fragments') {
return true
}
// GET /api/collections/:collectionId/fragments/:fragmentId
if (object && object.type === 'fragment') {
return true
}
// GET /api/users
if (object && object.path === '/api/users') {
return true
}
// // GET /api/teams
if (object && object.path === '/api/teams') {
return true
}
// // GET /api/team
if (object && object.type === 'team') {
return true
}
// // GET /api/user
if (object && object.type === 'user') {
return true
}
return false
},
POST: (userId, operation, object, context) => {
const mode = new AuthsomeMode(userId, operation, object, context)
// POST /api/collections
if (object && object.path === '/api/collections') {
return mode.canCreateCollection()
}
// POST /api/users
if (object && object.path === '/api/users') {
return true
}
// POST /api/users/authenticate
if (object && object.token) {
return true
}
// POST /api/fragments
if (object && object.path === '/api/collections/:collectionId/fragments') {
return true
}
// POST /api/teams
if (object && object.path === '/api/teams') {
return true
}
return false
},
PATCH: (userId, operation, object, context) => {
// const mode = new AuthsomeMode(userId, operation, object, context)
// PATCH /api/collections/:id
let data
if (object) {
if (object.current) {
data = object.current
} else {
data = object
}
} else {
return false
}
if (data.type === 'collection') {
return true
}
// PATCH /api/fragments/:id
if (data.type === 'fragment') {
return true
}
// PATCH /api/teams/:id
if (data.current.type === 'team') {
return true
}
return false
},
DELETE: (userId, operation, object, context) => {
// const mode = new AuthsomeMode(userId, operation, object, context)
// DELETE /api/collections/:id
if (object && object.type === 'collection') {
return true
}
// DELETE /api/fragments/:id
if (object && object.type === 'fragment') {
return true
}
// DELETE /api/teams/:id
if (object && object.type === 'team') {
return true
}
return false
},
before: async (userId, operation, object, context) => true,
// const user = userId && (await context.models.User.find(userId))
// return user && user.admin
}
[
"pubsweet-component-password-reset-backend",
"@pubsweet/model-user",
"@pubsweet/model-team",
"@pubsweet/model-blog",
"@pubsweet/model-blogpost"
"@pubsweet/model-blogpost",
"@pubsweet/component-password-reset-server"
]
......@@ -8,6 +8,7 @@ import { login, passwordReset, helloWorld } from './pageObjects'
let admin
fixture('Admin user')
.page(passwordReset.url)
.before(startServer)
.beforeEach(async () => {
const result = await setup()
......@@ -20,7 +21,6 @@ test('Password reset journey', async t => {
// request password reset email
await t
.navigateTo(passwordReset.url)
.typeText(passwordReset.username, admin.username)
.click(passwordReset.submit)
.expect(passwordReset.alert.innerText)
......
......@@ -19,7 +19,7 @@ test('Signup journey', async t => {
await login
.doLogin(user.username, user.password)
.expect(login.alert.innerText)
.contains('Unauthorized')
.contains('Wrong username or password.')
// signup
await t
......@@ -35,5 +35,5 @@ test('Signup journey', async t => {
await login
.doLogin(user.username, user.password)
.expect(t.eval(() => window.location.href))
.eql('http://localhost:4000/dashboard')
.eql('http://localhost:4000/dashboard/hello-world')
})
import faker from 'faker'
import start from 'pubsweet/src/startup/start'
import { addUser, addCollection, createTables } from '@pubsweet/db-manager'
import { addUser, createTables } from '@pubsweet/db-manager'
let server
......@@ -20,12 +20,6 @@ export async function setup(user, collection) {
admin: true,
}
const collectionData = collection || {
title: faker.lorem.words(),
}
await addUser(userData)
await addCollection(collectionData)
return { userData, collectionData }
return { userData }
}
......@@ -3,7 +3,7 @@ import { ReactSelector } from 'testcafe-react-selectors'
const helloWorld = {
url: `${config.get('pubsweet-server.baseUrl')}/dashboard`,
text: ReactSelector('HelloWorld').nth(0),
text: ReactSelector('HelloWorld'),
}
export default helloWorld
......@@ -8,9 +8,12 @@ const login = {
username: Selector('form input[type=text]'),
password: Selector('form input[type=password]'),
submit: Selector('form button'),
signUp: ReactSelector('Login Styled(Link)').nth(0),
resetPassword: ReactSelector('Login Link').nth(1),
signUp: ReactSelector('Login')
.findReact('Link')
.withProps({ to: '/signup' }),
resetPassword: ReactSelector('Login')
.findReact('Link')
.withProps({ to: '/password-reset' }),
alert: Selector(() => document.querySelector('form').previousSibling),
doLogin: (username, password) =>
......
......@@ -7,6 +7,7 @@ module.exports = [
/pubsweet-[^/\\]+\/(?!node_modules)/,
/@pubsweet\/[^/\\]+\/(?!node_modules)/,
// include other packages when this repo is mounted in a workspace
/components\/client\/[^/\\]+\/(?!node_modules)/,
/packages\/[^/\\]+\/(?!node_modules)/,
/node_modules\/xpub-edit/,
]
......@@ -18,6 +18,7 @@ module.exports = [
{
// The configuration for the client
name: 'app',
mode: 'development',
target: 'web',
context: path.join(__dirname, '..', 'app'),
entry: {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment