diff --git a/.gitbook/assets/storybook-output.png b/.gitbook/assets/storybook-output.png new file mode 100644 index 000000000..2b157dd62 Binary files /dev/null and b/.gitbook/assets/storybook-output.png differ diff --git a/.vscode/settings.json b/.vscode/settings.json index e2a727871..9acbf50bd 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,6 +7,6 @@ "autoFix": true } ], - "editor.formatOnSave": true, + "editor.formatOnSave": false, "eslint.autoFixOnSave": true -} +} \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0eb90a824..1475df0de 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -50,17 +50,17 @@ But what do we do when waiting for merge into master \(wanting to keep PRs small * but what about when you are waiting for merge? * solutions * 1\) put 2nd PR into branch that the first PR is hitting - but requires update after merging - * 2\) prefer to leave exiting PR until it can be reviewed, and instead go and work on some other part of the codebase that is not impacted by the first PR + * 2\) prefer to leave existing PR until it can be reviewed, and instead go and work on some other part of the codebase that is not impacted by the first PR ### Code Review * Github setting in place - at least one review is required to merge - in principle anyone (who is not the PR owner) can review - - but often it will be the core developers (Robert, Ulf, Greg, Wolfgang?) + - but often it will be the core developers (Robert, Wolfgang, Matt, Alina, Alex) - once there is a review, and presuming no requested changes, PR opener can merge * CI/tests - the CI needs to pass - - linting <-- autofix? + - linting (yarn lint --fix) - tests (unit, feature) (backend, frontend) - codecoverage diff --git a/backend/README.md b/backend/README.md index cd56e231f..14e6d0ddd 100644 --- a/backend/README.md +++ b/backend/README.md @@ -72,6 +72,8 @@ To reset the database run: $ docker-compose exec backend yarn run db:reset # you could also wipe out your neo4j database and delete all volumes with: $ docker-compose down -v +# if container is not running, run this command to set up your database indeces and contstraints +$ docker-compose run neo4j db_setup ``` {% endtab %} @@ -88,7 +90,6 @@ $ yarn run db:reset {% endtab %} {% endtabs %} - # Testing **Beware**: We have no multiple database setup at the moment. We clean the diff --git a/backend/package.json b/backend/package.json index cd9985a03..cd51dee0b 100644 --- a/backend/package.json +++ b/backend/package.json @@ -41,7 +41,7 @@ ] }, "dependencies": { - "@hapi/joi": "^16.1.2", + "@hapi/joi": "^16.1.4", "@sentry/node": "^5.6.2", "activitystrea.ms": "~2.1.3", "apollo-cache-inmemory": "~1.6.3", @@ -77,7 +77,7 @@ "metascraper-author": "^5.7.4", "metascraper-clearbit-logo": "^5.3.0", "metascraper-date": "^5.7.4", - "metascraper-description": "^5.7.4", + "metascraper-description": "^5.7.5", "metascraper-image": "^5.7.5", "metascraper-lang": "^5.7.4", "metascraper-lang-detector": "^4.8.5", @@ -89,7 +89,7 @@ "metascraper-video": "^5.7.5", "metascraper-youtube": "^5.7.5", "minimatch": "^3.0.4", - "mustache": "^3.0.3", + "mustache": "^3.1.0", "neo4j-driver": "~1.7.6", "neo4j-graphql-js": "^2.7.2", "neode": "^0.3.3", @@ -106,13 +106,13 @@ "xregexp": "^4.2.4" }, "devDependencies": { - "@babel/cli": "~7.6.0", - "@babel/core": "~7.6.0", + "@babel/cli": "~7.6.2", + "@babel/core": "~7.6.2", "@babel/node": "~7.6.1", "@babel/plugin-proposal-throw-expressions": "^7.2.0", "@babel/preset-env": "~7.6.0", "@babel/register": "~7.6.2", - "apollo-server-testing": "~2.9.3", + "apollo-server-testing": "~2.9.4", "babel-core": "~7.0.0-0", "babel-eslint": "~10.0.3", "babel-jest": "~24.9.0", diff --git a/backend/src/schema/resolvers/shout.spec.js b/backend/src/schema/resolvers/shout.spec.js index 718a1e169..e39ac2e24 100644 --- a/backend/src/schema/resolvers/shout.spec.js +++ b/backend/src/schema/resolvers/shout.spec.js @@ -1,13 +1,13 @@ -import { GraphQLClient } from 'graphql-request' +import { createTestClient } from 'apollo-server-testing' import Factory from '../../seed/factories' -import { host, login, gql } from '../../jest/helpers' -import { neode } from '../../bootstrap/neo4j' +import { gql } from '../../jest/helpers' +import { neode as getNeode, getDriver } from '../../bootstrap/neo4j' +import createServer from '../../server' -let clientUser1, clientUser2 -let headersUser1, headersUser2 +let mutate, query, authenticatedUser, variables const factory = Factory() -const instance = neode() -const categoryIds = ['cat9'] +const instance = getNeode() +const driver = getDriver() const mutationShoutPost = gql` mutation($id: ID!) { @@ -19,141 +19,148 @@ const mutationUnshoutPost = gql` unshout(id: $id, type: Post) } ` -const createPostMutation = gql` - mutation($id: ID, $title: String!, $content: String!, $categoryIds: [ID]!) { - CreatePost(id: $id, title: $title, content: $content, categoryIds: $categoryIds) { +const queryPost = gql` + query($id: ID!) { + Post(id: $id) { id - title - content + shoutedBy { + id + } } } ` -const createPostVariables = { - id: 'p1234', - title: 'Post Title 1234', - content: 'Some Post Content 1234', - categoryIds, -} -beforeEach(async () => { - await factory.create('User', { - id: 'u1', - email: 'test@example.org', - password: '1234', - }) - await factory.create('User', { - id: 'u2', - email: 'test2@example.org', - password: '1234', - }) - await instance.create('Category', { - id: 'cat9', - name: 'Democracy & Politics', - icon: 'university', - }) - headersUser1 = await login({ email: 'test@example.org', password: '1234' }) - headersUser2 = await login({ email: 'test2@example.org', password: '1234' }) - clientUser1 = new GraphQLClient(host, { headers: headersUser1 }) - clientUser2 = new GraphQLClient(host, { headers: headersUser2 }) - await clientUser1.request(createPostMutation, createPostVariables) - await clientUser2.request(createPostMutation, { - id: 'p12345', - title: 'Post Title 12345', - content: 'Some Post Content 12345', - categoryIds, +describe('shout and unshout posts', () => { + let currentUser, postAuthor + beforeAll(() => { + authenticatedUser = undefined + const { server } = createServer({ + context: () => { + return { + driver, + neode: instance, + user: authenticatedUser, + } + }, + }) + mutate = createTestClient(server).mutate + query = createTestClient(server).query + }) + afterEach(() => { + factory.cleanDatabase() }) -}) -afterEach(async () => { - await factory.cleanDatabase() -}) - -describe('shout', () => { - describe('shout foreign post', () => { - describe('unauthenticated shout', () => { + describe('shout', () => { + describe('unauthenticated', () => { it('throws authorization error', async () => { - const client = new GraphQLClient(host) - await expect(client.request(mutationShoutPost, { id: 'p1234' })).rejects.toThrow( - 'Not Authorised', - ) + variables = { id: 'post-to-shout-id' } + authenticatedUser = undefined + await expect(mutate({ mutation: mutationShoutPost, variables })).resolves.toMatchObject({ + errors: [{ message: 'Not Authorised!' }], + }) + }) + }) + describe('authenticated', () => { + beforeEach(async () => { + currentUser = await factory.create('User', { + id: 'current-user-id', + name: 'Current User', + email: 'current.user@example.org', + password: '1234', + }) + + postAuthor = await factory.create('User', { + id: 'post-author-id', + name: 'Post Author', + email: 'post.author@example.org', + password: '1234', + }) + authenticatedUser = await currentUser.toJson() + await factory.create('Post', { + name: 'Other user post', + id: 'another-user-post-id', + author: postAuthor, + }) + await factory.create('Post', { + name: 'current user post', + id: 'current-user-post-id', + author: currentUser, + }) + variables = {} + }) + + it("another user's post", async () => { + variables = { id: 'another-user-post-id' } + await expect(mutate({ mutation: mutationShoutPost, variables })).resolves.toMatchObject({ + data: { shout: true }, + }) + await expect(query({ query: queryPost, variables })).resolves.toMatchObject({ + data: { Post: [{ id: 'another-user-post-id', shoutedBy: [{ id: 'current-user-id' }] }] }, + errors: undefined, + }) + }) + + it('my own post', async () => { + variables = { id: 'current-user-post-id' } + await expect(mutate({ mutation: mutationShoutPost, variables })).resolves.toMatchObject({ + data: { shout: false }, + }) + await expect(query({ query: queryPost, variables })).resolves.toMatchObject({ + data: { Post: [{ id: 'current-user-post-id', shoutedBy: [] }] }, + errors: undefined, + }) + }) + }) + }) + describe('unshout', () => { + describe('unauthenticated', () => { + it('throws authorization error', async () => { + authenticatedUser = undefined + variables = { id: 'post-to-shout-id' } + await expect(mutate({ mutation: mutationUnshoutPost, variables })).resolves.toMatchObject({ + errors: [{ message: 'Not Authorised!' }], + }) }) }) - it('I shout a post of another user', async () => { - const res = await clientUser1.request(mutationShoutPost, { id: 'p12345' }) - const expected = { - shout: true, - } - expect(res).toMatchObject(expected) + describe('authenticated', () => { + beforeEach(async () => { + currentUser = await factory.create('User', { + id: 'current-user-id', + name: 'Current User', + email: 'current.user@example.org', + password: '1234', + }) - const { Post } = await clientUser1.request(gql` - query { - Post(id: "p12345") { - shoutedByCurrentUser - } - } - `) - const expected2 = { - shoutedByCurrentUser: true, - } - expect(Post[0]).toMatchObject(expected2) - }) - - it('I can`t shout my own post', async () => { - const res = await clientUser1.request(mutationShoutPost, { id: 'p1234' }) - const expected = { - shout: false, - } - expect(res).toMatchObject(expected) - - const { Post } = await clientUser1.request(gql` - query { - Post(id: "p1234") { - shoutedByCurrentUser - } - } - `) - const expected2 = { - shoutedByCurrentUser: false, - } - expect(Post[0]).toMatchObject(expected2) - }) - }) - - describe('unshout foreign post', () => { - describe('unauthenticated shout', () => { - it('throws authorization error', async () => { - // shout - await clientUser1.request(mutationShoutPost, { id: 'p12345' }) - // unshout - const client = new GraphQLClient(host) - await expect(client.request(mutationUnshoutPost, { id: 'p12345' })).rejects.toThrow( - 'Not Authorised', - ) + postAuthor = await factory.create('User', { + id: 'id-of-another-user', + name: 'Another User', + email: 'another.user@example.org', + password: '1234', + }) + authenticatedUser = await currentUser.toJson() + await factory.create('Post', { + name: 'Posted By Another User', + id: 'posted-by-another-user', + author: postAuthor, + }) + await mutate({ + mutation: mutationShoutPost, + variables: { id: 'posted-by-another-user' }, + }) + variables = {} }) - }) - it('I unshout a post of another user', async () => { - // shout - await clientUser1.request(mutationShoutPost, { id: 'p12345' }) - const expected = { - unshout: true, - } - // unshout - const res = await clientUser1.request(mutationUnshoutPost, { id: 'p12345' }) - expect(res).toMatchObject(expected) - - const { Post } = await clientUser1.request(gql` - query { - Post(id: "p12345") { - shoutedByCurrentUser - } - } - `) - const expected2 = { - shoutedByCurrentUser: false, - } - expect(Post[0]).toMatchObject(expected2) + it("another user's post", async () => { + variables = { id: 'posted-by-another-user' } + await expect(mutate({ mutation: mutationUnshoutPost, variables })).resolves.toMatchObject({ + data: { unshout: true }, + }) + await expect(query({ query: queryPost, variables })).resolves.toMatchObject({ + data: { Post: [{ id: 'posted-by-another-user', shoutedBy: [] }] }, + errors: undefined, + }) + }) }) }) }) diff --git a/backend/yarn.lock b/backend/yarn.lock index 29f0126da..557988bfb 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -14,10 +14,10 @@ resolved "https://registry.yarnpkg.com/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.24.tgz#3ce939cb127fb8aaa3ffc1e90dff9b8af9f2e3dc" integrity sha512-8GqG48m1XqyXh4mIZrtB5xOhUwSsh1WsrrsaZQOEYYql3YN9DEu9OOSg0ILzXHZo/h2Q74777YE4YzlArQzQEQ== -"@babel/cli@~7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.6.0.tgz#1470a04394eaf37862989ea4912adf440fa6ff8d" - integrity sha512-1CTDyGUjQqW3Mz4gfKZ04KGOckyyaNmKneAMlABPS+ZyuxWv3FrVEVz7Ag08kNIztVx8VaJ8YgvYLSNlMKAT5Q== +"@babel/cli@~7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.6.2.tgz#4ce8b5b4b2e4b4c1b7bd841cec62085e2dfc4465" + integrity sha512-JDZ+T/br9pPfT2lmAMJypJDTTTHM9ePD/ED10TRjRzJVdEVy+JB3iRlhzYmTt5YkNgHvxWGlUVnLtdv6ruiDrQ== dependencies: commander "^2.8.1" convert-source-map "^1.1.0" @@ -38,17 +38,17 @@ dependencies: "@babel/highlight" "^7.0.0" -"@babel/core@^7.1.0", "@babel/core@~7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.6.0.tgz#9b00f73554edd67bebc86df8303ef678be3d7b48" - integrity sha512-FuRhDRtsd6IptKpHXAa+4WPZYY2ZzgowkbLBecEDDSje1X/apG7jQM33or3NdOmjXBKWGOg4JmSiRfUfuTtHXw== +"@babel/core@^7.1.0", "@babel/core@~7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.6.2.tgz#069a776e8d5e9eefff76236bc8845566bd31dd91" + integrity sha512-l8zto/fuoZIbncm+01p8zPSDZu/VuuJhAfA7d/AbzM09WR7iVhavvfNDYCNpo1VvLk6E6xgAoP9P+/EMJHuRkQ== dependencies: "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.6.0" - "@babel/helpers" "^7.6.0" - "@babel/parser" "^7.6.0" + "@babel/generator" "^7.6.2" + "@babel/helpers" "^7.6.2" + "@babel/parser" "^7.6.2" "@babel/template" "^7.6.0" - "@babel/traverse" "^7.6.0" + "@babel/traverse" "^7.6.2" "@babel/types" "^7.6.0" convert-source-map "^1.1.0" debug "^4.1.0" @@ -58,16 +58,15 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/generator@^7.4.0", "@babel/generator@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.0.tgz#e2c21efbfd3293ad819a2359b448f002bfdfda56" - integrity sha512-Ms8Mo7YBdMMn1BYuNtKuP/z0TgEIhbcyB8HVR6PPNYp4P61lMsABiS4A3VG1qznjXVCf3r+fVHhm4efTYVsySA== +"@babel/generator@^7.4.0", "@babel/generator@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.6.2.tgz#dac8a3c2df118334c2a29ff3446da1636a8f8c03" + integrity sha512-j8iHaIW4gGPnViaIHI7e9t/Hl8qLjERI6DcV9kEpAIDJsAOrcnXqRS7t+QbhL76pwbtqP+QCQLL0z1CyVmtjjQ== dependencies: "@babel/types" "^7.6.0" jsesc "^2.5.1" lodash "^4.17.13" source-map "^0.5.0" - trim-right "^1.0.1" "@babel/helper-annotate-as-pure@^7.0.0": version "7.0.0" @@ -224,13 +223,13 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.2.0" -"@babel/helpers@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.6.0.tgz#21961d16c6a3c3ab597325c34c465c0887d31c6e" - integrity sha512-W9kao7OBleOjfXtFGgArGRX6eCP0UEcA2ZWEWNkJdRZnHhW4eEbeswbG3EwaRsnQUAEGWYgMq1HsIXuNNNy2eQ== +"@babel/helpers@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.6.2.tgz#681ffe489ea4dcc55f23ce469e58e59c1c045153" + integrity sha512-3/bAUL8zZxYs1cdX2ilEE0WobqbCmKWr/889lf2SS0PpDcpEIY8pb1CCyz0pEcX3pEb+MCbks1jIokz2xLtGTA== dependencies: "@babel/template" "^7.6.0" - "@babel/traverse" "^7.6.0" + "@babel/traverse" "^7.6.2" "@babel/types" "^7.6.0" "@babel/highlight@^7.0.0": @@ -254,10 +253,10 @@ node-environment-flags "^1.0.5" v8flags "^3.1.1" -"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.0.tgz#3e05d0647432a8326cb28d0de03895ae5a57f39b" - integrity sha512-+o2q111WEx4srBs7L9eJmcwi655eD8sXniLqMB93TBK9GrNzGrxDWSjiqz2hLU0Ha8MTXFIP0yd9fNdP+m43ZQ== +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.6.0", "@babel/parser@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.6.2.tgz#205e9c95e16ba3b8b96090677a67c9d6075b70a1" + integrity sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg== "@babel/plugin-proposal-async-generator-functions@^7.2.0": version "7.2.0" @@ -704,16 +703,16 @@ "@babel/parser" "^7.6.0" "@babel/types" "^7.6.0" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5", "@babel/traverse@^7.6.0": - version "7.6.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.0.tgz#389391d510f79be7ce2ddd6717be66d3fed4b516" - integrity sha512-93t52SaOBgml/xY74lsmt7xOR4ufYvhb5c5qiM6lu4J/dWGMAfAh6eKw4PjLes6DI6nQgearoxnFJk60YchpvQ== +"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5", "@babel/traverse@^7.6.2": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.6.2.tgz#b0e2bfd401d339ce0e6c05690206d1e11502ce2c" + integrity sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ== dependencies: "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.6.0" + "@babel/generator" "^7.6.2" "@babel/helper-function-name" "^7.1.0" "@babel/helper-split-export-declaration" "^7.4.4" - "@babel/parser" "^7.6.0" + "@babel/parser" "^7.6.2" "@babel/types" "^7.6.0" debug "^4.1.0" globals "^11.1.0" @@ -736,10 +735,10 @@ exec-sh "^0.3.2" minimist "^1.2.0" -"@hapi/address@2.x.x", "@hapi/address@^2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.1.tgz#61395b5ed94c4cb19c2dc4c85969cff3d40d583f" - integrity sha512-DYuHzu978pP1XW1GD3HGvLnAFjbQTIgc2+V153FGkbS2pgo9haigCdwBnUDrbhaOkgiJlbZvoEqDrcxSLHpiWA== +"@hapi/address@2.x.x", "@hapi/address@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.2.tgz#1c794cd6dbf2354d1eb1ef10e0303f573e1c7222" + integrity sha512-O4QDrx+JoGKZc6aN64L04vqa7e41tIiLU+OvKdcYaEMP97UttL0f9GIi9/0A4WAMx0uBd6SidDIhktZhgOcN8Q== "@hapi/bourne@1.x.x": version "1.3.2" @@ -766,12 +765,12 @@ "@hapi/hoek" "8.x.x" "@hapi/topo" "3.x.x" -"@hapi/joi@^16.1.2": - version "16.1.2" - resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-16.1.2.tgz#c566d9e0d81d6847f7622f7d5e23adadaa2d7332" - integrity sha512-wkMIEMQQPNmat9P7zws7wO8Gon9W3NgG5Pac1m0LK8bQ1bbszofxzL0CJogAgzitk5rZZw5/txR+wOK/ioLmGw== +"@hapi/joi@^16.1.4": + version "16.1.4" + resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-16.1.4.tgz#b039fe474a0ab838c1a90620c53a208fcef75d99" + integrity sha512-m7ctezhxjob+dSpXnCNlgAj6rrEpdSsaWu3GWL3g1AybQCU36mlAo9IwGFJwIxD+oHgdO6mYyviYlaejX+qN6g== dependencies: - "@hapi/address" "^2.1.1" + "@hapi/address" "^2.1.2" "@hapi/formula" "^1.2.0" "@hapi/hoek" "^8.2.4" "@hapi/pinpoint" "^1.0.2" @@ -1764,12 +1763,12 @@ apollo-server-plugin-base@^0.6.4: dependencies: apollo-server-types "^0.2.4" -apollo-server-testing@~2.9.3: - version "2.9.3" - resolved "https://registry.yarnpkg.com/apollo-server-testing/-/apollo-server-testing-2.9.3.tgz#38a86b5fa0bce57f8ec4fb581e5419437178b3e2" - integrity sha512-n2bIcVXQNFzr84FZK1S0o4PFqwb1pPuIg/fymjPYjtFP2OHmLLvGRm+KaXhUjxEAUh+/9zAQLhmgx+p6GMUAhA== +apollo-server-testing@~2.9.4: + version "2.9.4" + resolved "https://registry.yarnpkg.com/apollo-server-testing/-/apollo-server-testing-2.9.4.tgz#421783573bdc5cef70dfe574b5193db38a33b5fb" + integrity sha512-qvnA9cXRKqizfYPHBli4LeSKYXwFVsQkGF3eHgofN/RbTqnEBqW7I5L14qDYAjGZg9/Z4alJf69hFE8KPHbT0Q== dependencies: - apollo-server-core "^2.9.3" + apollo-server-core "^2.9.4" apollo-server-types@^0.2.4: version "0.2.4" @@ -5911,12 +5910,12 @@ metascraper-date@^5.7.4: dependencies: "@metascraper/helpers" "^5.7.4" -metascraper-description@^5.7.4: - version "5.7.4" - resolved "https://registry.yarnpkg.com/metascraper-description/-/metascraper-description-5.7.4.tgz#f1fd88ee5b1c1fac5e7db3dcae8c69e342e6efd6" - integrity sha512-qncq4IjsFK+ZEdWjtjhokozoWu76qfVHG/RIRHjrDG19tTwWv+PXlgyvtFaetxezI4+lR3uQHssLVb7Nv9meJw== +metascraper-description@^5.7.5: + version "5.7.5" + resolved "https://registry.yarnpkg.com/metascraper-description/-/metascraper-description-5.7.5.tgz#b19be853f7f712d2c388cb0c4086b3b38f6e603b" + integrity sha512-9WHt9XRIj7OCS1wkFbvFI4dOkdgc6I74dC78UcVlwJYJKpRRonm83i5opev4chG4psOwbUhZUhKS3n+Rb8khCg== dependencies: - "@metascraper/helpers" "^5.7.4" + "@metascraper/helpers" "^5.7.5" metascraper-image@^5.7.5: version "5.7.5" @@ -6148,10 +6147,10 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -mustache@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/mustache/-/mustache-3.0.3.tgz#ee4fb971887fa6cc1b6b6d219a74b5e3c7535f32" - integrity sha512-vM5FkMHamTYmVYeAujypihuPrJQDtaUIlKeeVb1AMJ73OZLtWiF7GprqrjxD0gJWT53W9JfqXxf97nXQjMQkqA== +mustache@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mustache/-/mustache-3.1.0.tgz#9fba26e7aefc5709f07ff585abb7e0abced6c372" + integrity sha512-3Bxq1R5LBZp7fbFPZzFe5WN4s0q3+gxZaZuZVY+QctYJiCiVgXHOTIC0/HgZuOPFt/6BQcx5u0H2CUOxT/RoGQ== mute-stream@0.0.8: version "0.0.8" @@ -8332,11 +8331,6 @@ trigram-utils@^1.0.0: n-gram "^1.0.0" trim "0.0.1" -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= - trim@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" diff --git a/docker-compose.yml b/docker-compose.yml index 587ec718f..e937feeed 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,6 +10,7 @@ services: - "BUILD_COMMIT=${TRAVIS_COMMIT}" ports: - 3000:3000 + - 3002:3002 networks: - hc-network depends_on: @@ -55,12 +56,12 @@ services: - hc-network environment: - NEO4J_AUTH=none + - NEO4J_dbms_security_procedures_unrestricted=algo.*,apoc.* ports: - 7687:7687 - 7474:7474 volumes: - neo4j_data:/data - networks: hc-network: volumes: diff --git a/package.json b/package.json index d71a399b3..94e567787 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "cross-env": "^6.0.0", "cypress": "^3.4.1", "cypress-cucumber-preprocessor": "^1.16.0", - "cypress-file-upload": "^3.3.3", + "cypress-file-upload": "^3.3.4", "cypress-plugin-retries": "^1.3.0", "dotenv": "^8.1.0", "faker": "Marak/faker.js#master", diff --git a/webapp/README.md b/webapp/README.md index 604c7e6ba..b9c235196 100644 --- a/webapp/README.md +++ b/webapp/README.md @@ -33,6 +33,42 @@ $ yarn build $ yarn start ``` +### Storybook + +We encourage contributors to use Storybook to test out new components in an isolated way, and benefit from its many features. +See the docs for live examples and answers to FAQ, among other helpful information. ![Storybook docs](https://storybook.js.org/docs/basics/introduction/) + +{% tabs %} +{% tab title="Docker" %} + +After you have started the application following the instructions above, in another terminal run: + +```bash +$ docker-compose exec webapp yarn storybook +``` +The output should look similar to this: + +![Storybook output](../.gitbook/assets/storybook-output.png) + +Click on the link http://localhost:3002/ to open the browser to your interactive storybook. + +{% endtab %} + +{% tab title="Without Docker" %} +Run the following command: + +```bash +# in webapp/ +yarn storybook +``` + +Open http://localhost:3002/ in your browser + +{% endtab %} +{% endtabs %} + + + ## Styleguide All reusable Components \(for example avatar\) should be done inside the [Nitro-Styleguide](https://github.com/Human-Connection/Nitro-Styleguide) repository. diff --git a/webapp/package.json b/webapp/package.json index 39124acf2..841b32c53 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -63,9 +63,9 @@ "apollo-client": "~2.6.4", "cookie-universal-nuxt": "~2.0.18", "cross-env": "~6.0.0", - "date-fns": "2.2.1", + "date-fns": "2.4.0", "express": "~4.17.1", - "graphql": "~14.5.7", + "graphql": "~14.5.8", "isemail": "^3.2.0", "jsonwebtoken": "~8.5.1", "linkify-it": "~2.2.0", diff --git a/webapp/yarn.lock b/webapp/yarn.lock index 5d771fc17..49375e89c 100644 --- a/webapp/yarn.lock +++ b/webapp/yarn.lock @@ -5822,10 +5822,10 @@ data-urls@^1.0.0: whatwg-mimetype "^2.2.0" whatwg-url "^7.0.0" -date-fns@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.2.1.tgz#b3f79cf56760af106050c686f4c72586a3383ee9" - integrity sha512-4V1i5CnTinjBvJpXTq7sDHD4NY6JPcl15112IeSNNLUWQOQ+kIuCvRGOFZMQZNvkadw8F9QTyZxz59rIRU6K+w== +date-fns@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.4.0.tgz#e02d1d08ce80ae1db3de40a0028c9f54203d034b" + integrity sha512-xS547fK1omgCgOGbyU0fBY2pdeXQ9/WO/PMsVgX1jtF56dXNHrV3Z+GKWIOE7IG+UEeu+fTyTlnIvBKbxXxdSw== date-fns@^1.27.2: version "1.30.1" @@ -7748,10 +7748,10 @@ graphql-upload@^8.0.2: http-errors "^1.7.2" object-path "^0.11.4" -"graphql@14.0.2 - 14.2.0 || ^14.3.1", graphql@^14.4.0, graphql@~14.5.7: - version "14.5.7" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.5.7.tgz#8646a3fcc07922319cc3967eba4a64b32929f77f" - integrity sha512-as410RMJSUFqF8RcH2QWxZ5ioqHzsH9VWnWbaU+UnDXJ/6azMDIYPrtXCBPXd8rlunEVb7W8z6fuUnNHMbFu9A== +"graphql@14.0.2 - 14.2.0 || ^14.3.1", graphql@^14.4.0, graphql@~14.5.8: + version "14.5.8" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.5.8.tgz#504f3d3114cb9a0a3f359bbbcf38d9e5bf6a6b3c" + integrity sha512-MMwmi0zlVLQKLdGiMfWkgQD7dY/TUKt4L+zgJ/aR0Howebod3aNgP5JkgvAULiR2HPVZaP2VEElqtdidHweLkg== dependencies: iterall "^1.2.2" diff --git a/yarn.lock b/yarn.lock index 0380317ee..54937694e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1894,10 +1894,10 @@ cypress-cucumber-preprocessor@^1.16.0: glob "^7.1.2" through "^2.3.8" -cypress-file-upload@^3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/cypress-file-upload/-/cypress-file-upload-3.3.3.tgz#119188fa78e9cfc00904c52d76d4ca56d34950df" - integrity sha512-CmXGRMHonoyCa8EcF6jomxqMAe56HvKfnW7S69EmTga8ecYmvQUI6gYttcHO+5UTmFQOFl7xbABV3+AbnI4btA== +cypress-file-upload@^3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/cypress-file-upload/-/cypress-file-upload-3.3.4.tgz#cbeb8a7a07150a1c60f2873666979e48b6335070" + integrity sha512-kfdrQ6cWBw82G7EbHSqZJiOQWRh9cGz9K1mjePNZax00gBL0qOdRTjfkAnR2vEmmJyCfnN3efryjfhFeLrGWVw== cypress-plugin-retries@^1.3.0: version "1.3.0"