mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-12 23:35:58 +00:00
Merge branch 'master' into migrate-styleguide-icons
This commit is contained in:
commit
a210dd599d
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
backend/snapshots/* linguist-generated=true
|
||||
|
||||
17
.github/stale.yml
vendored
Normal file
17
.github/stale.yml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 60
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 30
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -18,3 +18,4 @@ cypress.env.json
|
||||
**/coverage
|
||||
|
||||
release/
|
||||
*~
|
||||
@ -41,7 +41,7 @@ script:
|
||||
- docker-compose down
|
||||
- docker-compose -f docker-compose.yml up -d
|
||||
- wait-on http://localhost:7474
|
||||
- yarn run cypress:run
|
||||
- yarn run cypress:run --record
|
||||
# Coverage
|
||||
- yarn run codecov
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
* [Neo4J](neo4j/README.md)
|
||||
* [Backend](backend/README.md)
|
||||
* [GraphQL](backend/graphql.md)
|
||||
* [neo4j-graphql-js](backend/neo4j-graphql-js.md)
|
||||
* [Webapp](webapp/README.md)
|
||||
* [Components](webapp/components.md)
|
||||
* [HTML](webapp/html.md)
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
NEO4J_URI=bolt://localhost:7687
|
||||
NEO4J_USERNAME=neo4j
|
||||
NEO4J_PASSWORD=letmein
|
||||
GRAPHQL_PORT=4000
|
||||
GRAPHQL_URI=http://localhost:4000
|
||||
CLIENT_URI=http://localhost:3000
|
||||
SMTP_HOST=
|
||||
|
||||
16
backend/neo4j-graphql-js.md
Normal file
16
backend/neo4j-graphql-js.md
Normal file
@ -0,0 +1,16 @@
|
||||
# neo4j-graphql.js
|
||||
|
||||
We use an npm package called `neo4j-graphql-js` as a cypher query builder. This
|
||||
library also generates resolvers for graphql queries, unless we implement them
|
||||
ourselves.
|
||||
|
||||
|
||||
## Debugging
|
||||
|
||||
As you can see in their [documentation](https://github.com/neo4j-graphql/neo4j-graphql-js)
|
||||
it is possible to log out the generated cypher statements. To do so, run the
|
||||
backend like this:
|
||||
|
||||
```sh
|
||||
DEBUG=neo4j-graphql-js yarn run dev
|
||||
```
|
||||
@ -35,12 +35,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@hapi/joi": "^16.1.7",
|
||||
"@sentry/node": "^5.8.0",
|
||||
"@sentry/node": "^5.9.0",
|
||||
"apollo-cache-inmemory": "~1.6.3",
|
||||
"apollo-client": "~2.6.4",
|
||||
"apollo-link-context": "~1.0.19",
|
||||
"apollo-link-http": "~1.5.16",
|
||||
"apollo-server": "~2.9.7",
|
||||
"apollo-server": "~2.9.9",
|
||||
"apollo-server-express": "^2.9.7",
|
||||
"babel-plugin-transform-runtime": "^6.23.0",
|
||||
"bcryptjs": "~2.4.3",
|
||||
@ -64,26 +64,26 @@
|
||||
"linkifyjs": "~2.1.8",
|
||||
"lodash": "~4.17.14",
|
||||
"merge-graphql-schemas": "^1.7.3",
|
||||
"metascraper": "^4.10.3",
|
||||
"metascraper-audio": "^5.7.17",
|
||||
"metascraper-author": "^5.7.17",
|
||||
"metascraper": "^5.8.8",
|
||||
"metascraper-audio": "^5.8.7",
|
||||
"metascraper-author": "^5.8.7",
|
||||
"metascraper-clearbit-logo": "^5.3.0",
|
||||
"metascraper-date": "^5.7.17",
|
||||
"metascraper-description": "^5.7.17",
|
||||
"metascraper-image": "^5.7.17",
|
||||
"metascraper-lang": "^5.7.17",
|
||||
"metascraper-lang-detector": "^4.8.5",
|
||||
"metascraper-logo": "^5.7.17",
|
||||
"metascraper-publisher": "^5.7.17",
|
||||
"metascraper-soundcloud": "^5.7.17",
|
||||
"metascraper-title": "^5.7.17",
|
||||
"metascraper-url": "^5.7.17",
|
||||
"metascraper-video": "^5.7.17",
|
||||
"metascraper-youtube": "^5.7.17",
|
||||
"metascraper-date": "^5.8.7",
|
||||
"metascraper-description": "^5.8.7",
|
||||
"metascraper-image": "^5.8.7",
|
||||
"metascraper-lang": "^5.8.7",
|
||||
"metascraper-lang-detector": "^4.10.2",
|
||||
"metascraper-logo": "^5.8.7",
|
||||
"metascraper-publisher": "^5.8.7",
|
||||
"metascraper-soundcloud": "^5.8.7",
|
||||
"metascraper-title": "^5.8.7",
|
||||
"metascraper-url": "^5.8.7",
|
||||
"metascraper-video": "^5.8.7",
|
||||
"metascraper-youtube": "^5.8.7",
|
||||
"minimatch": "^3.0.4",
|
||||
"mustache": "^3.1.0",
|
||||
"neo4j-driver": "~1.7.6",
|
||||
"neo4j-graphql-js": "^2.8.0",
|
||||
"neo4j-graphql-js": "^2.9.3",
|
||||
"neode": "^0.3.3",
|
||||
"node-fetch": "~2.6.0",
|
||||
"nodemailer": "^6.3.1",
|
||||
@ -105,24 +105,24 @@
|
||||
"@babel/plugin-proposal-throw-expressions": "^7.2.0",
|
||||
"@babel/preset-env": "~7.7.1",
|
||||
"@babel/register": "~7.7.0",
|
||||
"apollo-server-testing": "~2.9.7",
|
||||
"apollo-server-testing": "~2.9.9",
|
||||
"babel-core": "~7.0.0-0",
|
||||
"babel-eslint": "~10.0.3",
|
||||
"babel-jest": "~24.9.0",
|
||||
"chai": "~4.2.0",
|
||||
"cucumber": "~6.0.3",
|
||||
"cucumber": "~6.0.5",
|
||||
"eslint": "~6.6.0",
|
||||
"eslint-config-prettier": "~6.5.0",
|
||||
"eslint-config-prettier": "~6.7.0",
|
||||
"eslint-config-standard": "~14.1.0",
|
||||
"eslint-plugin-import": "~2.18.2",
|
||||
"eslint-plugin-jest": "~23.0.3",
|
||||
"eslint-plugin-jest": "~23.0.4",
|
||||
"eslint-plugin-node": "~10.0.0",
|
||||
"eslint-plugin-prettier": "~3.1.1",
|
||||
"eslint-plugin-promise": "~4.2.1",
|
||||
"eslint-plugin-standard": "~4.0.1",
|
||||
"jest": "~24.9.0",
|
||||
"nodemon": "~1.19.4",
|
||||
"prettier": "~1.18.2",
|
||||
"prettier": "~1.19.1",
|
||||
"supertest": "~4.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
2667
backend/snapshots/embeds/HumanConnectionOrg.html
Normal file
2667
backend/snapshots/embeds/HumanConnectionOrg.html
Normal file
File diff suppressed because it is too large
Load Diff
1783
backend/snapshots/embeds/babyLovesCat.html
Normal file
1783
backend/snapshots/embeds/babyLovesCat.html
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,12 +0,0 @@
|
||||
import {
|
||||
GraphQLLowerCaseDirective,
|
||||
GraphQLTrimDirective,
|
||||
GraphQLDefaultToDirective,
|
||||
} from 'graphql-custom-directives'
|
||||
|
||||
export default function applyDirectives(augmentedSchema) {
|
||||
const directives = [GraphQLLowerCaseDirective, GraphQLTrimDirective, GraphQLDefaultToDirective]
|
||||
augmentedSchema._directives.push.apply(augmentedSchema._directives, directives)
|
||||
|
||||
return augmentedSchema
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
import { GraphQLDate, GraphQLTime, GraphQLDateTime } from 'graphql-iso-date'
|
||||
|
||||
export default function applyScalars(augmentedSchema) {
|
||||
augmentedSchema._typeMap.Date = GraphQLDate
|
||||
augmentedSchema._typeMap.Time = GraphQLTime
|
||||
augmentedSchema._typeMap.DateTime = GraphQLDateTime
|
||||
|
||||
return augmentedSchema
|
||||
}
|
||||
@ -16,7 +16,6 @@ const {
|
||||
NEO4J_URI = 'bolt://localhost:7687',
|
||||
NEO4J_USERNAME = 'neo4j',
|
||||
NEO4J_PASSWORD = 'neo4j',
|
||||
GRAPHQL_PORT = 4000,
|
||||
CLIENT_URI = 'http://localhost:3000',
|
||||
GRAPHQL_URI = 'http://localhost:4000',
|
||||
} = process.env
|
||||
@ -36,7 +35,6 @@ export const smtpConfigs = {
|
||||
}
|
||||
export const neo4jConfigs = { NEO4J_URI, NEO4J_USERNAME, NEO4J_PASSWORD }
|
||||
export const serverConfigs = {
|
||||
GRAPHQL_PORT,
|
||||
CLIENT_URI,
|
||||
GRAPHQL_URI,
|
||||
PUBLIC_REGISTRATION: process.env.PUBLIC_REGISTRATION === 'true',
|
||||
|
||||
5
backend/src/helpers/jest.js
Normal file
5
backend/src/helpers/jest.js
Normal file
@ -0,0 +1,5 @@
|
||||
//* This is a fake ES2015 template string, just to benefit of syntax
|
||||
// highlighting of `gql` template strings in certain editors.
|
||||
export function gql(strings) {
|
||||
return strings.join('')
|
||||
}
|
||||
@ -2,7 +2,8 @@ import createServer from './server'
|
||||
import CONFIG from './config'
|
||||
|
||||
const { app } = createServer()
|
||||
app.listen({ port: CONFIG.GRAPHQL_PORT }, () => {
|
||||
const url = new URL(CONFIG.GRAPHQL_URI)
|
||||
app.listen({ port: url.port }, () => {
|
||||
/* eslint-disable-next-line no-console */
|
||||
console.log(`GraphQLServer ready at ${CONFIG.GRAPHQL_URI} 🚀`)
|
||||
})
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,4 +1,4 @@
|
||||
import { gql } from '../../jest/helpers'
|
||||
import { gql } from '../../helpers/jest'
|
||||
import Factory from '../../seed/factories'
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import { neode, getDriver } from '../../bootstrap/neo4j'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { gql } from '../../jest/helpers'
|
||||
import { gql } from '../../helpers/jest'
|
||||
import Factory from '../../seed/factories'
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import { neode, getDriver } from '../../bootstrap/neo4j'
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { gql } from '../helpers/jest'
|
||||
import Factory from '../seed/factories'
|
||||
import { gql } from '../jest/helpers'
|
||||
import { neode as getNeode, getDriver } from '../bootstrap/neo4j'
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import createServer from '../server'
|
||||
|
||||
@ -41,20 +41,6 @@ const isMySocialMedia = rule({
|
||||
return socialMedia.ownedBy.node.id === user.id
|
||||
})
|
||||
|
||||
/* TODO: decide if we want to remove this check: the check
|
||||
* `onlyEnabledContent` throws authorization errors only if you have
|
||||
* arguments for `disabled` or `deleted` assuming these are filter
|
||||
* parameters. Soft-delete middleware obfuscates data on its way out
|
||||
* anyways. Furthermore, `neo4j-graphql-js` offers many ways to filter for
|
||||
* data so I believe, this is not a good check anyways.
|
||||
*/
|
||||
const onlyEnabledContent = rule({
|
||||
cache: 'strict',
|
||||
})(async (parent, args, ctx, info) => {
|
||||
const { disabled, deleted } = args
|
||||
return !(disabled || deleted)
|
||||
})
|
||||
|
||||
const invitationLimitReached = rule({
|
||||
cache: 'no_cache',
|
||||
})(async (parent, args, { user, driver }) => {
|
||||
@ -125,7 +111,8 @@ const permissions = shield(
|
||||
reports: isModerator,
|
||||
statistics: allow,
|
||||
currentUser: allow,
|
||||
Post: or(onlyEnabledContent, isModerator),
|
||||
Post: allow,
|
||||
profilePagePosts: allow,
|
||||
Comment: allow,
|
||||
User: or(noEmailFilter, isAdmin),
|
||||
isLoggedIn: allow,
|
||||
@ -134,7 +121,6 @@ const permissions = shield(
|
||||
PostsEmotionsByCurrentUser: isAuthenticated,
|
||||
blockedUsers: isAuthenticated,
|
||||
notifications: isAuthenticated,
|
||||
profilePagePosts: or(onlyEnabledContent, isModerator),
|
||||
Donations: isAuthenticated,
|
||||
},
|
||||
Mutation: {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import createServer from '../server'
|
||||
import Factory from '../seed/factories'
|
||||
import { gql } from '../jest/helpers'
|
||||
import { gql } from '../helpers/jest'
|
||||
import { getDriver, neode as getNeode } from '../bootstrap/neo4j'
|
||||
|
||||
const factory = Factory()
|
||||
|
||||
@ -25,9 +25,5 @@ export default {
|
||||
args.slug = args.slug || (await uniqueSlug(args.title, isUniqueFor(context, 'Post')))
|
||||
return resolve(root, args, context, info)
|
||||
},
|
||||
CreateCategory: async (resolve, root, args, context, info) => {
|
||||
args.slug = args.slug || (await uniqueSlug(args.name, isUniqueFor(context, 'Category')))
|
||||
return resolve(root, args, context, info)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import Factory from '../seed/factories'
|
||||
import { gql } from '../jest/helpers'
|
||||
import { gql } from '../helpers/jest'
|
||||
import { neode as getNeode, getDriver } from '../bootstrap/neo4j'
|
||||
import createServer from '../server'
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
|
||||
@ -3,9 +3,7 @@ const isModerator = ({ user }) => {
|
||||
}
|
||||
|
||||
const setDefaultFilters = (resolve, root, args, context, info) => {
|
||||
if (typeof args.deleted !== 'boolean') {
|
||||
args.deleted = false
|
||||
}
|
||||
args.deleted = false
|
||||
|
||||
if (!isModerator(context)) {
|
||||
args.disabled = false
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import Factory from '../../seed/factories'
|
||||
import { gql } from '../../jest/helpers'
|
||||
import { gql } from '../../helpers/jest'
|
||||
import { neode as getNeode, getDriver } from '../../bootstrap/neo4j'
|
||||
import createServer from '../../server'
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
@ -341,76 +341,6 @@ describe('softDeleteMiddleware', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('filter (deleted: true)', () => {
|
||||
beforeEach(() => {
|
||||
graphqlQuery = gql`
|
||||
{
|
||||
Post(deleted: true) {
|
||||
title
|
||||
}
|
||||
}
|
||||
`
|
||||
})
|
||||
|
||||
describe('as user', () => {
|
||||
beforeEach(async () => {
|
||||
authenticatedUser = await user.toJson()
|
||||
})
|
||||
|
||||
it('throws authorisation error', async () => {
|
||||
const { data, errors } = await action()
|
||||
expect(data).toEqual({ Post: null })
|
||||
expect(errors[0]).toHaveProperty('message', 'Not Authorised!')
|
||||
})
|
||||
})
|
||||
|
||||
describe('as moderator', () => {
|
||||
beforeEach(async () => {
|
||||
authenticatedUser = await moderator.toJson()
|
||||
})
|
||||
|
||||
it('does not show deleted posts', async () => {
|
||||
const expected = { data: { Post: [{ title: 'UNAVAILABLE' }] } }
|
||||
await expect(action()).resolves.toMatchObject(expected)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('filter (disabled: true)', () => {
|
||||
beforeEach(() => {
|
||||
graphqlQuery = gql`
|
||||
{
|
||||
Post(disabled: true) {
|
||||
title
|
||||
}
|
||||
}
|
||||
`
|
||||
})
|
||||
|
||||
describe('as user', () => {
|
||||
beforeEach(async () => {
|
||||
authenticatedUser = await user.toJson()
|
||||
})
|
||||
|
||||
it('throws authorisation error', async () => {
|
||||
const { data, errors } = await action()
|
||||
expect(data).toEqual({ Post: null })
|
||||
expect(errors[0]).toHaveProperty('message', 'Not Authorised!')
|
||||
})
|
||||
})
|
||||
|
||||
describe('as moderator', () => {
|
||||
beforeEach(async () => {
|
||||
authenticatedUser = await moderator.toJson()
|
||||
})
|
||||
|
||||
it('shows disabled posts', async () => {
|
||||
const expected = { data: { Post: [{ title: 'Disabled post' }] } }
|
||||
await expect(action()).resolves.toMatchObject(expected)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -127,6 +127,10 @@ module.exports = {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
},
|
||||
showShoutsPublicly: {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
},
|
||||
locale: {
|
||||
type: 'string',
|
||||
allow: [null],
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
export const undefinedToNull = list => {
|
||||
const resolvers = {}
|
||||
list.forEach(key => {
|
||||
resolvers[key] = async (parent, params, context, resolveInfo) => {
|
||||
return typeof parent[key] === 'undefined' ? null : parent[key]
|
||||
}
|
||||
})
|
||||
return resolvers
|
||||
}
|
||||
@ -1,56 +1,27 @@
|
||||
import { makeAugmentedSchema } from 'neo4j-graphql-js'
|
||||
import CONFIG from './../config'
|
||||
import applyScalars from './../bootstrap/scalars'
|
||||
import applyDirectives from './../bootstrap/directives'
|
||||
import typeDefs from './types'
|
||||
import resolvers from './resolvers'
|
||||
|
||||
export default applyScalars(
|
||||
applyDirectives(
|
||||
makeAugmentedSchema({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
config: {
|
||||
query: {
|
||||
exclude: [
|
||||
'Badge',
|
||||
'Embed',
|
||||
'InvitationCode',
|
||||
'EmailAddress',
|
||||
'Notfication',
|
||||
'Statistics',
|
||||
'LoggedInUser',
|
||||
'Location',
|
||||
'SocialMedia',
|
||||
'NOTIFIED',
|
||||
'REPORTED',
|
||||
'Donations',
|
||||
],
|
||||
// add 'User' here as soon as possible
|
||||
},
|
||||
mutation: {
|
||||
exclude: [
|
||||
'Badge',
|
||||
'Embed',
|
||||
'InvitationCode',
|
||||
'EmailAddress',
|
||||
'Notfication',
|
||||
'Post',
|
||||
'Comment',
|
||||
'Statistics',
|
||||
'LoggedInUser',
|
||||
'Location',
|
||||
'SocialMedia',
|
||||
'User',
|
||||
'EMOTED',
|
||||
'NOTIFIED',
|
||||
'REPORTED',
|
||||
'Donations',
|
||||
],
|
||||
// add 'User' here as soon as possible
|
||||
},
|
||||
debug: !!CONFIG.DEBUG,
|
||||
},
|
||||
}),
|
||||
),
|
||||
)
|
||||
export default makeAugmentedSchema({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
config: {
|
||||
query: {
|
||||
exclude: [
|
||||
'Badge',
|
||||
'Embed',
|
||||
'InvitationCode',
|
||||
'EmailAddress',
|
||||
'Notfication',
|
||||
'Statistics',
|
||||
'LoggedInUser',
|
||||
'Location',
|
||||
'SocialMedia',
|
||||
'NOTIFIED',
|
||||
'REPORTED',
|
||||
'Donations',
|
||||
],
|
||||
},
|
||||
mutation: false,
|
||||
},
|
||||
})
|
||||
|
||||
@ -3,7 +3,7 @@ import { neo4jgraphql } from 'neo4j-graphql-js'
|
||||
export default {
|
||||
Query: {
|
||||
Badge: async (object, args, context, resolveInfo) => {
|
||||
return neo4jgraphql(object, args, context, resolveInfo, false)
|
||||
return neo4jgraphql(object, args, context, resolveInfo)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import Factory from '../../seed/factories'
|
||||
import { gql } from '../../jest/helpers'
|
||||
import { gql } from '../../helpers/jest'
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import createServer from '../../server'
|
||||
import { neode as getNeode, getDriver } from '../../bootstrap/neo4j'
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import Factory from '../../seed/factories'
|
||||
import { gql } from '../../jest/helpers'
|
||||
import { gql } from '../../helpers/jest'
|
||||
import { neode as getNeode, getDriver } from '../../bootstrap/neo4j'
|
||||
import createServer from '../../server'
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import Factory from '../../seed/factories'
|
||||
import { gql } from '../../jest/helpers'
|
||||
import { gql } from '../../helpers/jest'
|
||||
import { getDriver, neode as getNeode } from '../../bootstrap/neo4j'
|
||||
import createServer from '../../server'
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
|
||||
@ -3,7 +3,7 @@ import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import createServer from '../../server'
|
||||
import { gql } from '../../jest/helpers'
|
||||
import { gql } from '../../helpers/jest'
|
||||
|
||||
jest.mock('node-fetch')
|
||||
const { Response } = jest.requireActual('node-fetch')
|
||||
@ -15,15 +15,12 @@ afterEach(() => {
|
||||
let variables = {}
|
||||
|
||||
const HumanConnectionOrg = fs.readFileSync(
|
||||
path.join(__dirname, '../../jest/snapshots/embeds/HumanConnectionOrg.html'),
|
||||
'utf8',
|
||||
)
|
||||
const pr960 = fs.readFileSync(
|
||||
path.join(__dirname, '../../jest/snapshots/embeds/pr960.html'),
|
||||
path.join(__dirname, '../../../snapshots/embeds/HumanConnectionOrg.html'),
|
||||
'utf8',
|
||||
)
|
||||
const pr960 = fs.readFileSync(path.join(__dirname, '../../../snapshots/embeds/pr960.html'), 'utf8')
|
||||
const babyLovesCat = fs.readFileSync(
|
||||
path.join(__dirname, '../../jest/snapshots/embeds/babyLovesCat.html'),
|
||||
path.join(__dirname, '../../../snapshots/embeds/babyLovesCat.html'),
|
||||
'utf8',
|
||||
)
|
||||
|
||||
@ -88,7 +85,7 @@ describe('Query', () => {
|
||||
})
|
||||
|
||||
it('shows some default data', async () => {
|
||||
const expected = expect.objectContaining({
|
||||
await expect(embedAction(variables)).resolves.toMatchObject({
|
||||
data: {
|
||||
embed: {
|
||||
audio: null,
|
||||
@ -98,7 +95,7 @@ describe('Query', () => {
|
||||
html: null,
|
||||
image: null,
|
||||
lang: null,
|
||||
publisher: 'YouTube',
|
||||
publisher: null,
|
||||
sources: ['resource'],
|
||||
title: null,
|
||||
type: 'link',
|
||||
@ -106,8 +103,8 @@ describe('Query', () => {
|
||||
video: null,
|
||||
},
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
await expect(embedAction(variables)).resolves.toEqual(expected)
|
||||
})
|
||||
})
|
||||
|
||||
@ -120,7 +117,7 @@ describe('Query', () => {
|
||||
})
|
||||
|
||||
it('does not crash if embed provider returns invalid JSON', async () => {
|
||||
const expected = expect.objectContaining({
|
||||
await expect(embedAction(variables)).resolves.toMatchObject({
|
||||
data: {
|
||||
embed: {
|
||||
audio: null,
|
||||
@ -140,8 +137,8 @@ describe('Query', () => {
|
||||
video: null,
|
||||
},
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
await expect(embedAction(variables)).resolves.toEqual(expected)
|
||||
})
|
||||
})
|
||||
|
||||
@ -154,7 +151,7 @@ describe('Query', () => {
|
||||
})
|
||||
|
||||
it('returns meta data even if no embed html can be retrieved', async () => {
|
||||
const expected = expect.objectContaining({
|
||||
await expect(embedAction(variables)).resolves.toMatchObject({
|
||||
data: {
|
||||
embed: {
|
||||
type: 'link',
|
||||
@ -174,8 +171,8 @@ describe('Query', () => {
|
||||
html: null,
|
||||
},
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
await expect(embedAction(variables)).resolves.toEqual(expected)
|
||||
})
|
||||
})
|
||||
|
||||
@ -188,7 +185,7 @@ describe('Query', () => {
|
||||
})
|
||||
|
||||
it('returns meta data plus youtube iframe html', async () => {
|
||||
const expected = expect.objectContaining({
|
||||
await expect(embedAction(variables)).resolves.toMatchObject({
|
||||
data: {
|
||||
embed: {
|
||||
type: 'video',
|
||||
@ -208,8 +205,8 @@ describe('Query', () => {
|
||||
'<iframe width="480" height="270" src="https://www.youtube.com/embed/qkdXAtO40Fo?start=18&feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>',
|
||||
},
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
await expect(embedAction(variables)).resolves.toEqual(expected)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -2,7 +2,7 @@ import { createTestClient } from 'apollo-server-testing'
|
||||
import Factory from '../../seed/factories'
|
||||
import { getDriver, neode as getNeode } from '../../bootstrap/neo4j'
|
||||
import createServer from '../../server'
|
||||
import { gql } from '../../jest/helpers'
|
||||
import { gql } from '../../helpers/jest'
|
||||
|
||||
const factory = Factory()
|
||||
const driver = getDriver()
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import Factory from '../../seed/factories'
|
||||
import { gql } from '../../jest/helpers'
|
||||
import { gql } from '../../helpers/jest'
|
||||
import { neode as getNeode, getDriver } from '../../bootstrap/neo4j'
|
||||
import createServer from '../../server'
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import Factory from '../../seed/factories'
|
||||
import { gql } from '../../jest/helpers'
|
||||
import { gql } from '../../helpers/jest'
|
||||
import { neode as getNeode, getDriver } from '../../bootstrap/neo4j'
|
||||
import createServer from '../../server'
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import Factory from '../../seed/factories'
|
||||
import { gql } from '../../jest/helpers'
|
||||
import { gql } from '../../helpers/jest'
|
||||
import { getDriver } from '../../bootstrap/neo4j'
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import createServer from '../.././server'
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import Factory from '../../seed/factories'
|
||||
import { gql } from '../../jest/helpers'
|
||||
import { gql } from '../../helpers/jest'
|
||||
import { neode as getNeode, getDriver } from '../../bootstrap/neo4j'
|
||||
import createPasswordReset from './helpers/createPasswordReset'
|
||||
import createServer from '../../server'
|
||||
|
||||
@ -29,7 +29,7 @@ const filterForBlockedUsers = async (params, context) => {
|
||||
}
|
||||
|
||||
const maintainPinnedPosts = params => {
|
||||
const pinnedPostFilter = { pinnedBy_in: { role_in: ['admin'] } }
|
||||
const pinnedPostFilter = { pinned: true }
|
||||
if (isEmpty(params.filter)) {
|
||||
params.filter = { OR: [pinnedPostFilter, {}] }
|
||||
} else {
|
||||
@ -43,15 +43,15 @@ export default {
|
||||
Post: async (object, params, context, resolveInfo) => {
|
||||
params = await filterForBlockedUsers(params, context)
|
||||
params = await maintainPinnedPosts(params)
|
||||
return neo4jgraphql(object, params, context, resolveInfo, false)
|
||||
return neo4jgraphql(object, params, context, resolveInfo)
|
||||
},
|
||||
findPosts: async (object, params, context, resolveInfo) => {
|
||||
params = await filterForBlockedUsers(params, context)
|
||||
return neo4jgraphql(object, params, context, resolveInfo, false)
|
||||
return neo4jgraphql(object, params, context, resolveInfo)
|
||||
},
|
||||
profilePagePosts: async (object, params, context, resolveInfo) => {
|
||||
params = await filterForBlockedUsers(params, context)
|
||||
return neo4jgraphql(object, params, context, resolveInfo, false)
|
||||
return neo4jgraphql(object, params, context, resolveInfo)
|
||||
},
|
||||
PostsEmotionsCountByEmotion: async (object, params, context, resolveInfo) => {
|
||||
const session = context.driver.session()
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import Factory from '../../seed/factories'
|
||||
import { gql } from '../../jest/helpers'
|
||||
import { gql } from '../../helpers/jest'
|
||||
import { neode as getNeode, getDriver } from '../../bootstrap/neo4j'
|
||||
import createServer from '../../server'
|
||||
|
||||
@ -210,6 +210,7 @@ describe('Post', () => {
|
||||
data: {
|
||||
Post: expect.arrayContaining(expected),
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -229,7 +230,9 @@ describe('Post', () => {
|
||||
|
||||
await user.relateTo(followedUser, 'following')
|
||||
variables = { filter: { author: { followedBy_some: { id: 'current-user' } } } }
|
||||
const expected = {
|
||||
await expect(
|
||||
query({ query: postQueryFilteredByUsersFollowed, variables }),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
Post: [
|
||||
{
|
||||
@ -238,10 +241,8 @@ describe('Post', () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
await expect(
|
||||
query({ query: postQueryFilteredByUsersFollowed, variables }),
|
||||
).resolves.toMatchObject(expected)
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import Factory from '../../seed/factories'
|
||||
import { gql } from '../../jest/helpers'
|
||||
import { gql } from '../../helpers/jest'
|
||||
import { getDriver, neode as getNeode } from '../../bootstrap/neo4j'
|
||||
import createServer from '../../server'
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import createServer from '../.././server'
|
||||
import Factory from '../../seed/factories'
|
||||
import { gql } from '../../jest/helpers'
|
||||
import { gql } from '../../helpers/jest'
|
||||
import { getDriver, neode as getNeode } from '../../bootstrap/neo4j'
|
||||
|
||||
const factory = Factory()
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import Factory from '../../seed/factories'
|
||||
import { gql } from '../../jest/helpers'
|
||||
import { gql } from '../../helpers/jest'
|
||||
import { neode as getNeode, getDriver } from '../../bootstrap/neo4j'
|
||||
import createServer from '../../server'
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import Factory from '../../seed/factories'
|
||||
import { gql } from '../../jest/helpers'
|
||||
import { gql } from '../../helpers/jest'
|
||||
import { neode as getNeode, getDriver } from '../../bootstrap/neo4j'
|
||||
import createServer from '../../server'
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import createServer from '../../server'
|
||||
import Factory from '../../seed/factories'
|
||||
import { gql } from '../../jest/helpers'
|
||||
import { gql } from '../../helpers/jest'
|
||||
import { neode, getDriver } from '../../bootstrap/neo4j'
|
||||
|
||||
const driver = getDriver()
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import jwt from 'jsonwebtoken'
|
||||
import CONFIG from './../../config'
|
||||
import Factory from '../../seed/factories'
|
||||
import { gql } from '../../jest/helpers'
|
||||
import { gql } from '../../helpers/jest'
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import createServer, { context } from '../../server'
|
||||
import encode from '../../jwt/encode'
|
||||
|
||||
@ -54,7 +54,7 @@ export default {
|
||||
user = await user.toJson()
|
||||
return [user.node]
|
||||
}
|
||||
return neo4jgraphql(object, args, context, resolveInfo, false)
|
||||
return neo4jgraphql(object, args, context, resolveInfo)
|
||||
},
|
||||
},
|
||||
Mutation: {
|
||||
@ -177,6 +177,8 @@ export default {
|
||||
'termsAndConditionsAgreedVersion',
|
||||
'termsAndConditionsAgreedAt',
|
||||
'allowEmbedIframes',
|
||||
'showShoutsPublicly',
|
||||
'locale',
|
||||
],
|
||||
boolean: {
|
||||
followedByCurrentUser:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import Factory from '../../seed/factories'
|
||||
import { gql } from '../../jest/helpers'
|
||||
import { gql } from '../../helpers/jest'
|
||||
import { neode as getNeode, getDriver } from '../../bootstrap/neo4j'
|
||||
import createServer from '../../server'
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { createTestClient } from 'apollo-server-testing'
|
||||
import createServer from '../../../server'
|
||||
import Factory from '../../../seed/factories'
|
||||
import { gql } from '../../../jest/helpers'
|
||||
import { gql } from '../../../helpers/jest'
|
||||
import { neode, getDriver } from '../../../bootstrap/neo4j'
|
||||
|
||||
const driver = getDriver()
|
||||
|
||||
@ -1 +0,0 @@
|
||||
scalar Date
|
||||
@ -1 +0,0 @@
|
||||
scalar DateTime
|
||||
@ -1 +0,0 @@
|
||||
scalar Time
|
||||
@ -3,8 +3,6 @@ type Badge {
|
||||
type: BadgeType!
|
||||
status: BadgeStatus!
|
||||
icon: String!
|
||||
#createdAt: DateTime
|
||||
#updatedAt: DateTime
|
||||
createdAt: String
|
||||
updatedAt: String
|
||||
|
||||
|
||||
@ -1,13 +1,41 @@
|
||||
enum _CategoryOrdering {
|
||||
id_asc
|
||||
id_desc
|
||||
name_asc
|
||||
name_desc
|
||||
slug_asc
|
||||
slug_desc
|
||||
icon_asc
|
||||
icon_desc
|
||||
createdAt_asc
|
||||
createdAt_desc
|
||||
updatedAt_asc
|
||||
updatedAt_desc
|
||||
postCount_asc
|
||||
postCount_desc
|
||||
}
|
||||
|
||||
type Category {
|
||||
id: ID!
|
||||
name: String!
|
||||
slug: String
|
||||
icon: String!
|
||||
#createdAt: DateTime
|
||||
#updatedAt: DateTime
|
||||
createdAt: String
|
||||
updatedAt: String
|
||||
|
||||
posts: [Post]! @relation(name: "CATEGORIZED", direction: "IN")
|
||||
postCount: Int! @cypher(statement: "MATCH (this)<-[:CATEGORIZED]-(r:Post) RETURN COUNT(r)")
|
||||
}
|
||||
|
||||
type Query {
|
||||
Category(
|
||||
id: ID
|
||||
name: String
|
||||
slug: String
|
||||
icon: String
|
||||
createdAt: String
|
||||
updatedAt: String
|
||||
first: Int
|
||||
offset: Int
|
||||
orderBy: [_CategoryOrdering]
|
||||
): [Category]
|
||||
}
|
||||
|
||||
@ -1,3 +1,41 @@
|
||||
enum _CommentOrdering {
|
||||
id_asc
|
||||
id_desc
|
||||
content_asc
|
||||
content_desc
|
||||
createdAt_asc
|
||||
createdAt_desc
|
||||
updatedAt_asc
|
||||
updatedAt_desc
|
||||
}
|
||||
|
||||
input _CommentFilter {
|
||||
AND: [_CommentFilter!]
|
||||
OR: [_CommentFilter!]
|
||||
id: ID
|
||||
id_not: ID
|
||||
id_in: [ID!]
|
||||
id_not_in: [ID!]
|
||||
author: _UserFilter
|
||||
author_not: _UserFilter
|
||||
author_in: [_UserFilter!]
|
||||
author_not_in: [_UserFilter!]
|
||||
content: String
|
||||
content_not: String
|
||||
content_in: [String!]
|
||||
content_not_in: [String!]
|
||||
content_contains: String
|
||||
content_not_contains: String
|
||||
content_starts_with: String
|
||||
content_not_starts_with: String
|
||||
content_ends_with: String
|
||||
content_not_ends_with: String
|
||||
post: _PostFilter
|
||||
post_not: _PostFilter
|
||||
post_in: [_PostFilter!]
|
||||
post_not_in: [_PostFilter!]
|
||||
}
|
||||
|
||||
type Comment {
|
||||
id: ID!
|
||||
activityId: String
|
||||
@ -12,6 +50,19 @@ type Comment {
|
||||
disabledBy: User @relation(name: "DISABLED", direction: "IN")
|
||||
}
|
||||
|
||||
type Query {
|
||||
Comment(
|
||||
id: ID
|
||||
content: String
|
||||
createdAt: String
|
||||
updatedAt: String
|
||||
first: Int
|
||||
offset: Int
|
||||
orderBy: [_CommentOrdering]
|
||||
filter: _CommentFilter
|
||||
): [Comment]
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
CreateComment(
|
||||
id: ID
|
||||
|
||||
@ -3,8 +3,6 @@ type EMOTED @relation(name: "EMOTED") {
|
||||
to: Post
|
||||
|
||||
emotion: Emotion
|
||||
# createdAt: DateTime
|
||||
# updatedAt: DateTime
|
||||
createdAt: String
|
||||
updatedAt: String
|
||||
}
|
||||
|
||||
@ -2,9 +2,6 @@ type InvitationCode {
|
||||
id: ID!
|
||||
token: String
|
||||
generatedBy: User @relation(name: "GENERATED", direction: "IN")
|
||||
|
||||
#createdAt: DateTime
|
||||
#usedAt: DateTime
|
||||
createdAt: String
|
||||
}
|
||||
|
||||
|
||||
@ -1,26 +1,101 @@
|
||||
input _PostFilter {
|
||||
AND: [_PostFilter!]
|
||||
OR: [_PostFilter!]
|
||||
id: ID
|
||||
id_not: ID
|
||||
id_in: [ID!]
|
||||
id_not_in: [ID!]
|
||||
author: _UserFilter
|
||||
author_not: _UserFilter
|
||||
author_in: [_UserFilter!]
|
||||
author_not_in: [_UserFilter!]
|
||||
title: String
|
||||
title_not: String
|
||||
title_in: [String!]
|
||||
title_not_in: [String!]
|
||||
title_contains: String
|
||||
title_not_contains: String
|
||||
title_starts_with: String
|
||||
title_not_starts_with: String
|
||||
title_ends_with: String
|
||||
title_not_ends_with: String
|
||||
slug: String
|
||||
slug_not: String
|
||||
slug_in: [String!]
|
||||
slug_not_in: [String!]
|
||||
slug_contains: String
|
||||
slug_not_contains: String
|
||||
slug_starts_with: String
|
||||
slug_not_starts_with: String
|
||||
slug_ends_with: String
|
||||
slug_not_ends_with: String
|
||||
content: String
|
||||
content_not: String
|
||||
content_in: [String!]
|
||||
content_not_in: [String!]
|
||||
content_contains: String
|
||||
content_not_contains: String
|
||||
content_starts_with: String
|
||||
content_not_starts_with: String
|
||||
content_ends_with: String
|
||||
content_not_ends_with: String
|
||||
image: String
|
||||
visibility: Visibility
|
||||
visibility_not: Visibility
|
||||
visibility_in: [Visibility!]
|
||||
visibility_not_in: [Visibility!]
|
||||
language: String
|
||||
language_not: String
|
||||
language_in: [String!]
|
||||
language_not_in: [String!]
|
||||
pinned: Boolean # required for `maintainPinnedPost`
|
||||
tags: _TagFilter
|
||||
tags_not: _TagFilter
|
||||
tags_in: [_TagFilter!]
|
||||
tags_not_in: [_TagFilter!]
|
||||
tags_some: _TagFilter
|
||||
tags_none: _TagFilter
|
||||
tags_single: _TagFilter
|
||||
tags_every: _TagFilter
|
||||
categories: _CategoryFilter
|
||||
categories_not: _CategoryFilter
|
||||
categories_in: [_CategoryFilter!]
|
||||
categories_not_in: [_CategoryFilter!]
|
||||
categories_some: _CategoryFilter
|
||||
categories_none: _CategoryFilter
|
||||
categories_single: _CategoryFilter
|
||||
categories_every: _CategoryFilter
|
||||
comments: _CommentFilter
|
||||
comments_not: _CommentFilter
|
||||
comments_in: [_CommentFilter!]
|
||||
comments_not_in: [_CommentFilter!]
|
||||
comments_some: _CommentFilter
|
||||
comments_none: _CommentFilter
|
||||
comments_single: _CommentFilter
|
||||
comments_every: _CommentFilter
|
||||
emotions: _PostEMOTEDFilter
|
||||
emotions_not: _PostEMOTEDFilter
|
||||
emotions_in: [_PostEMOTEDFilter!]
|
||||
emotions_not_in: [_PostEMOTEDFilter!]
|
||||
emotions_some: _PostEMOTEDFilter
|
||||
emotions_none: _PostEMOTEDFilter
|
||||
emotions_single: _PostEMOTEDFilter
|
||||
emotions_every: _PostEMOTEDFilter
|
||||
}
|
||||
|
||||
enum _PostOrdering {
|
||||
id_asc
|
||||
id_desc
|
||||
activityId_asc
|
||||
activityId_desc
|
||||
objectId_asc
|
||||
objectId_desc
|
||||
title_asc
|
||||
title_desc
|
||||
slug_asc
|
||||
slug_desc
|
||||
content_asc
|
||||
content_desc
|
||||
contentExcerpt_asc
|
||||
contentExcerpt_desc
|
||||
image_asc
|
||||
image_desc
|
||||
visibility_asc
|
||||
visibility_desc
|
||||
deleted_asc
|
||||
deleted_desc
|
||||
disabled_asc
|
||||
disabled_desc
|
||||
createdAt_asc
|
||||
createdAt_desc
|
||||
updatedAt_asc
|
||||
@ -79,7 +154,7 @@ type Post {
|
||||
@cypher(
|
||||
statement: "MATCH (this)<-[:SHOUTED]-(r:User) WHERE NOT r.deleted = true AND NOT r.disabled = true RETURN COUNT(DISTINCT r)"
|
||||
)
|
||||
|
||||
|
||||
# Has the currently logged in user shouted that post?
|
||||
shoutedByCurrentUser: Boolean!
|
||||
@cypher(
|
||||
@ -128,6 +203,22 @@ type Mutation {
|
||||
}
|
||||
|
||||
type Query {
|
||||
Post(
|
||||
id: ID
|
||||
title: String
|
||||
slug: String
|
||||
content: String
|
||||
image: String
|
||||
visibility: Visibility
|
||||
pinned: Boolean
|
||||
createdAt: String
|
||||
updatedAt: String
|
||||
language: String
|
||||
first: Int
|
||||
offset: Int
|
||||
orderBy: [_PostOrdering]
|
||||
filter: _PostFilter
|
||||
): [Post]
|
||||
PostsEmotionsCountByEmotion(postId: ID!, data: _EMOTEDInput!): Int!
|
||||
PostsEmotionsByCurrentUser(postId: ID!): [String]
|
||||
profilePagePosts(filter: _PostFilter, first: Int, offset: Int, orderBy: [_PostOrdering]): [Post]
|
||||
|
||||
@ -1,3 +1,20 @@
|
||||
input _TagFilter {
|
||||
AND: [_TagFilter!]
|
||||
OR: [_TagFilter!]
|
||||
id: ID
|
||||
id_not: ID
|
||||
id_in: [ID!]
|
||||
id_not_in: [ID!]
|
||||
taggedPosts: _PostFilter
|
||||
taggedPosts_not: _PostFilter
|
||||
taggedPosts_in: [_PostFilter!]
|
||||
taggedPosts_not_in: [_PostFilter!]
|
||||
taggedPosts_some: _PostFilter
|
||||
taggedPosts_none: _PostFilter
|
||||
taggedPosts_single: _PostFilter
|
||||
taggedPosts_every: _PostFilter
|
||||
}
|
||||
|
||||
type Tag {
|
||||
id: ID!
|
||||
taggedPosts: [Post]! @relation(name: "TAGGED", direction: "IN")
|
||||
@ -6,3 +23,22 @@ type Tag {
|
||||
deleted: Boolean
|
||||
disabled: Boolean
|
||||
}
|
||||
|
||||
enum _TagOrdering {
|
||||
id_asc
|
||||
id_desc
|
||||
taggedCount_asc
|
||||
taggedCount_desc
|
||||
taggedCountUnique_asc
|
||||
taggedCountUnique_desc
|
||||
}
|
||||
|
||||
type Query {
|
||||
Tag(
|
||||
id: ID
|
||||
first: Int
|
||||
offset: Int
|
||||
orderBy: [_TagOrdering]
|
||||
filter: _TagFilter
|
||||
): [Tag]
|
||||
}
|
||||
|
||||
@ -1,3 +1,28 @@
|
||||
enum _UserOrdering {
|
||||
id_asc
|
||||
id_desc
|
||||
name_asc
|
||||
name_desc
|
||||
slug_asc
|
||||
slug_desc
|
||||
avatar_asc
|
||||
avatar_desc
|
||||
coverImg_asc
|
||||
coverImg_desc
|
||||
role_asc
|
||||
role_desc
|
||||
locationName_asc
|
||||
locationName_desc
|
||||
about_asc
|
||||
about_desc
|
||||
createdAt_asc
|
||||
createdAt_desc
|
||||
updatedAt_asc
|
||||
updatedAt_desc
|
||||
locale_asc
|
||||
locale_desc
|
||||
}
|
||||
|
||||
type User {
|
||||
id: ID!
|
||||
actorId: String
|
||||
@ -28,6 +53,7 @@ type User {
|
||||
termsAndConditionsAgreedAt: String
|
||||
|
||||
allowEmbedIframes: Boolean
|
||||
showShoutsPublicly: Boolean
|
||||
locale: String
|
||||
friends: [User]! @relation(name: "FRIENDS", direction: "BOTH")
|
||||
friendsCount: Int! @cypher(statement: "MATCH (this)<-[: FRIENDS]->(r: User) RETURN COUNT(DISTINCT r)")
|
||||
@ -91,12 +117,6 @@ input _UserFilter {
|
||||
id_not: ID
|
||||
id_in: [ID!]
|
||||
id_not_in: [ID!]
|
||||
id_contains: ID
|
||||
id_not_contains: ID
|
||||
id_starts_with: ID
|
||||
id_not_starts_with: ID
|
||||
id_ends_with: ID
|
||||
id_not_ends_with: ID
|
||||
friends: _UserFilter
|
||||
friends_not: _UserFilter
|
||||
friends_in: [_UserFilter!]
|
||||
@ -127,8 +147,7 @@ input _UserFilter {
|
||||
type Query {
|
||||
User(
|
||||
id: ID
|
||||
email: String
|
||||
actorId: String
|
||||
email: String # admins need to search for a user sometimes
|
||||
name: String
|
||||
slug: String
|
||||
avatar: String
|
||||
@ -138,14 +157,6 @@ type Query {
|
||||
about: String
|
||||
createdAt: String
|
||||
updatedAt: String
|
||||
friendsCount: Int
|
||||
followingCount: Int
|
||||
followedByCount: Int
|
||||
followedByCurrentUser: Boolean
|
||||
contributionsCount: Int
|
||||
commentedCount: Int
|
||||
shoutedCount: Int
|
||||
badgesCount: Int
|
||||
first: Int
|
||||
offset: Int
|
||||
orderBy: [_UserOrdering]
|
||||
@ -170,6 +181,8 @@ type Mutation {
|
||||
termsAndConditionsAgreedVersion: String
|
||||
termsAndConditionsAgreedAt: String
|
||||
allowEmbedIframes: Boolean
|
||||
showShoutsPublicly: Boolean
|
||||
|
||||
locale: String
|
||||
): User
|
||||
|
||||
|
||||
@ -17,6 +17,7 @@ export default function create() {
|
||||
termsAndConditionsAgreedVersion: '0.0.1',
|
||||
termsAndConditionsAgreedAt: '2019-08-01T10:47:19.212Z',
|
||||
allowEmbedIframes: false,
|
||||
showShoutsPublicly: false,
|
||||
locale: 'en',
|
||||
}
|
||||
defaults.slug = slugify(defaults.name, { lower: true })
|
||||
|
||||
@ -4,7 +4,7 @@ import { createTestClient } from 'apollo-server-testing'
|
||||
import createServer from '../server'
|
||||
import Factory from './factories'
|
||||
import { neode as getNeode, getDriver } from '../bootstrap/neo4j'
|
||||
import { gql } from '../jest/helpers'
|
||||
import { gql } from '../helpers/jest'
|
||||
|
||||
const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
||||
|
||||
|
||||
@ -4,7 +4,6 @@ import { expect } from 'chai'
|
||||
// import { client } from '../../../src/activitypub/apollo-client'
|
||||
import { GraphQLClient } from 'graphql-request'
|
||||
import Factory from '../../../src/seed/factories'
|
||||
import { host } from '../../../src/jest/helpers'
|
||||
const debug = require('debug')('ea:test:steps')
|
||||
|
||||
const factory = Factory()
|
||||
|
||||
@ -1075,10 +1075,10 @@
|
||||
url-regex "~4.1.1"
|
||||
video-extensions "~1.1.0"
|
||||
|
||||
"@metascraper/helpers@^5.7.17":
|
||||
version "5.7.17"
|
||||
resolved "https://registry.yarnpkg.com/@metascraper/helpers/-/helpers-5.7.17.tgz#401897c7239090ca7149b83e581712845bbb3709"
|
||||
integrity sha512-t21LqfDpaIrWg2JaivXG6mVzUsIVW05cAsKySA5Tj9Hgi9oZXxaaNes5XipOzk6P242RI48SDo7CkSbYiio7Tw==
|
||||
"@metascraper/helpers@^5.8.7":
|
||||
version "5.8.7"
|
||||
resolved "https://registry.yarnpkg.com/@metascraper/helpers/-/helpers-5.8.7.tgz#b05f83f2a90001f7753c18a8b1bb978bd7c2f9d9"
|
||||
integrity sha512-gDErMAA3d1CdkGxvAG4cDi7D2+fReZpD6lzYNJ/gsq45U3Pdz7ltsAvbp4amK92bGKYYPZtnUq85Wrr+Q+e06Q==
|
||||
dependencies:
|
||||
audio-extensions "0.0.0"
|
||||
chrono-node "~1.3.11"
|
||||
@ -1093,7 +1093,7 @@
|
||||
isostring "0.0.1"
|
||||
lodash "~4.17.15"
|
||||
memoize-one "~5.1.1"
|
||||
mime-types "~2.1.24"
|
||||
mime-types "~2.1.25"
|
||||
normalize-url "~4.5.0"
|
||||
smartquotes "~2.3.1"
|
||||
title "~3.4.1"
|
||||
@ -1183,10 +1183,10 @@
|
||||
"@sentry/types" "5.7.1"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sentry/node@^5.8.0":
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.8.0.tgz#68ec032b0e7fb840cc8ccc1b39c09ac6febc1046"
|
||||
integrity sha512-hIzt1BysyQJez8ChgWpFkLcGq3t/HaLMqzrXF5vu+Uuekl5OfwsvzZ+8Dlv78rI4CvlL9a2EuI/94iqUNwhOSQ==
|
||||
"@sentry/node@^5.9.0":
|
||||
version "5.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.9.0.tgz#9a8da70990e64c88a391ef86dcf29f43e0a52e59"
|
||||
integrity sha512-1CWwSGhRfMr4Bvt1i0vIms+BBZd4dBzlDyWpyCboodCXF1rTJRci9roQ+Wh9XWwFEWvgDD2PzuKzfvu638v2Wg==
|
||||
dependencies:
|
||||
"@sentry/core" "5.8.0"
|
||||
"@sentry/hub" "5.8.0"
|
||||
@ -1764,10 +1764,10 @@ apollo-server-caching@^0.5.0:
|
||||
dependencies:
|
||||
lru-cache "^5.0.0"
|
||||
|
||||
apollo-server-core@^2.9.7:
|
||||
version "2.9.7"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-2.9.7.tgz#0f32344af90dec445ac780be95350bfa736fc416"
|
||||
integrity sha512-EqKyROy+21sM93YHjGpy6wlnzK/vH0fnZh7RCf3uB69aQ3OjgdP4AQ5oWRQ62NDN+aoic7OLhChSDJeDonq/NQ==
|
||||
apollo-server-core@^2.9.9:
|
||||
version "2.9.9"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-2.9.9.tgz#73df4989ac0ad09d20c20ef3e06f8c816bc7a13f"
|
||||
integrity sha512-JxtYDasqeem5qUwPrCVh2IsBOgSQF4MKrRgy8dpxd+ymWfaaVelCUows1VE8vghgRxqDExnM9ibOxcZeI6mO6g==
|
||||
dependencies:
|
||||
"@apollographql/apollo-tools" "^0.4.0"
|
||||
"@apollographql/graphql-playground-html" "1.6.24"
|
||||
@ -1804,10 +1804,10 @@ apollo-server-errors@^2.3.4:
|
||||
resolved "https://registry.yarnpkg.com/apollo-server-errors/-/apollo-server-errors-2.3.4.tgz#b70ef01322f616cbcd876f3e0168a1a86b82db34"
|
||||
integrity sha512-Y0PKQvkrb2Kd18d1NPlHdSqmlr8TgqJ7JQcNIfhNDgdb45CnqZlxL1abuIRhr8tiw8OhVOcFxz2KyglBi8TKdA==
|
||||
|
||||
apollo-server-express@^2.9.7:
|
||||
version "2.9.7"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-2.9.7.tgz#54fbaf93b68f0123ecb1dead26cbfda5b15bd10e"
|
||||
integrity sha512-+DuJk1oq34Zx0bLYzgBgJH/eXS0JNxw2JycHQvV0+PAQ0Qi01oomJRA2r1S5isnfnSAnHb2E9jyBTptoHdw3MQ==
|
||||
apollo-server-express@^2.9.7, apollo-server-express@^2.9.9:
|
||||
version "2.9.9"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server-express/-/apollo-server-express-2.9.9.tgz#2a379217d7a7be012f0329be8bf89a63e181d42e"
|
||||
integrity sha512-qltC3ttGz8zvrut7HzrcqKOUg0vHpvVyYeeOy8jvghZpqXyWFuJhnw6uxAFcKNKCPl3mJ1psji83P1Um2ceJgg==
|
||||
dependencies:
|
||||
"@apollographql/graphql-playground-html" "1.6.24"
|
||||
"@types/accepts" "^1.3.5"
|
||||
@ -1815,7 +1815,7 @@ apollo-server-express@^2.9.7:
|
||||
"@types/cors" "^2.8.4"
|
||||
"@types/express" "4.17.1"
|
||||
accepts "^1.3.5"
|
||||
apollo-server-core "^2.9.7"
|
||||
apollo-server-core "^2.9.9"
|
||||
apollo-server-types "^0.2.5"
|
||||
body-parser "^1.18.3"
|
||||
cors "^2.8.4"
|
||||
@ -1833,12 +1833,12 @@ apollo-server-plugin-base@^0.6.5:
|
||||
dependencies:
|
||||
apollo-server-types "^0.2.5"
|
||||
|
||||
apollo-server-testing@~2.9.7:
|
||||
version "2.9.7"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server-testing/-/apollo-server-testing-2.9.7.tgz#8d05058ddda4a715fac2fefb2b8e973e409a7672"
|
||||
integrity sha512-yy18ceSyX2a9UYcs6X7K0xFZwcS1riEh99zdWU0XB/yzzTIdGZkFYeJmV/zjpGL3CFyXF7Va/muo6otl4nDOsA==
|
||||
apollo-server-testing@~2.9.9:
|
||||
version "2.9.9"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server-testing/-/apollo-server-testing-2.9.9.tgz#451836fa2e077e93f45182dde50ca72c15be2e84"
|
||||
integrity sha512-ejbFJLrprMDBZWdi4hOZkZUSMzNJvX5NVDXWWUFHAySbY2zDsbHrQ9jE/2KQJrI3Q93jUgmpUTAu6kS0cjxt4Q==
|
||||
dependencies:
|
||||
apollo-server-core "^2.9.7"
|
||||
apollo-server-core "^2.9.9"
|
||||
|
||||
apollo-server-types@^0.2.5:
|
||||
version "0.2.5"
|
||||
@ -1849,13 +1849,13 @@ apollo-server-types@^0.2.5:
|
||||
apollo-server-caching "^0.5.0"
|
||||
apollo-server-env "^2.4.3"
|
||||
|
||||
apollo-server@~2.9.7:
|
||||
version "2.9.7"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server/-/apollo-server-2.9.7.tgz#aab337b75c04ddea0fa9b171b30c4e91932c04d8"
|
||||
integrity sha512-maGGCsK4Ft5ucox5ZJf6oaKhgPvzHY3jXWbA1F/mn0/EYX8e1RVO3Qtj8aQQ0/vCKx8r4vYgj+ctqBVaN/nr4A==
|
||||
apollo-server@~2.9.9:
|
||||
version "2.9.9"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server/-/apollo-server-2.9.9.tgz#f10249fa9884be2a0ad59876e301fdfccb456208"
|
||||
integrity sha512-b4IfGxZDzhOnfaPTinAD0rx8XpgxkVMjNuwooRULOJEeYG8Vd/OiBYSS7LSGy1g3hdiLBgJhMFC0ce7pjdcyFw==
|
||||
dependencies:
|
||||
apollo-server-core "^2.9.7"
|
||||
apollo-server-express "^2.9.7"
|
||||
apollo-server-core "^2.9.9"
|
||||
apollo-server-express "^2.9.9"
|
||||
express "^4.0.0"
|
||||
graphql-subscriptions "^1.0.0"
|
||||
graphql-tools "^4.0.0"
|
||||
@ -2583,6 +2583,11 @@ commander@^2.8.1, commander@~2.20.0:
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
|
||||
integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
|
||||
|
||||
commander@^2.9.0:
|
||||
version "2.20.3"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||
|
||||
commander@^3.0.1:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e"
|
||||
@ -2778,6 +2783,11 @@ css-what@2.1:
|
||||
resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2"
|
||||
integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==
|
||||
|
||||
cssfilter@0.0.10:
|
||||
version "0.0.10"
|
||||
resolved "https://registry.yarnpkg.com/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae"
|
||||
integrity sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4=
|
||||
|
||||
cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0":
|
||||
version "0.3.8"
|
||||
resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a"
|
||||
@ -2790,10 +2800,10 @@ cssstyle@^1.0.0:
|
||||
dependencies:
|
||||
cssom "0.3.x"
|
||||
|
||||
cucumber-expressions@^8.0.1:
|
||||
version "8.0.1"
|
||||
resolved "https://registry.yarnpkg.com/cucumber-expressions/-/cucumber-expressions-8.0.1.tgz#47eb87dcb626e90a4672986da1130f3c470b9e3d"
|
||||
integrity sha512-g+A+tUEafNofe6ErwvOkqaMvDj9NuOr0GouGotpw4r5yK2d4144o9/6sQpXBr2YXbRy5ItmER/2bzAyDAzhPyQ==
|
||||
cucumber-expressions@^8.1.0:
|
||||
version "8.2.1"
|
||||
resolved "https://registry.yarnpkg.com/cucumber-expressions/-/cucumber-expressions-8.2.1.tgz#e250063993350df106a8664c90a414814f555e2d"
|
||||
integrity sha512-6n5JKbAzXfIiwyu2UyUcOmO83QmuSme25+Dw2taK6VNOybOfRkh4yNMA9VtuAJHOmsX3/8l0OVjTbE8lHnjOHA==
|
||||
dependencies:
|
||||
becke-ch--regex--s0-0-v1--base--pl--lib "^1.4.0"
|
||||
xregexp "^4.2.4"
|
||||
@ -2803,17 +2813,17 @@ cucumber-tag-expressions@^2.0.2:
|
||||
resolved "https://registry.yarnpkg.com/cucumber-tag-expressions/-/cucumber-tag-expressions-2.0.2.tgz#aac27aae3690818ec15235bd056282dad8a2d2b8"
|
||||
integrity sha512-DohmT4X641KX/sb96bdb7J2kXNcQBPrYmf3Oc5kiHCLfzFMWx/o2kB4JvjvQPZnYuA9lRt6pqtArM5gvUn4uzw==
|
||||
|
||||
cucumber@~6.0.3:
|
||||
version "6.0.3"
|
||||
resolved "https://registry.yarnpkg.com/cucumber/-/cucumber-6.0.3.tgz#bf69ecc992772e580dabe265b2ed06ddab13d076"
|
||||
integrity sha512-FSx7xdAQfFjcxp/iRBAuCFSXp2iJP1tF2Q5k/a67YgHiYbnwsD9F+UNv9ZG90LFHNsNQhb+67AmVxHkp4JRDpg==
|
||||
cucumber@~6.0.5:
|
||||
version "6.0.5"
|
||||
resolved "https://registry.yarnpkg.com/cucumber/-/cucumber-6.0.5.tgz#cdc752ad18b551bcf7bc92774c925302f4408714"
|
||||
integrity sha512-x+W9Fwk6TvcapQsYMxwFU5AsQJDOIJVGrPKmH15OC7jzb9/Dk7Hb0ZAyw4WcpaDcUDRc8bi2k2yJejDp5eTRlg==
|
||||
dependencies:
|
||||
assertion-error-formatter "^3.0.0"
|
||||
bluebird "^3.4.1"
|
||||
cli-table3 "^0.5.1"
|
||||
colors "^1.1.2"
|
||||
commander "^3.0.1"
|
||||
cucumber-expressions "^8.0.1"
|
||||
cucumber-expressions "^8.1.0"
|
||||
cucumber-tag-expressions "^2.0.2"
|
||||
duration "^0.2.1"
|
||||
escape-string-regexp "^2.0.0"
|
||||
@ -3289,10 +3299,10 @@ escodegen@^1.9.1:
|
||||
optionalDependencies:
|
||||
source-map "~0.6.1"
|
||||
|
||||
eslint-config-prettier@~6.5.0:
|
||||
version "6.5.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.5.0.tgz#aaf9a495e2a816865e541bfdbb73a65cc162b3eb"
|
||||
integrity sha512-cjXp8SbO9VFGW/Z7mbTydqS9to8Z58E5aYhj3e1+Hx7lS9s6gL5ILKNpCqZAFOVYRcSkWPFYljHrEh8QFEK5EQ==
|
||||
eslint-config-prettier@~6.7.0:
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.7.0.tgz#9a876952e12df2b284adbd3440994bf1f39dfbb9"
|
||||
integrity sha512-FamQVKM3jjUVwhG4hEMnbtsq7xOIDm+SY5iBPfR8gKsJoAB2IQnNF+bk1+8Fy44Nq7PPJaLvkRxILYdJWoguKQ==
|
||||
dependencies:
|
||||
get-stdin "^6.0.0"
|
||||
|
||||
@ -3342,10 +3352,10 @@ eslint-plugin-import@~2.18.2:
|
||||
read-pkg-up "^2.0.0"
|
||||
resolve "^1.11.0"
|
||||
|
||||
eslint-plugin-jest@~23.0.3:
|
||||
version "23.0.3"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.0.3.tgz#d3f157f7791f97713372c13259ba1dfc436eb4c1"
|
||||
integrity sha512-9cNxr66zeOyz1S9AkQL4/ouilR6QHpYj8vKOQZ60fu9hAt5PJWS4KqWqfr1aqN5NFEZSPjFOla2Azn+KTWiGwg==
|
||||
eslint-plugin-jest@~23.0.4:
|
||||
version "23.0.4"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.0.4.tgz#1ab81ffe3b16c5168efa72cbd4db14d335092aa0"
|
||||
integrity sha512-OaP8hhT8chJNodUPvLJ6vl8gnalcsU/Ww1t9oR3HnGdEWjm/DdCCUXLOral+IPGAeWu/EwgVQCK/QtxALpH1Yw==
|
||||
dependencies:
|
||||
"@typescript-eslint/experimental-utils" "^2.5.0"
|
||||
|
||||
@ -3981,7 +3991,7 @@ glob-parent@^5.0.0:
|
||||
dependencies:
|
||||
is-glob "^4.0.1"
|
||||
|
||||
glob@7.1.6:
|
||||
glob@7.1.6, glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
|
||||
version "7.1.6"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
|
||||
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
|
||||
@ -3993,18 +4003,6 @@ glob@7.1.6:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
|
||||
version "7.1.5"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.5.tgz#6714c69bee20f3c3e64c4dd905553e532b40cdc0"
|
||||
integrity sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.0.4"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
global-dirs@^0.1.0:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445"
|
||||
@ -5689,6 +5687,11 @@ map-cache@^0.2.2:
|
||||
resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
|
||||
integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=
|
||||
|
||||
map-values-deep@~1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/map-values-deep/-/map-values-deep-1.0.2.tgz#b0176a1c463158ae33e24de0ce8150621a2b30d3"
|
||||
integrity sha512-br+tp4aANql3WnpDRjD14H7hHopPlJRnzCL0ZlGCRHAQZTU0g0x1rUQFq/ikb3zZQK+lW2AG7RJi+CFfQ8kSPA==
|
||||
|
||||
map-visit@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f"
|
||||
@ -5730,19 +5733,19 @@ merge-stream@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
|
||||
integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
|
||||
|
||||
metascraper-audio@^5.7.17:
|
||||
version "5.7.17"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-audio/-/metascraper-audio-5.7.17.tgz#b8e78a797deb155b02f30bcbe39da554bf1bf898"
|
||||
integrity sha512-g11lRNVor5Pu4D1j3tL7aakSQM51CUl2Evp8QgFKcuYGjF+a1RiGq6veojiTf/9nWcKX8dUSTUJkQSIzdoJrFQ==
|
||||
metascraper-audio@^5.8.7:
|
||||
version "5.8.7"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-audio/-/metascraper-audio-5.8.7.tgz#ce27b1f4056c1d1cbaa2cec0e819c3704f38fff4"
|
||||
integrity sha512-ew9KZKOIl3u0500j7qIR/ZNiVtSohuyyiIWSxJVEeeguEOwAhMpOrpYAEkvKRo5CB89F2PNBIsXJIzMC4BWFrw==
|
||||
dependencies:
|
||||
"@metascraper/helpers" "^5.7.17"
|
||||
"@metascraper/helpers" "^5.8.7"
|
||||
|
||||
metascraper-author@^5.7.17:
|
||||
version "5.7.17"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-author/-/metascraper-author-5.7.17.tgz#0403eaa4d1992152246f01616fac1d52b0583c8a"
|
||||
integrity sha512-vaMAn6glCr9f2PGvNObqMI7ECtQ7+CMkXSxKyn3fyxRVKnV95fBR+xi4+UJ2DWqTvVQ6t7gZwlzFWA4CwxfniQ==
|
||||
metascraper-author@^5.8.7:
|
||||
version "5.8.7"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-author/-/metascraper-author-5.8.7.tgz#c29db97a24af801101008a547caea6a33a56e467"
|
||||
integrity sha512-PwuCZvHnDm10Q1zMQllpCLjtlYR1zSF+rDCRkf/TUuBC/ozz27/JkXDL+ml2nmK8IQGLGRUQKOzrQ0vVMFKvQw==
|
||||
dependencies:
|
||||
"@metascraper/helpers" "^5.7.17"
|
||||
"@metascraper/helpers" "^5.8.7"
|
||||
lodash "~4.17.15"
|
||||
|
||||
metascraper-clearbit-logo@^5.3.0:
|
||||
@ -5752,28 +5755,28 @@ metascraper-clearbit-logo@^5.3.0:
|
||||
dependencies:
|
||||
got "~9.6.0"
|
||||
|
||||
metascraper-date@^5.7.17:
|
||||
version "5.7.17"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-date/-/metascraper-date-5.7.17.tgz#8777bc5deaccce1235ed0b2eb8f0746c981ee245"
|
||||
integrity sha512-OPKXu7S+S6JoZNVV9Dox6OIG2x5hzDx2J3IzMwzQwVdKzulMPSFMLCcJU8zLZ03dajSOszRf8aL1eSBfZscpIw==
|
||||
metascraper-date@^5.8.7:
|
||||
version "5.8.7"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-date/-/metascraper-date-5.8.7.tgz#146733ecce34f8d4a53c7c6ddcfc51c033287757"
|
||||
integrity sha512-9+IslaGg+J+4cwPU5qu/MEexkoWj7sBxycmCA6vgfuCQCqNwlQ68vk2a/UVDw8OJOYjwX81JGrzxOqrQP0/kXw==
|
||||
dependencies:
|
||||
"@metascraper/helpers" "^5.7.17"
|
||||
"@metascraper/helpers" "^5.8.7"
|
||||
|
||||
metascraper-description@^5.7.17:
|
||||
version "5.7.17"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-description/-/metascraper-description-5.7.17.tgz#b0daa54d0345546ececcc033065790402aabb5ec"
|
||||
integrity sha512-cQfg9Spl3FLK2x8O7DvecwSYEBUmRjtdZW2y1EVqHsOKwT13SeUy1kp+lZa8+8vFh4o8oJPzXHxgbLhAfAmVqQ==
|
||||
metascraper-description@^5.8.7:
|
||||
version "5.8.7"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-description/-/metascraper-description-5.8.7.tgz#e85ce218daf33b74813b1523ad7dc7dc3fb128af"
|
||||
integrity sha512-KOv5gnQVvGF1CgpUczu7KJm76rWJ7SH5UFcqFST60hRNgR9xy0y3aHbVDOhZkjNN4UKqnxMF6XTS/WaQxCK/AA==
|
||||
dependencies:
|
||||
"@metascraper/helpers" "^5.7.17"
|
||||
"@metascraper/helpers" "^5.8.7"
|
||||
|
||||
metascraper-image@^5.7.17:
|
||||
version "5.7.17"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-image/-/metascraper-image-5.7.17.tgz#186b29979cb8aefc6c21d0342c386a8fef80be55"
|
||||
integrity sha512-bwAUJrJibJ+fJGxL8T789Ki1z+8sqsz0sqb3W+mfR/ZLkhCu+jWLYqPVtMgTPM9Zaqqqxg5uTQs1uAVrnguKDA==
|
||||
metascraper-image@^5.8.7:
|
||||
version "5.8.7"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-image/-/metascraper-image-5.8.7.tgz#d24697c5b5a6ba688948c48fadcb5fffeb6c703d"
|
||||
integrity sha512-OMK+PFnHeavCSuEJY5tFkG5tdl/luYmPys7PKkJIwC8A8q5qoAC0InIUu+c0SDrdf4nzOj083DZTp32YQxYF5A==
|
||||
dependencies:
|
||||
"@metascraper/helpers" "^5.7.17"
|
||||
"@metascraper/helpers" "^5.8.7"
|
||||
|
||||
metascraper-lang-detector@^4.8.5:
|
||||
metascraper-lang-detector@^4.10.2:
|
||||
version "4.10.2"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-lang-detector/-/metascraper-lang-detector-4.10.2.tgz#45744bc331125c098e8b27716d76740161b121d2"
|
||||
integrity sha512-Lz1d5v/i1j08gQYz7sCdoxjOx94ArLV4UucUhGZeQpR4E6dK47V6aqfYwODRe2XAqhaU+3oLnbAipoHkOeZXiw==
|
||||
@ -5782,81 +5785,80 @@ metascraper-lang-detector@^4.8.5:
|
||||
franc "~4.0.0"
|
||||
iso-639-3 "~1.1.0"
|
||||
|
||||
metascraper-lang@^5.7.17:
|
||||
version "5.7.17"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-lang/-/metascraper-lang-5.7.17.tgz#3952db650bcd909fff0308d1d2254e954a0c0028"
|
||||
integrity sha512-G/XqySeDpZmoV1rgWeMs/hmX1NFX0IN2w4viNdgdMRXB+lhqeyk5Z20x9ssPAqiJ4Ab6tyR274NkgYa0ZNRMDw==
|
||||
metascraper-lang@^5.8.7:
|
||||
version "5.8.7"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-lang/-/metascraper-lang-5.8.7.tgz#5214af961d55b7b4c98e679fffe7477a0f3f9c53"
|
||||
integrity sha512-ASidffvAmnankJtb9BIqVyRRlcz0uJ5mAbkAoWL1xkd9GyUxRLvkCjKq/pvsapASNabfqjwbgSj7hO8mv5hbkQ==
|
||||
dependencies:
|
||||
"@metascraper/helpers" "^5.7.17"
|
||||
"@metascraper/helpers" "^5.8.7"
|
||||
|
||||
metascraper-logo@^5.7.17:
|
||||
version "5.7.17"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-logo/-/metascraper-logo-5.7.17.tgz#b26e2fb38e94cfe9ec9dfc7e28d8da26a0a0689d"
|
||||
integrity sha512-S4aqxN4Qi3UXDLN4HhinEuQHUopYXbFw0Y5Cwj9TbGKfESeQ1n6Jm4eOgGifEYyyZMSeRR9li189EK3YPnYcFg==
|
||||
metascraper-logo@^5.8.7:
|
||||
version "5.8.7"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-logo/-/metascraper-logo-5.8.7.tgz#5efb7e6c5f91ccad812e2d9ec3facfef179f40b6"
|
||||
integrity sha512-QudGVJBBeXLWU54Xw2PmnsTf+qPUnbyYaOl4aFLg2wkLLza1GbuvOYGMiH9Y8k0WcRoesi9sQk+P0a/611blew==
|
||||
dependencies:
|
||||
"@metascraper/helpers" "^5.7.17"
|
||||
"@metascraper/helpers" "^5.8.7"
|
||||
|
||||
metascraper-publisher@^5.7.17:
|
||||
version "5.7.17"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-publisher/-/metascraper-publisher-5.7.17.tgz#38455e035d8d34c42eff529316ee15f31726d641"
|
||||
integrity sha512-BxiweB0vxXX0UF2YVxzwC7Y8X0A5mU+eaa6TsTrTGHPBWeZCUJaLJ2Ge35c00SIC+USgdu8KFyzF6+pJBObwvQ==
|
||||
metascraper-publisher@^5.8.7:
|
||||
version "5.8.7"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-publisher/-/metascraper-publisher-5.8.7.tgz#2b67f04db46123f9c6d57eaa3de610921fd28e01"
|
||||
integrity sha512-vVfoyqGPxKWWQjvBL0gz4Xyol3QYdr5HWSs9DI7cLrlIDExOByPPah5bZVSijeseeKymyf36BvCm54+chOZN5g==
|
||||
dependencies:
|
||||
"@metascraper/helpers" "^5.7.17"
|
||||
"@metascraper/helpers" "^5.8.7"
|
||||
|
||||
metascraper-soundcloud@^5.7.17:
|
||||
version "5.7.17"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-soundcloud/-/metascraper-soundcloud-5.7.17.tgz#925fc91505b69f1e3e7f0c535567c7918f8afbd9"
|
||||
integrity sha512-yllxXR0AHQmJLXCua+CJtjzmNr9I+mU/H23ED+S2t9Yd07xQDmqL8pkkuD8DAAy7aC6oIL0qghQPwk8qdM97Ug==
|
||||
metascraper-soundcloud@^5.8.7:
|
||||
version "5.8.7"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-soundcloud/-/metascraper-soundcloud-5.8.7.tgz#a557f070671978730ea06d18be3d5668cf323ab5"
|
||||
integrity sha512-qzwT7igIUi0k8NYC31lfLBeJEIUSxgJvQX3LC1JMxrEue5YMmE86SZRYASGemhMzhW5LtM/oA9jQECT3a8enJA==
|
||||
dependencies:
|
||||
"@metascraper/helpers" "^5.7.17"
|
||||
memoize-one "~5.1.1"
|
||||
"@metascraper/helpers" "^5.8.7"
|
||||
tldts "~5.6.1"
|
||||
|
||||
metascraper-title@^5.7.17:
|
||||
version "5.7.17"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-title/-/metascraper-title-5.7.17.tgz#5b947635361bfb4d7557eadcb623489c812322e6"
|
||||
integrity sha512-YCEbiU2MbPMLulXmLbSBN/N7ti9tBVr45yqMKSuFsWiNJ98bFsM1IQp1LN5KqRQmNkOg+8JsYgK+R9vqYwaGjg==
|
||||
metascraper-title@^5.8.7:
|
||||
version "5.8.7"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-title/-/metascraper-title-5.8.7.tgz#aecbbd9515bd74d2aeafa587c83447d926508ba0"
|
||||
integrity sha512-u+5KeJbsFKpi+pMnG71Gd49OLDQpkjiGIRTddhCZQhb45qHoTlGKN1nZuQ8nqJI6+ARWicFqtquomkaRXfBEnw==
|
||||
dependencies:
|
||||
"@metascraper/helpers" "^5.7.17"
|
||||
"@metascraper/helpers" "^5.8.7"
|
||||
lodash "~4.17.15"
|
||||
|
||||
metascraper-url@^5.7.17:
|
||||
version "5.7.17"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-url/-/metascraper-url-5.7.17.tgz#e8ba40a17a59b54139f42d6e3cf430dc6f32e7d7"
|
||||
integrity sha512-7OOhCXpxdMiJatrbxa9rqLmUT/t/s34PDgtknoE/2FfmZY7X/xyORamcuqUHjV37sOpCPTun+GcJL4l3ddCi3Q==
|
||||
metascraper-url@^5.8.7:
|
||||
version "5.8.7"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-url/-/metascraper-url-5.8.7.tgz#8c04a8f9b82af1058145f21788655b7b6b04fd9c"
|
||||
integrity sha512-K79mT509wV6B1Ak9vSslAbDPQMMRjjWowVgjcby5bOyFpO2j7mQkQIZYobEFpYLHlpb2R9myWJaTKAZe9KrF0A==
|
||||
dependencies:
|
||||
"@metascraper/helpers" "^5.7.17"
|
||||
"@metascraper/helpers" "^5.8.7"
|
||||
|
||||
metascraper-video@^5.7.17:
|
||||
version "5.7.17"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-video/-/metascraper-video-5.7.17.tgz#414d4641fbea667e73c42fe3706d673ee4c4aec5"
|
||||
integrity sha512-lftJGynCVNfC15eyMW7tN3QWJl9T2sVNCgP0dZsW8OC1hWQM7WY3PW8yYd2PP6nUuwOTjNLL1F4oWNhldWrE8A==
|
||||
metascraper-video@^5.8.7:
|
||||
version "5.8.7"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-video/-/metascraper-video-5.8.7.tgz#7a5d1e8955f9a65891908eef319683b6176765a2"
|
||||
integrity sha512-J4OJlB+nla8ITwqH2H6dgQ+nrecYILVhsGFKG54p2qsSokXwgZrQ4P7WhUMd0VpBsYuebcRgdzY8OGUDb+7l0Q==
|
||||
dependencies:
|
||||
"@metascraper/helpers" "^5.7.17"
|
||||
"@metascraper/helpers" "^5.8.7"
|
||||
lodash "~4.17.15"
|
||||
|
||||
metascraper-youtube@^5.7.17:
|
||||
version "5.7.17"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-youtube/-/metascraper-youtube-5.7.17.tgz#a3bdf06bbc9aa3766f08a779fa880d8a3fda9f8c"
|
||||
integrity sha512-CZX03wX8ui8fjx+iBZCiAGdSKy4dMFiDrVSPmTMK2W8sn2guYv2QQ41g8gruFJgrF+m+mCOUG6KYgy3B/v5LdQ==
|
||||
metascraper-youtube@^5.8.7:
|
||||
version "5.8.7"
|
||||
resolved "https://registry.yarnpkg.com/metascraper-youtube/-/metascraper-youtube-5.8.7.tgz#8a799602788d90ed34a885f4754fc98aa5e917ca"
|
||||
integrity sha512-00b+KNoRxDYc+Pbx25a74ZV2hX4ARqKY9J70AFZm/kstmxh2VOApyuIkuNkQM8PgTqEMXm3lAFiz6aYMnPcVMg==
|
||||
dependencies:
|
||||
"@metascraper/helpers" "^5.7.17"
|
||||
"@metascraper/helpers" "^5.8.7"
|
||||
get-video-id "~3.1.4"
|
||||
is-reachable "~4.0.0"
|
||||
memoize-one "~5.1.1"
|
||||
p-locate "~4.1.0"
|
||||
|
||||
metascraper@^4.10.3:
|
||||
version "4.10.3"
|
||||
resolved "https://registry.yarnpkg.com/metascraper/-/metascraper-4.10.3.tgz#8a97ed2e914e81d1dbc1f17a5b1e64f1b804493f"
|
||||
integrity sha512-wNQm5A/PIxWcahaMwI+b3rOmmXRDNmjyF6Q15dHYXEqYoGl3dFaaT4lnTTm8yntvE+fOj8+o51ON2FBdstxbsA==
|
||||
metascraper@^5.8.8:
|
||||
version "5.8.8"
|
||||
resolved "https://registry.yarnpkg.com/metascraper/-/metascraper-5.8.8.tgz#9fbf6913f55bb448a9195e40e38f3599bc5a818f"
|
||||
integrity sha512-z4G3SXGBVnd0+FSHqR3LJF+6emO03GlY2KoOTqsFCnRuY0B72nJyR/NRRYLn4PRX6PMQ6QZ+GWKa7oxBX6hZqQ==
|
||||
dependencies:
|
||||
"@metascraper/helpers" "^4.10.2"
|
||||
"@metascraper/helpers" "^5.8.7"
|
||||
cheerio "~1.0.0-rc.2"
|
||||
cheerio-advanced-selectors "~2.0.1"
|
||||
lodash "~4.17.11"
|
||||
p-reduce "~2.0.0"
|
||||
lodash "~4.17.15"
|
||||
map-values-deep "~1.0.2"
|
||||
whoops "~4.0.2"
|
||||
xss "~1.0.6"
|
||||
|
||||
methods@^1.1.1, methods@^1.1.2, methods@~1.1.2:
|
||||
version "1.1.2"
|
||||
@ -5887,6 +5889,11 @@ mime-db@1.40.0:
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32"
|
||||
integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==
|
||||
|
||||
mime-db@1.42.0:
|
||||
version "1.42.0"
|
||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac"
|
||||
integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==
|
||||
|
||||
mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.22, mime-types@~2.1.24:
|
||||
version "2.1.24"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81"
|
||||
@ -5894,6 +5901,13 @@ mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.22, mime-types@~2.1.24:
|
||||
dependencies:
|
||||
mime-db "1.40.0"
|
||||
|
||||
mime-types@~2.1.25:
|
||||
version "2.1.25"
|
||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.25.tgz#39772d46621f93e2a80a856c53b86a62156a6437"
|
||||
integrity sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==
|
||||
dependencies:
|
||||
mime-db "1.42.0"
|
||||
|
||||
mime@1.6.0, mime@^1.4.1:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
||||
@ -6070,10 +6084,10 @@ neo4j-driver@^1.7.3, neo4j-driver@^1.7.5, neo4j-driver@~1.7.6:
|
||||
text-encoding-utf-8 "^1.0.2"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
neo4j-graphql-js@^2.8.0:
|
||||
version "2.8.0"
|
||||
resolved "https://registry.yarnpkg.com/neo4j-graphql-js/-/neo4j-graphql-js-2.8.0.tgz#58035b9213656e17b6ed4c6cbf4dfe1c56a8a219"
|
||||
integrity sha512-nDuzmi6W/YGIIVm+GAXCr/8CLABsU/RfeLebLH32vqeKViFATMfm4eT66aOq/GwHJ0838+o20yCbIFdx5rTP/A==
|
||||
neo4j-graphql-js@^2.9.3:
|
||||
version "2.9.3"
|
||||
resolved "https://registry.yarnpkg.com/neo4j-graphql-js/-/neo4j-graphql-js-2.9.3.tgz#91afb0631eb35014110022a74e572c9eb065d281"
|
||||
integrity sha512-SzIX3BYE3EsKp/XU8Wog97TzfsrQdrKp/t7le7tnODojcBd5eSVJyKPrbaKqcnWMkLzKzO/SRX9PMQ2cDdXUKw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.5.5"
|
||||
"@babel/runtime-corejs2" "^7.5.5"
|
||||
@ -6532,11 +6546,6 @@ p-reduce@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa"
|
||||
integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=
|
||||
|
||||
p-reduce@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-2.0.0.tgz#365a26916213650711124881a6bdc4e32c2bfe36"
|
||||
integrity sha512-VcNNEqiYIkRCGeUHELY5dUrnQHCRwL6eIH/L9oSbl/PsvyHQXD1ws/MFwuEb+6dgH/URCfROVUqOYL37eHi2kQ==
|
||||
|
||||
p-some@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/p-some/-/p-some-4.1.0.tgz#28e73bc1e0d62db54c2ed513acd03acba30d5c04"
|
||||
@ -6784,10 +6793,10 @@ prettier-linter-helpers@^1.0.0:
|
||||
dependencies:
|
||||
fast-diff "^1.1.2"
|
||||
|
||||
prettier@~1.18.2:
|
||||
version "1.18.2"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea"
|
||||
integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==
|
||||
prettier@~1.19.1:
|
||||
version "1.19.1"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb"
|
||||
integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==
|
||||
|
||||
pretty-format@^24.9.0:
|
||||
version "24.9.0"
|
||||
@ -8625,6 +8634,14 @@ xregexp@^4.2.4:
|
||||
dependencies:
|
||||
"@babel/runtime-corejs2" "^7.2.0"
|
||||
|
||||
xss@~1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/xss/-/xss-1.0.6.tgz#eaf11e9fc476e3ae289944a1009efddd8a124b51"
|
||||
integrity sha512-6Q9TPBeNyoTRxgZFk5Ggaepk/4vUOYdOsIUYvLehcsIZTFjaavbVnsuAkLA5lIFuug5hw8zxcB9tm01gsjph2A==
|
||||
dependencies:
|
||||
commander "^2.9.0"
|
||||
cssfilter "0.0.10"
|
||||
|
||||
xtend@^4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
|
||||
@ -5,9 +5,12 @@ import {
|
||||
} from "cypress-cucumber-preprocessor/steps";
|
||||
import helpers from "../../support/helpers";
|
||||
import { VERSION } from '../../constants/terms-and-conditions-version.js'
|
||||
import locales from '../../../webapp/locales'
|
||||
import orderBy from 'lodash/orderBy'
|
||||
|
||||
/* global cy */
|
||||
|
||||
const languages = orderBy(locales, 'name')
|
||||
let lastPost = {};
|
||||
|
||||
let loginCredentials = {
|
||||
@ -245,6 +248,12 @@ Then("I select a category", () => {
|
||||
.click();
|
||||
});
|
||||
|
||||
When("I choose {string} as the language for the post", (languageCode) => {
|
||||
cy.get('.ds-flex-item > .ds-form-item .ds-select ')
|
||||
.click().get('.ds-select-option')
|
||||
.eq(languages.findIndex(l => l.code === languageCode)).click()
|
||||
})
|
||||
|
||||
Then("the post shows up on the landing page at position {int}", index => {
|
||||
cy.openPage("landing");
|
||||
const selector = `.post-card:nth-child(${index}) > .ds-card-content`;
|
||||
@ -536,4 +545,4 @@ Then("I see only one post with the title {string}", title => {
|
||||
.find(".post-link")
|
||||
.should("have.length", 1);
|
||||
cy.get(".main-container").contains(".post-link", title);
|
||||
});
|
||||
});
|
||||
|
||||
@ -20,6 +20,7 @@ Feature: Notification for a mention
|
||||
"""
|
||||
And mention "@matt-rider" in the text
|
||||
And I select a category
|
||||
And I choose "en" as the language for the post
|
||||
And I click on "Save"
|
||||
When I log out
|
||||
And I log in with the following credentials:
|
||||
|
||||
@ -17,7 +17,8 @@ Feature: Create a post
|
||||
Human Connection is a free and open-source social network
|
||||
for active citizenship.
|
||||
"""
|
||||
Then I select a category
|
||||
And I select a category
|
||||
And I choose "en" as the language for the post
|
||||
And I click on "Save"
|
||||
Then I get redirected to ".../my-first-post"
|
||||
And the post was saved successfully
|
||||
|
||||
@ -17,7 +17,7 @@ import "cypress-file-upload";
|
||||
import helpers from "./helpers";
|
||||
import users from "../fixtures/users.json";
|
||||
import { GraphQLClient, request } from 'graphql-request'
|
||||
import { gql } from '../../backend/src/jest/helpers'
|
||||
import { gql } from '../../backend/src/helpers/jest'
|
||||
|
||||
const backendHost = Cypress.env('BACKEND_HOST')
|
||||
const switchLang = name => {
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
data:
|
||||
SMTP_HOST: "mailserver.human-connection"
|
||||
SMTP_PORT: "25"
|
||||
GRAPHQL_PORT: "4000"
|
||||
GRAPHQL_URI: "http://nitro-backend.human-connection:4000"
|
||||
NEO4J_URI: "bolt://nitro-neo4j.human-connection:7687"
|
||||
NEO4J_AUTH: "none"
|
||||
|
||||
@ -2,11 +2,15 @@ version: "3.4"
|
||||
|
||||
services:
|
||||
webapp:
|
||||
environment:
|
||||
- "CI=${CI}"
|
||||
image: humanconnection/nitro-web:build-and-test
|
||||
build:
|
||||
context: webapp
|
||||
target: build-and-test
|
||||
backend:
|
||||
environment:
|
||||
- "CI=${CI}"
|
||||
image: humanconnection/nitro-backend:build-and-test
|
||||
build:
|
||||
context: backend
|
||||
|
||||
@ -15,7 +15,6 @@ services:
|
||||
environment:
|
||||
- NEO4J_dbms_security_auth__enabled=false
|
||||
- NEO4J_dbms_memory_heap_max__size=2G
|
||||
- GRAPHQL_PORT=4000
|
||||
- GRAPHQL_URI=http://localhost:4000
|
||||
- CLIENT_URI=http://localhost:3000
|
||||
- JWT_SECRET=b/&&7b78BF&fv/Vd
|
||||
|
||||
@ -39,7 +39,6 @@ services:
|
||||
- uploads:/nitro-backend/public/uploads
|
||||
environment:
|
||||
- NEO4J_URI=bolt://neo4j:7687
|
||||
- GRAPHQL_PORT=4000
|
||||
- GRAPHQL_URI=http://backend:4000
|
||||
- CLIENT_URI=http://localhost:3000
|
||||
- JWT_SECRET=b/&&7b78BF&fv/Vd
|
||||
|
||||
13
package.json
13
package.json
@ -8,15 +8,14 @@
|
||||
"nonGlobalStepDefinitions": true
|
||||
},
|
||||
"scripts": {
|
||||
"install:all": "yarn install && cd backend && yarn install && cd ../webapp && yarn install",
|
||||
"db:seed": "cd backend && yarn run db:seed",
|
||||
"db:reset": "cd backend && yarn run db:reset",
|
||||
"cypress:backend:server": "cd backend && yarn run test:before:server",
|
||||
"cypress:backend:seeder": "cd backend && yarn run test:before:seeder",
|
||||
"cypress:webapp": "cd webapp && cross-env GRAPHQL_URI=http://localhost:4123 yarn run dev",
|
||||
"cypress:setup": "run-p cypress:backend:* cypress:webapp",
|
||||
"cypress:run": "cypress run --browser chromium",
|
||||
"cypress:open": "cypress open --browser chromium",
|
||||
"test:jest": "cd webapp && yarn test && cd ../backend && yarn test:jest && codecov",
|
||||
"cypress:backend": "cd backend && yarn run dev",
|
||||
"cypress:webapp": "cd webapp && yarn run dev",
|
||||
"cypress:setup": "run-p cypress:backend cypress:webapp",
|
||||
"cypress:run": "cross-env cypress run --browser chromium",
|
||||
"cypress:open": "cross-env cypress open --browser chromium",
|
||||
"version": "auto-changelog -p"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
FROM node:13.0.1-alpine as base
|
||||
FROM node:13.1.0-alpine as base
|
||||
LABEL Description="Web Frontend of the Social Network Human-Connection.org" Vendor="Human-Connection gGmbH" Version="0.0.1" Maintainer="Human-Connection gGmbH (developer@human-connection.org)"
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
FROM node:13.0.1-alpine as build
|
||||
FROM node:13.1.0-alpine as build
|
||||
LABEL Description="Maintenance page of the Social Network Human-Connection.org" Vendor="Human-Connection gGmbH" Version="0.0.1" Maintainer="Human-Connection gGmbH (developer@human-connection.org)"
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
@ -69,7 +69,7 @@ export default {
|
||||
if (!this.user.slug) {
|
||||
return []
|
||||
}
|
||||
let routes = [
|
||||
const routes = [
|
||||
{
|
||||
name: this.$t('profile.name'),
|
||||
path: `/profile/${this.user.id}/${this.user.slug}`,
|
||||
|
||||
@ -6,10 +6,12 @@ const localVue = global.localVue
|
||||
describe('CategoriesSelect.vue', () => {
|
||||
let wrapper
|
||||
let mocks
|
||||
let provide
|
||||
let democracyAndPolitics
|
||||
let environmentAndNature
|
||||
let consumptionAndSustainablity
|
||||
|
||||
const propsData = { model: 'categoryIds' }
|
||||
const categories = [
|
||||
{
|
||||
id: 'cat9',
|
||||
@ -33,6 +35,11 @@ describe('CategoriesSelect.vue', () => {
|
||||
},
|
||||
]
|
||||
beforeEach(() => {
|
||||
provide = {
|
||||
$parentForm: {
|
||||
update: jest.fn(),
|
||||
},
|
||||
}
|
||||
mocks = {
|
||||
$t: jest.fn(),
|
||||
}
|
||||
@ -40,7 +47,7 @@ describe('CategoriesSelect.vue', () => {
|
||||
|
||||
describe('shallowMount', () => {
|
||||
const Wrapper = () => {
|
||||
return mount(CategoriesSelect, { mocks, localVue })
|
||||
return mount(CategoriesSelect, { propsData, mocks, localVue, provide })
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
@ -58,8 +65,8 @@ describe('CategoriesSelect.vue', () => {
|
||||
expect(wrapper.vm.selectedCategoryIds).toEqual([categories[0].id])
|
||||
})
|
||||
|
||||
it('emits an updateCategories event when the selectedCategoryIds changes', () => {
|
||||
expect(wrapper.emitted().updateCategories[0][0]).toEqual([categories[0].id])
|
||||
it('calls $parent.update with selected category ids', () => {
|
||||
expect(provide.$parentForm.update).toHaveBeenCalledWith('categoryIds', ['cat9'])
|
||||
})
|
||||
|
||||
it('removes categories when clicked a second time', () => {
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
<ds-flex-item>
|
||||
<ds-button
|
||||
size="small"
|
||||
:data-test="categoryButtonsId(category.id)"
|
||||
@click.prevent="toggleCategory(category.id)"
|
||||
:primary="isActive(category.id)"
|
||||
:disabled="isDisabled(category.id)"
|
||||
@ -28,16 +29,23 @@
|
||||
|
||||
<script>
|
||||
import CategoryQuery from '~/graphql/CategoryQuery'
|
||||
import xor from 'lodash/xor'
|
||||
|
||||
export default {
|
||||
inject: {
|
||||
$parentForm: {
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
props: {
|
||||
existingCategoryIds: { type: Array, default: () => [] },
|
||||
model: { type: String, required: true },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
categories: null,
|
||||
selectedMax: 3,
|
||||
selectedCategoryIds: [],
|
||||
selectedCategoryIds: this.existingCategoryIds,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -48,39 +56,22 @@ export default {
|
||||
return this.selectedCount >= this.selectedMax
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
selectedCategoryIds(categoryIds) {
|
||||
this.$emit('updateCategories', categoryIds)
|
||||
},
|
||||
existingCategoryIds: {
|
||||
immediate: true,
|
||||
handler: function(existingCategoryIds) {
|
||||
if (!existingCategoryIds || !existingCategoryIds.length) {
|
||||
return
|
||||
}
|
||||
this.selectedCategoryIds = existingCategoryIds
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
toggleCategory(id) {
|
||||
const index = this.selectedCategoryIds.indexOf(id)
|
||||
if (index > -1) {
|
||||
this.selectedCategoryIds.splice(index, 1)
|
||||
} else {
|
||||
this.selectedCategoryIds.push(id)
|
||||
this.selectedCategoryIds = xor(this.selectedCategoryIds, [id])
|
||||
if (this.$parentForm) {
|
||||
this.$parentForm.update(this.model, this.selectedCategoryIds)
|
||||
}
|
||||
},
|
||||
isActive(id) {
|
||||
const index = this.selectedCategoryIds.indexOf(id)
|
||||
if (index > -1) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return this.selectedCategoryIds.includes(id)
|
||||
},
|
||||
isDisabled(id) {
|
||||
return !!(this.reachedMaximum && !this.isActive(id))
|
||||
},
|
||||
categoryButtonsId(categoryId) {
|
||||
return `category-buttons-${categoryId}`
|
||||
},
|
||||
},
|
||||
apollo: {
|
||||
Category: {
|
||||
|
||||
@ -8,7 +8,7 @@ describe('Category', () => {
|
||||
let icon
|
||||
let name
|
||||
|
||||
let Wrapper = () => {
|
||||
const Wrapper = () => {
|
||||
return shallowMount(Category, {
|
||||
localVue,
|
||||
propsData: {
|
||||
|
||||
@ -53,7 +53,7 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
routes() {
|
||||
let routes = []
|
||||
const routes = []
|
||||
|
||||
if (this.resourceType === 'contribution') {
|
||||
if (this.isOwner) {
|
||||
|
||||
@ -16,15 +16,45 @@ config.stubs['client-only'] = '<span><slot /></span>'
|
||||
config.stubs['nuxt-link'] = '<span><slot /></span>'
|
||||
config.stubs['v-popover'] = '<span><slot /></span>'
|
||||
|
||||
const categories = [
|
||||
{
|
||||
id: 'cat3',
|
||||
slug: 'health-wellbeing',
|
||||
icon: 'medkit',
|
||||
},
|
||||
{
|
||||
id: 'cat12',
|
||||
slug: 'it-internet-data-privacy',
|
||||
icon: 'mouse-pointer',
|
||||
},
|
||||
{
|
||||
id: 'cat9',
|
||||
slug: 'democracy-politics',
|
||||
icon: 'university',
|
||||
},
|
||||
{
|
||||
id: 'cat15',
|
||||
slug: 'consumption-sustainability',
|
||||
icon: 'shopping-cart',
|
||||
},
|
||||
{
|
||||
id: 'cat4',
|
||||
slug: 'environment-nature',
|
||||
icon: 'tree',
|
||||
},
|
||||
]
|
||||
|
||||
describe('ContributionForm.vue', () => {
|
||||
let wrapper
|
||||
let postTitleInput
|
||||
let expectedParams
|
||||
let deutschOption
|
||||
let cancelBtn
|
||||
let mocks
|
||||
let propsData
|
||||
let categoryIds
|
||||
let wrapper,
|
||||
postTitleInput,
|
||||
expectedParams,
|
||||
cancelBtn,
|
||||
mocks,
|
||||
propsData,
|
||||
categoryIds,
|
||||
englishLanguage,
|
||||
deutschLanguage,
|
||||
dataPrivacyButton
|
||||
const postTitle = 'this is a title for a post'
|
||||
const postTitleTooShort = 'xx'
|
||||
let postTitleTooLong = ''
|
||||
@ -32,11 +62,6 @@ describe('ContributionForm.vue', () => {
|
||||
postTitleTooLong += 'x'
|
||||
}
|
||||
const postContent = 'this is a post'
|
||||
const postContentTooShort = 'xx'
|
||||
let postContentTooLong = ''
|
||||
for (let i = 0; i < 2001; i++) {
|
||||
postContentTooLong += 'x'
|
||||
}
|
||||
const imageUpload = {
|
||||
file: {
|
||||
filename: 'avataar.svg',
|
||||
@ -105,90 +130,59 @@ describe('ContributionForm.vue', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = Wrapper()
|
||||
wrapper.setData({
|
||||
form: {
|
||||
languageOptions: [
|
||||
{
|
||||
label: 'Deutsch',
|
||||
value: 'de',
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
describe('CreatePost', () => {
|
||||
describe('language placeholder', () => {
|
||||
it("displays the name that corresponds with the user's location code", () => {
|
||||
expect(wrapper.find('.ds-select-placeholder').text()).toEqual('English')
|
||||
})
|
||||
})
|
||||
|
||||
describe('invalid form submission', () => {
|
||||
it('title and content should not be empty ', async () => {
|
||||
wrapper.find('.submit-button-for-test').trigger('click')
|
||||
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
|
||||
beforeEach(async () => {
|
||||
wrapper.find(CategoriesSelect).setData({ categories })
|
||||
postTitleInput = wrapper.find('.ds-input')
|
||||
postTitleInput.setValue(postTitle)
|
||||
await wrapper.vm.updateEditorContent(postContent)
|
||||
englishLanguage = wrapper.findAll('li').filter(language => language.text() === 'English')
|
||||
englishLanguage.trigger('click')
|
||||
dataPrivacyButton = await wrapper
|
||||
.find(CategoriesSelect)
|
||||
.find('[data-test="category-buttons-cat12"]')
|
||||
dataPrivacyButton.trigger('click')
|
||||
})
|
||||
|
||||
it('title should not be empty', async () => {
|
||||
await wrapper.vm.updateEditorContent(postContent)
|
||||
wrapper.find('.submit-button-for-test').trigger('click')
|
||||
postTitleInput.setValue('')
|
||||
wrapper.find('form').trigger('submit')
|
||||
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('title should not be too long', async () => {
|
||||
postTitleInput = wrapper.find('.ds-input')
|
||||
postTitleInput.setValue(postTitleTooLong)
|
||||
await wrapper.vm.updateEditorContent(postContent)
|
||||
wrapper.find('.submit-button-for-test').trigger('click')
|
||||
wrapper.find('form').trigger('submit')
|
||||
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('title should not be too short', async () => {
|
||||
postTitleInput = wrapper.find('.ds-input')
|
||||
postTitleInput.setValue(postTitleTooShort)
|
||||
await wrapper.vm.updateEditorContent(postContent)
|
||||
wrapper.find('.submit-button-for-test').trigger('click')
|
||||
wrapper.find('form').trigger('submit')
|
||||
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('content should not be empty', async () => {
|
||||
postTitleInput = wrapper.find('.ds-input')
|
||||
postTitleInput.setValue(postTitle)
|
||||
await wrapper.find('.submit-button-for-test').trigger('click')
|
||||
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('content should not be too short', async () => {
|
||||
postTitleInput = wrapper.find('.ds-input')
|
||||
postTitleInput.setValue(postTitle)
|
||||
await wrapper.vm.updateEditorContent(postContentTooShort)
|
||||
wrapper.find('.submit-button-for-test').trigger('click')
|
||||
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('content should not be too long', async () => {
|
||||
postTitleInput = wrapper.find('.ds-input')
|
||||
postTitleInput.setValue(postTitle)
|
||||
await wrapper.vm.updateEditorContent(postContentTooLong)
|
||||
wrapper.find('.submit-button-for-test').trigger('click')
|
||||
await wrapper.vm.updateEditorContent('')
|
||||
await wrapper.find('form').trigger('submit')
|
||||
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should have at least one category', async () => {
|
||||
postTitleInput = wrapper.find('.ds-input')
|
||||
postTitleInput.setValue(postTitle)
|
||||
await wrapper.vm.updateEditorContent(postContent)
|
||||
wrapper.find('.submit-button-for-test').trigger('click')
|
||||
dataPrivacyButton = await wrapper
|
||||
.find(CategoriesSelect)
|
||||
.find('[data-test="category-buttons-cat12"]')
|
||||
dataPrivacyButton.trigger('click')
|
||||
wrapper.find('form').trigger('submit')
|
||||
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should have not have more than three categories', async () => {
|
||||
postTitleInput = wrapper.find('.ds-input')
|
||||
postTitleInput.setValue(postTitle)
|
||||
await wrapper.vm.updateEditorContent(postContent)
|
||||
wrapper.vm.form.categoryIds = ['cat4', 'cat9', 'cat15', 'cat27']
|
||||
wrapper.find('.submit-button-for-test').trigger('click')
|
||||
wrapper.find('form').trigger('submit')
|
||||
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
@ -210,43 +204,51 @@ describe('ContributionForm.vue', () => {
|
||||
postTitleInput = wrapper.find('.ds-input')
|
||||
postTitleInput.setValue(postTitle)
|
||||
await wrapper.vm.updateEditorContent(postContent)
|
||||
categoryIds = ['cat12']
|
||||
wrapper.find(CategoriesSelect).vm.$emit('updateCategories', categoryIds)
|
||||
wrapper.find(CategoriesSelect).setData({ categories })
|
||||
englishLanguage = wrapper.findAll('li').filter(language => language.text() === 'English')
|
||||
englishLanguage.trigger('click')
|
||||
dataPrivacyButton = await wrapper
|
||||
.find(CategoriesSelect)
|
||||
.find('[data-test="category-buttons-cat12"]')
|
||||
dataPrivacyButton.trigger('click')
|
||||
})
|
||||
|
||||
it('creates a post with valid title, content, and at least one category', async () => {
|
||||
await wrapper.find('.submit-button-for-test').trigger('click')
|
||||
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
||||
})
|
||||
|
||||
it("sends a fallback language based on a user's locale", () => {
|
||||
wrapper.find('.submit-button-for-test').trigger('click')
|
||||
await wrapper.find('form').trigger('submit')
|
||||
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
||||
})
|
||||
|
||||
it('supports changing the language', async () => {
|
||||
expectedParams.variables.language = 'de'
|
||||
deutschOption = wrapper.findAll('li').at(0)
|
||||
deutschOption.trigger('click')
|
||||
wrapper.find('.submit-button-for-test').trigger('click')
|
||||
deutschLanguage = wrapper.findAll('li').filter(language => language.text() === 'Deutsch')
|
||||
deutschLanguage.trigger('click')
|
||||
wrapper.find('form').trigger('submit')
|
||||
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
||||
})
|
||||
|
||||
it('supports adding a teaser image', async () => {
|
||||
expectedParams.variables.imageUpload = imageUpload
|
||||
wrapper.find(TeaserImage).vm.$emit('addTeaserImage', imageUpload)
|
||||
await wrapper.find('.submit-button-for-test').trigger('click')
|
||||
await wrapper.find('form').trigger('submit')
|
||||
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
||||
})
|
||||
|
||||
it('content is valid with just a link', async () => {
|
||||
await wrapper.vm.updateEditorContent(
|
||||
'<a href="https://www.youtube.com/watch?v=smoEelV6FUk" target="_blank"></a>',
|
||||
)
|
||||
wrapper.find('form').trigger('submit')
|
||||
expect(mocks.$apollo.mutate).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it("pushes the user to the post's page", async () => {
|
||||
wrapper.find('.submit-button-for-test').trigger('click')
|
||||
wrapper.find('form').trigger('submit')
|
||||
await mocks.$apollo.mutate
|
||||
expect(mocks.$router.push).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('shows a success toaster', async () => {
|
||||
wrapper.find('.submit-button-for-test').trigger('click')
|
||||
wrapper.find('form').trigger('submit')
|
||||
await mocks.$apollo.mutate
|
||||
expect(mocks.$toast.success).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
@ -271,11 +273,17 @@ describe('ContributionForm.vue', () => {
|
||||
postTitleInput.setValue(postTitle)
|
||||
await wrapper.vm.updateEditorContent(postContent)
|
||||
categoryIds = ['cat12']
|
||||
wrapper.find(CategoriesSelect).vm.$emit('updateCategories', categoryIds)
|
||||
wrapper.find(CategoriesSelect).setData({ categories })
|
||||
englishLanguage = wrapper.findAll('li').filter(language => language.text() === 'English')
|
||||
englishLanguage.trigger('click')
|
||||
dataPrivacyButton = await wrapper
|
||||
.find(CategoriesSelect)
|
||||
.find('[data-test="category-buttons-cat12"]')
|
||||
dataPrivacyButton.trigger('click')
|
||||
})
|
||||
|
||||
it('shows an error toaster when apollo mutation rejects', async () => {
|
||||
await wrapper.find('.submit-button-for-test').trigger('click')
|
||||
await wrapper.find('form').trigger('submit')
|
||||
await mocks.$apollo.mutate
|
||||
await expect(mocks.$toast.error).toHaveBeenCalledWith('Not Authorised!')
|
||||
})
|
||||
@ -337,11 +345,11 @@ describe('ContributionForm.vue', () => {
|
||||
expectedParams = {
|
||||
mutation: PostMutations().UpdatePost,
|
||||
variables: {
|
||||
title: postTitle,
|
||||
content: postContent,
|
||||
title: propsData.contribution.title,
|
||||
content: propsData.contribution.content,
|
||||
language: propsData.contribution.language,
|
||||
id: propsData.contribution.id,
|
||||
categoryIds,
|
||||
categoryIds: ['cat12'],
|
||||
image,
|
||||
imageUpload: null,
|
||||
},
|
||||
@ -349,22 +357,20 @@ describe('ContributionForm.vue', () => {
|
||||
})
|
||||
|
||||
it('calls the UpdatePost apollo mutation', async () => {
|
||||
postTitleInput = wrapper.find('.ds-input')
|
||||
postTitleInput.setValue(postTitle)
|
||||
expectedParams.variables.content = postContent
|
||||
wrapper.vm.updateEditorContent(postContent)
|
||||
wrapper.find(CategoriesSelect).vm.$emit('updateCategories', categoryIds)
|
||||
wrapper.find('.submit-button-for-test').trigger('click')
|
||||
await wrapper.find('form').trigger('submit')
|
||||
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
||||
})
|
||||
|
||||
it('supports updating categories', async () => {
|
||||
const categoryIds = ['cat3', 'cat51', 'cat37']
|
||||
postTitleInput = wrapper.find('.ds-input')
|
||||
postTitleInput.setValue(postTitle)
|
||||
wrapper.vm.updateEditorContent(postContent)
|
||||
expectedParams.variables.categoryIds = categoryIds
|
||||
wrapper.find(CategoriesSelect).vm.$emit('updateCategories', categoryIds)
|
||||
await wrapper.find('.submit-button-for-test').trigger('click')
|
||||
expectedParams.variables.categoryIds.push('cat3')
|
||||
wrapper.find(CategoriesSelect).setData({ categories })
|
||||
const healthWellbeingButton = await wrapper
|
||||
.find(CategoriesSelect)
|
||||
.find('[data-test="category-buttons-cat3"]')
|
||||
healthWellbeingButton.trigger('click')
|
||||
await wrapper.find('form').trigger('submit')
|
||||
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,5 +1,11 @@
|
||||
<template>
|
||||
<ds-form ref="contributionForm" v-model="form" :schema="formSchema">
|
||||
<ds-form
|
||||
class="contribution-form"
|
||||
ref="contributionForm"
|
||||
v-model="form"
|
||||
:schema="formSchema"
|
||||
@submit="submit"
|
||||
>
|
||||
<template slot-scope="{ errors }">
|
||||
<hc-teaser-image :contribution="contribution" @addTeaserImage="addTeaserImage">
|
||||
<img
|
||||
@ -21,7 +27,13 @@
|
||||
name="title"
|
||||
autofocus
|
||||
/>
|
||||
<small class="smallTag">{{ form.title.length }}/{{ formSchema.title.max }}</small>
|
||||
<ds-text align="right">
|
||||
<ds-chip v-if="errors && errors.title" color="danger" size="base">
|
||||
{{ form.title.length }}/{{ formSchema.title.max }}
|
||||
<ds-icon name="warning"></ds-icon>
|
||||
</ds-chip>
|
||||
<ds-chip v-else size="base">{{ form.title.length }}/{{ formSchema.title.max }}</ds-chip>
|
||||
</ds-text>
|
||||
<client-only>
|
||||
<hc-editor
|
||||
:users="users"
|
||||
@ -29,27 +41,43 @@
|
||||
:hashtags="hashtags"
|
||||
@input="updateEditorContent"
|
||||
/>
|
||||
<small class="smallTag">{{ form.contentLength }}</small>
|
||||
<ds-text align="right">
|
||||
<ds-chip v-if="errors && errors.content" color="danger" size="base">
|
||||
{{ contentLength }}
|
||||
<ds-icon name="warning"></ds-icon>
|
||||
</ds-chip>
|
||||
<ds-chip v-else size="base">
|
||||
{{ contentLength }}
|
||||
</ds-chip>
|
||||
</ds-text>
|
||||
</client-only>
|
||||
<ds-space margin-bottom="small" />
|
||||
<hc-categories-select
|
||||
model="categoryIds"
|
||||
@updateCategories="updateCategories"
|
||||
:existingCategoryIds="form.categoryIds"
|
||||
/>
|
||||
<hc-categories-select model="categoryIds" :existingCategoryIds="form.categoryIds" />
|
||||
<ds-text align="right">
|
||||
<ds-chip v-if="errors && errors.categoryIds" color="danger" size="base">
|
||||
{{ form.categoryIds.length }} / 3
|
||||
<ds-icon name="warning"></ds-icon>
|
||||
</ds-chip>
|
||||
<ds-chip v-else size="base">{{ form.categoryIds.length }} / 3</ds-chip>
|
||||
</ds-text>
|
||||
<ds-flex class="contribution-form-footer">
|
||||
<ds-flex-item :width="{ base: '10%', sm: '10%', md: '10%', lg: '15%' }" />
|
||||
<ds-flex-item :width="{ base: '80%', sm: '30%', md: '30%', lg: '20%' }">
|
||||
<ds-flex-item :width="{ lg: '50%', md: '50%', sm: '100%' }" />
|
||||
<ds-flex-item>
|
||||
<ds-space margin-bottom="small" />
|
||||
<ds-select
|
||||
model="language"
|
||||
:options="form.languageOptions"
|
||||
:options="languageOptions"
|
||||
icon="globe"
|
||||
:placeholder="locale"
|
||||
:placeholder="$t('contribution.languageSelectText')"
|
||||
:label="$t('contribution.languageSelectLabel')"
|
||||
/>
|
||||
</ds-flex-item>
|
||||
</ds-flex>
|
||||
<ds-text align="right">
|
||||
<ds-chip v-if="errors && errors.language" size="base" color="danger">
|
||||
<ds-icon name="warning"></ds-icon>
|
||||
</ds-chip>
|
||||
</ds-text>
|
||||
<ds-space />
|
||||
<div slot="footer" style="text-align: right">
|
||||
<ds-button
|
||||
@ -60,15 +88,7 @@
|
||||
>
|
||||
{{ $t('actions.cancel') }}
|
||||
</ds-button>
|
||||
<ds-button
|
||||
class="submit-button-for-test"
|
||||
type="submit"
|
||||
icon="check"
|
||||
:loading="loading"
|
||||
:disabled="failsValidations || errors"
|
||||
primary
|
||||
@click.prevent="submit"
|
||||
>
|
||||
<ds-button type="submit" icon="check" :loading="loading" :disabled="errors" primary>
|
||||
{{ $t('actions.save') }}
|
||||
</ds-button>
|
||||
</div>
|
||||
@ -100,73 +120,78 @@ export default {
|
||||
contribution: { type: Object, default: () => {} },
|
||||
},
|
||||
data() {
|
||||
const languageOptions = orderBy(locales, 'name').map(locale => {
|
||||
return { label: locale.name, value: locale.code }
|
||||
})
|
||||
|
||||
const formDefaults = {
|
||||
title: '',
|
||||
content: '',
|
||||
teaserImage: null,
|
||||
image: null,
|
||||
language: null,
|
||||
categoryIds: [],
|
||||
}
|
||||
let id = null
|
||||
let slug = null
|
||||
const form = { ...formDefaults }
|
||||
if (this.contribution && this.contribution.id) {
|
||||
id = this.contribution.id
|
||||
slug = this.contribution.slug
|
||||
form.title = this.contribution.title
|
||||
form.content = this.contribution.content
|
||||
form.image = this.contribution.image
|
||||
form.language =
|
||||
this.contribution && this.contribution.language
|
||||
? languageOptions.find(o => this.contribution.language === o.value)
|
||||
: null
|
||||
form.categoryIds = this.categoryIds(this.contribution.categories)
|
||||
}
|
||||
return {
|
||||
form: {
|
||||
title: '',
|
||||
content: '',
|
||||
contentLength: 0,
|
||||
teaserImage: null,
|
||||
image: null,
|
||||
language: null,
|
||||
languageOptions: [],
|
||||
categoryIds: [],
|
||||
},
|
||||
form,
|
||||
formSchema: {
|
||||
title: { required: true, min: 3, max: 100 },
|
||||
content: [{ required: true }],
|
||||
content: { required: true },
|
||||
categoryIds: {
|
||||
type: 'array',
|
||||
required: true,
|
||||
validator: (rule, value) => {
|
||||
const errors = []
|
||||
if (!(value && value.length >= 1 && value.length <= 3)) {
|
||||
errors.push(new Error(this.$t('common.validations.categories')))
|
||||
}
|
||||
return errors
|
||||
},
|
||||
},
|
||||
language: { required: true },
|
||||
},
|
||||
id: null,
|
||||
languageOptions,
|
||||
id,
|
||||
slug,
|
||||
loading: false,
|
||||
slug: null,
|
||||
users: [],
|
||||
contentMin: 3,
|
||||
failsValidations: true,
|
||||
hashtags: [],
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
contribution: {
|
||||
immediate: true,
|
||||
handler: function(contribution) {
|
||||
if (!contribution || !contribution.id) {
|
||||
return
|
||||
}
|
||||
this.id = contribution.id
|
||||
this.slug = contribution.slug
|
||||
this.form.title = contribution.title
|
||||
this.form.content = contribution.content
|
||||
this.form.image = contribution.image
|
||||
this.form.categoryIds = this.categoryIds(contribution.categories)
|
||||
this.manageContent(this.form.content)
|
||||
},
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
locale() {
|
||||
const locale =
|
||||
this.contribution && this.contribution.language
|
||||
? locales.find(loc => this.contribution.language === loc.code)
|
||||
: locales.find(loc => this.$i18n.locale() === loc.code)
|
||||
return locale.name
|
||||
contentLength() {
|
||||
return this.$filters.removeHtml(this.form.content).length
|
||||
},
|
||||
...mapGetters({
|
||||
currentUser: 'auth/user',
|
||||
}),
|
||||
},
|
||||
mounted() {
|
||||
this.availableLocales()
|
||||
},
|
||||
methods: {
|
||||
submit() {
|
||||
const { title, content, image, teaserImage, categoryIds } = this.form
|
||||
let language
|
||||
if (this.form.language) {
|
||||
language = this.form.language.value
|
||||
} else if (this.contribution && this.contribution.language) {
|
||||
language = this.contribution.language
|
||||
} else {
|
||||
language = this.$i18n.locale()
|
||||
}
|
||||
const {
|
||||
language: { value: language },
|
||||
title,
|
||||
content,
|
||||
image,
|
||||
teaserImage,
|
||||
categoryIds,
|
||||
} = this.form
|
||||
this.loading = true
|
||||
this.$apollo
|
||||
.mutate({
|
||||
@ -185,7 +210,6 @@ export default {
|
||||
this.loading = false
|
||||
this.$toast.success(this.$t('contribution.success'))
|
||||
const result = data[this.id ? 'UpdatePost' : 'CreatePost']
|
||||
this.failedValidations = false
|
||||
|
||||
this.$router.push({
|
||||
name: 'post-id-slug',
|
||||
@ -195,45 +219,16 @@ export default {
|
||||
.catch(err => {
|
||||
this.$toast.error(err.message)
|
||||
this.loading = false
|
||||
this.failedValidations = true
|
||||
})
|
||||
},
|
||||
updateEditorContent(value) {
|
||||
// TODO: Do smth????? what is happening
|
||||
this.$refs.contributionForm.update('content', value)
|
||||
this.manageContent(value)
|
||||
},
|
||||
manageContent(content) {
|
||||
// filter HTML out of content value
|
||||
const str = content.replace(/<\/?[^>]+(>|$)/gm, '')
|
||||
// Set counter length of text
|
||||
this.form.contentLength = str.length
|
||||
this.validatePost()
|
||||
},
|
||||
availableLocales() {
|
||||
orderBy(locales, 'name').map(locale => {
|
||||
this.form.languageOptions.push({ label: locale.name, value: locale.code })
|
||||
})
|
||||
},
|
||||
updateCategories(ids) {
|
||||
this.form.categoryIds = ids
|
||||
this.validatePost()
|
||||
},
|
||||
addTeaserImage(file) {
|
||||
this.form.teaserImage = file
|
||||
},
|
||||
categoryIds(categories) {
|
||||
let categoryIds = []
|
||||
categories.map(categoryId => {
|
||||
categoryIds.push(categoryId.id)
|
||||
})
|
||||
return categoryIds
|
||||
},
|
||||
validatePost() {
|
||||
const passesContentValidations = this.form.contentLength >= this.contentMin
|
||||
const passesCategoryValidations =
|
||||
this.form.categoryIds.length > 0 && this.form.categoryIds.length <= 3
|
||||
this.failsValidations = !(passesContentValidations && passesCategoryValidations)
|
||||
return categories.map(c => c.id)
|
||||
},
|
||||
},
|
||||
apollo: {
|
||||
@ -288,4 +283,10 @@ export default {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.contribution-form {
|
||||
.ds-chip {
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -101,7 +101,7 @@ export default {
|
||||
}
|
||||
},
|
||||
handleSubmit() {
|
||||
let resourceArgs = []
|
||||
const resourceArgs = []
|
||||
if (this.deleteContributions) {
|
||||
resourceArgs.push('Post')
|
||||
}
|
||||
|
||||
@ -78,7 +78,7 @@ describe('Editor.vue', () => {
|
||||
|
||||
describe('limists suggestion list to 15 users', () => {
|
||||
beforeEach(() => {
|
||||
let manyUsersList = []
|
||||
const manyUsersList = []
|
||||
for (let i = 0; i < 25; i++) {
|
||||
manyUsersList.push({ id: `user${i}` })
|
||||
}
|
||||
@ -119,7 +119,7 @@ describe('Editor.vue', () => {
|
||||
|
||||
describe('limists suggestion list to 15 hashtags', () => {
|
||||
beforeEach(() => {
|
||||
let manyHashtagsList = []
|
||||
const manyHashtagsList = []
|
||||
for (let i = 0; i < 25; i++) {
|
||||
manyHashtagsList.push({ id: `hashtag${i}` })
|
||||
}
|
||||
|
||||
@ -27,7 +27,11 @@ const plugins = [
|
||||
]
|
||||
helpers.init({ plugins })
|
||||
|
||||
const users = [{ id: 1, slug: 'peter' }, { id: 2, slug: 'sandra' }, { id: 3, slug: 'jane' }]
|
||||
const users = [
|
||||
{ id: 1, slug: 'peter' },
|
||||
{ id: 2, slug: 'sandra' },
|
||||
{ id: 3, slug: 'jane' },
|
||||
]
|
||||
|
||||
storiesOf('Editor', module)
|
||||
.addDecorator(withA11y)
|
||||
|
||||
@ -377,6 +377,7 @@ li > p {
|
||||
.embed-preview-image {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-height: 450px;
|
||||
}
|
||||
|
||||
.embed-preview-image--clickable {
|
||||
|
||||
@ -63,30 +63,26 @@ describe('defaultExtensions', () => {
|
||||
it('recognizes embed code', () => {
|
||||
const editor = createEditor()
|
||||
const expected = {
|
||||
type: 'doc',
|
||||
content: [
|
||||
{
|
||||
type: 'paragraph',
|
||||
content: [
|
||||
{
|
||||
text: 'Baby loves cat:',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
type: 'paragraph',
|
||||
},
|
||||
{
|
||||
content: [
|
||||
{
|
||||
attrs: {
|
||||
dataEmbedUrl: 'https://www.youtube.com/watch?v=qkdXAtO40Fo',
|
||||
},
|
||||
type: 'embed',
|
||||
},
|
||||
],
|
||||
type: 'paragraph',
|
||||
type: 'embed',
|
||||
attrs: {
|
||||
dataEmbedUrl: 'https://www.youtube.com/watch?v=qkdXAtO40Fo',
|
||||
},
|
||||
},
|
||||
],
|
||||
type: 'doc',
|
||||
}
|
||||
|
||||
expect(editor.getJSON()).toEqual(expected)
|
||||
})
|
||||
})
|
||||
|
||||
@ -38,8 +38,8 @@ export default class Embed extends Node {
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
group: 'inline',
|
||||
inline: true,
|
||||
group: 'block',
|
||||
inline: false,
|
||||
parseDOM: [
|
||||
{
|
||||
tag: 'a[href].embed',
|
||||
|
||||
@ -5,6 +5,7 @@ export default class EventHandler extends Extension {
|
||||
get name() {
|
||||
return 'event_handler'
|
||||
}
|
||||
|
||||
get plugins() {
|
||||
return [
|
||||
new Plugin({
|
||||
|
||||
@ -9,7 +9,7 @@ config.stubs['nuxt-link'] = '<span><slot /></span>'
|
||||
describe('Hashtag', () => {
|
||||
let id
|
||||
|
||||
let Wrapper = () => {
|
||||
const Wrapper = () => {
|
||||
return shallowMount(Hashtag, {
|
||||
localVue,
|
||||
propsData: {
|
||||
|
||||
18
webapp/components/Hashtag/Hashtag.story.js
Normal file
18
webapp/components/Hashtag/Hashtag.story.js
Normal file
@ -0,0 +1,18 @@
|
||||
import { storiesOf } from '@storybook/vue'
|
||||
import { withA11y } from '@storybook/addon-a11y'
|
||||
import Hashtag from './Hashtag.vue'
|
||||
import helpers from '~/storybook/helpers'
|
||||
|
||||
helpers.init()
|
||||
|
||||
storiesOf('Hashtag', module)
|
||||
.addDecorator(withA11y)
|
||||
.addDecorator(helpers.layout)
|
||||
.add('clickable', () => ({
|
||||
components: { Hashtag },
|
||||
store: helpers.store,
|
||||
data: () => ({
|
||||
hashtag: 'SomeHashtag',
|
||||
}),
|
||||
template: '<hashtag :id="hashtag" />',
|
||||
}))
|
||||
@ -1,7 +0,0 @@
|
||||
### Example
|
||||
|
||||
Tag "Liebe"
|
||||
|
||||
```
|
||||
<hc-hashtag name="Liebe" />
|
||||
```
|
||||
@ -58,7 +58,7 @@ export default {
|
||||
return find(this.locales, { code: this.$i18n.locale() })
|
||||
},
|
||||
routes() {
|
||||
let routes = this.locales.map(locale => {
|
||||
const routes = this.locales.map(locale => {
|
||||
return {
|
||||
name: locale.name,
|
||||
path: locale.code,
|
||||
|
||||
@ -5,7 +5,7 @@ const localVue = global.localVue
|
||||
|
||||
localVue.filter('truncate', string => string)
|
||||
|
||||
config.stubs['dropdown'] = '<span class="dropdown"><slot /></span>'
|
||||
config.stubs.dropdown = '<span class="dropdown"><slot /></span>'
|
||||
|
||||
describe('NotificationMenu.vue', () => {
|
||||
let wrapper
|
||||
|
||||
@ -5,13 +5,13 @@ import Paginate from './Paginate'
|
||||
const localVue = global.localVue
|
||||
|
||||
describe('Paginate.vue', () => {
|
||||
let propsData, wrapper, Wrapper, nextButton, backButton
|
||||
let propsData, wrapper, nextButton, backButton
|
||||
|
||||
beforeEach(() => {
|
||||
propsData = {}
|
||||
})
|
||||
|
||||
Wrapper = () => {
|
||||
const Wrapper = () => {
|
||||
return mount(Paginate, { propsData, localVue })
|
||||
}
|
||||
describe('mount', () => {
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<ds-card
|
||||
:lang="post.language"
|
||||
:image="post.image | proxyApiUrl"
|
||||
:class="{ 'post-card': true, 'disabled-content': post.disabled, 'post--pinned': isPinned }"
|
||||
>
|
||||
|
||||
@ -4,6 +4,7 @@ import Signup, { SignupMutation, SignupByInvitationMutation } from './Signup'
|
||||
const localVue = global.localVue
|
||||
|
||||
config.stubs['sweetalert-icon'] = '<span><slot /></span>'
|
||||
config.stubs['nuxt-link'] = '<span><slot /></span>'
|
||||
|
||||
describe('Signup', () => {
|
||||
let wrapper
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user