diff --git a/.github/workflows/test-e2e.yml b/.github/workflows/test-e2e.yml index 9d007c451..74ebd1c43 100644 --- a/.github/workflows/test-e2e.yml +++ b/.github/workflows/test-e2e.yml @@ -24,22 +24,37 @@ jobs: - name: boot up test system | docker-compose run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps webapp neo4j backend - - name: cypress | Fullstack tests - id: e2e-tests + - name: Full stack tests | prepare run: | + wget --no-verbose -O /opt/cucumber-json-formatter "https://github.com/cucumber/json-formatter/releases/download/v19.0.0/cucumber-json-formatter-linux-386" + chmod +x /opt/cucumber-json-formatter + sudo ln -fs /opt/cucumber-json-formatter /usr/bin/cucumber-json-formatter cd backend yarn install yarn build cd .. yarn install - yarn run cypress:run --spec $(cypress/parallel-features.sh ${{ matrix.job }} ${{ env.jobs }} ) - ########################################################################## - # UPLOAD SCREENSHOTS - IF TESTS FAIL ##################################### - ########################################################################## - - name: Full stack tests | if any test failed, upload screenshots + - name: Full stack tests | run tests + id: e2e-tests + run: yarn run cypress:run --spec $(cypress/parallel-features.sh ${{ matrix.job }} ${{ env.jobs }} ) + + - name: Full stack tests | if tests failed, compile html report + if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }} + run: | + cd cypress/ + node create-cucumber-html-report.js + + - name: End-to-end tests | if tests failed, get pr number + id: pr + if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }} + uses: 8BitJonny/gh-get-current-pr@2.2.0 + + - name: End-to-end tests | if tests failed, upload report + id: e2e-report if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }} uses: actions/upload-artifact@v3 with: - name: cypress-screenshots - path: cypress/screenshots/ + name: ocelot-e2e-test-report-pr${{ steps.pr.outputs.number }} + path: /home/runner/work/Ocelot-Social/Ocelot-Social/cypress/reports/cucumber_html_report + diff --git a/backend/jest.config.js b/backend/jest.config.js index 264ad13c0..d1cc7bd3f 100644 --- a/backend/jest.config.js +++ b/backend/jest.config.js @@ -11,7 +11,7 @@ module.exports = { ], coverageThreshold: { global: { - lines: 70, + lines: 67, }, }, testMatch: ['**/src/**/?(*.)+(spec|test).ts?(x)'], diff --git a/backend/src/db/seed.ts b/backend/src/db/seed.ts index 338a30fdf..a717ff7a6 100644 --- a/backend/src/db/seed.ts +++ b/backend/src/db/seed.ts @@ -38,244 +38,235 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] }) const { mutate } = createTestClient(server) - const [Hamburg, Berlin, Germany, Paris, France] = await Promise.all([ - Factory.build('location', { - id: 'region.5127278006398860', - name: 'Hamburg', - type: 'region', - lng: 10.0, - lat: 53.55, - nameES: 'Hamburgo', - nameFR: 'Hambourg', - nameIT: 'Amburgo', - nameEN: 'Hamburg', - namePT: 'Hamburgo', - nameDE: 'Hamburg', - nameNL: 'Hamburg', - namePL: 'Hamburg', - nameRU: 'Гамбург', - }), - Factory.build('location', { - id: 'region.14880313158564380', - type: 'region', - name: 'Berlin', - lng: 13.38333, - lat: 52.51667, - nameES: 'Berlín', - nameFR: 'Berlin', - nameIT: 'Berlino', - nameEN: 'Berlin', - namePT: 'Berlim', - nameDE: 'Berlin', - nameNL: 'Berlijn', - namePL: 'Berlin', - nameRU: 'Берлин', - }), - Factory.build('location', { - id: 'country.10743216036480410', - name: 'Germany', - type: 'country', - namePT: 'Alemanha', - nameDE: 'Deutschland', - nameES: 'Alemania', - nameNL: 'Duitsland', - namePL: 'Niemcy', - nameFR: 'Allemagne', - nameIT: 'Germania', - nameEN: 'Germany', - nameRU: 'Германия', - }), - Factory.build('location', { - id: 'region.9397217726497330', - name: 'Paris', - type: 'region', - lng: 2.35183, - lat: 48.85658, - nameES: 'París', - nameFR: 'Paris', - nameIT: 'Parigi', - nameEN: 'Paris', - namePT: 'Paris', - nameDE: 'Paris', - nameNL: 'Parijs', - namePL: 'Paryż', - nameRU: 'Париж', - }), - Factory.build('location', { - id: 'country.9759535382641660', - name: 'France', - type: 'country', - namePT: 'França', - nameDE: 'Frankreich', - nameES: 'Francia', - nameNL: 'Frankrijk', - namePL: 'Francja', - nameFR: 'France', - nameIT: 'Francia', - nameEN: 'France', - nameRU: 'Франция', - }), - ]) - await Promise.all([ - Berlin.relateTo(Germany, 'isIn'), - Hamburg.relateTo(Germany, 'isIn'), - Paris.relateTo(France, 'isIn'), - ]) + // locations + const Hamburg = await Factory.build('location', { + id: 'region.5127278006398860', + name: 'Hamburg', + type: 'region', + lng: 10.0, + lat: 53.55, + nameES: 'Hamburgo', + nameFR: 'Hambourg', + nameIT: 'Amburgo', + nameEN: 'Hamburg', + namePT: 'Hamburgo', + nameDE: 'Hamburg', + nameNL: 'Hamburg', + namePL: 'Hamburg', + nameRU: 'Гамбург', + }) + const Berlin = await Factory.build('location', { + id: 'region.14880313158564380', + type: 'region', + name: 'Berlin', + lng: 13.38333, + lat: 52.51667, + nameES: 'Berlín', + nameFR: 'Berlin', + nameIT: 'Berlino', + nameEN: 'Berlin', + namePT: 'Berlim', + nameDE: 'Berlin', + nameNL: 'Berlijn', + namePL: 'Berlin', + nameRU: 'Берлин', + }) + const Germany = await Factory.build('location', { + id: 'country.10743216036480410', + name: 'Germany', + type: 'country', + namePT: 'Alemanha', + nameDE: 'Deutschland', + nameES: 'Alemania', + nameNL: 'Duitsland', + namePL: 'Niemcy', + nameFR: 'Allemagne', + nameIT: 'Germania', + nameEN: 'Germany', + nameRU: 'Германия', + }) + const Paris = await Factory.build('location', { + id: 'region.9397217726497330', + name: 'Paris', + type: 'region', + lng: 2.35183, + lat: 48.85658, + nameES: 'París', + nameFR: 'Paris', + nameIT: 'Parigi', + nameEN: 'Paris', + namePT: 'Paris', + nameDE: 'Paris', + nameNL: 'Parijs', + namePL: 'Paryż', + nameRU: 'Париж', + }) + const France = await Factory.build('location', { + id: 'country.9759535382641660', + name: 'France', + type: 'country', + namePT: 'França', + nameDE: 'Frankreich', + nameES: 'Francia', + nameNL: 'Frankrijk', + namePL: 'Francja', + nameFR: 'France', + nameIT: 'Francia', + nameEN: 'France', + nameRU: 'Франция', + }) + await Berlin.relateTo(Germany, 'isIn') + await Hamburg.relateTo(Germany, 'isIn') + await Paris.relateTo(France, 'isIn') - const [racoon, rabbit, wolf, bear, turtle, rhino] = await Promise.all([ - Factory.build('badge', { - id: 'indiegogo_en_racoon', - icon: '/img/badges/indiegogo_en_racoon.svg', - }), - Factory.build('badge', { - id: 'indiegogo_en_rabbit', - icon: '/img/badges/indiegogo_en_rabbit.svg', - }), - Factory.build('badge', { - id: 'indiegogo_en_wolf', - icon: '/img/badges/indiegogo_en_wolf.svg', - }), - Factory.build('badge', { - id: 'indiegogo_en_bear', - icon: '/img/badges/indiegogo_en_bear.svg', - }), - Factory.build('badge', { - id: 'indiegogo_en_turtle', - icon: '/img/badges/indiegogo_en_turtle.svg', - }), - Factory.build('badge', { - id: 'indiegogo_en_rhino', - icon: '/img/badges/indiegogo_en_rhino.svg', - }), - ]) + // badges + const racoon = await Factory.build('badge', { + id: 'indiegogo_en_racoon', + icon: '/img/badges/indiegogo_en_racoon.svg', + }) + const rabbit = await Factory.build('badge', { + id: 'indiegogo_en_rabbit', + icon: '/img/badges/indiegogo_en_rabbit.svg', + }) + const wolf = await Factory.build('badge', { + id: 'indiegogo_en_wolf', + icon: '/img/badges/indiegogo_en_wolf.svg', + }) + const bear = await Factory.build('badge', { + id: 'indiegogo_en_bear', + icon: '/img/badges/indiegogo_en_bear.svg', + }) + const turtle = await Factory.build('badge', { + id: 'indiegogo_en_turtle', + icon: '/img/badges/indiegogo_en_turtle.svg', + }) + const rhino = await Factory.build('badge', { + id: 'indiegogo_en_rhino', + icon: '/img/badges/indiegogo_en_rhino.svg', + }) - const [peterLustig, bobDerBaumeister, jennyRostock, huey, dewey, louie, dagobert] = - await Promise.all([ - Factory.build( - 'user', - { - id: 'u1', - name: 'Peter Lustig', - slug: 'peter-lustig', - role: 'admin', - }, - { - email: 'admin@example.org', - }, - ), - Factory.build( - 'user', - { - id: 'u2', - name: 'Bob der Baumeister', - slug: 'bob-der-baumeister', - role: 'moderator', - }, - { - email: 'moderator@example.org', - avatar: null, - }, - ), - Factory.build( - 'user', - { - id: 'u3', - name: 'Jenny Rostock', - slug: 'jenny-rostock', - role: 'user', - }, - { - email: 'user@example.org', - }, - ), - Factory.build( - 'user', - { - id: 'u4', - name: 'Huey', - slug: 'huey', - role: 'user', - }, - { - email: 'huey@example.org', - }, - ), - Factory.build( - 'user', - { - id: 'u5', - name: 'Dewey', - slug: 'dewey', - role: 'user', - }, - { - email: 'dewey@example.org', - avatar: null, - }, - ), - Factory.build( - 'user', - { - id: 'u6', - name: 'Louie', - slug: 'louie', - role: 'user', - }, - { - email: 'louie@example.org', - }, - ), - Factory.build( - 'user', - { - id: 'u7', - name: 'Dagobert', - slug: 'dagobert', - role: 'user', - }, - { - email: 'dagobert@example.org', - }, - ), - ]) + // users + const peterLustig = await Factory.build( + 'user', + { + id: 'u1', + name: 'Peter Lustig', + slug: 'peter-lustig', + role: 'admin', + }, + { + email: 'admin@example.org', + }, + ) + const bobDerBaumeister = await Factory.build( + 'user', + { + id: 'u2', + name: 'Bob der Baumeister', + slug: 'bob-der-baumeister', + role: 'moderator', + }, + { + email: 'moderator@example.org', + avatar: null, + }, + ) + const jennyRostock = await Factory.build( + 'user', + { + id: 'u3', + name: 'Jenny Rostock', + slug: 'jenny-rostock', + role: 'user', + }, + { + email: 'user@example.org', + }, + ) + const huey = await Factory.build( + 'user', + { + id: 'u4', + name: 'Huey', + slug: 'huey', + role: 'user', + }, + { + email: 'huey@example.org', + }, + ) + const dewey = await Factory.build( + 'user', + { + id: 'u5', + name: 'Dewey', + slug: 'dewey', + role: 'user', + }, + { + email: 'dewey@example.org', + avatar: null, + }, + ) + const louie = await Factory.build( + 'user', + { + id: 'u6', + name: 'Louie', + slug: 'louie', + role: 'user', + }, + { + email: 'louie@example.org', + }, + ) + const dagobert = await Factory.build( + 'user', + { + id: 'u7', + name: 'Dagobert', + slug: 'dagobert', + role: 'user', + }, + { + email: 'dagobert@example.org', + }, + ) - await Promise.all([ - peterLustig.relateTo(Berlin, 'isIn'), - bobDerBaumeister.relateTo(Hamburg, 'isIn'), - jennyRostock.relateTo(Paris, 'isIn'), - huey.relateTo(Paris, 'isIn'), - ]) + await peterLustig.relateTo(Berlin, 'isIn') + await bobDerBaumeister.relateTo(Hamburg, 'isIn') + await jennyRostock.relateTo(Paris, 'isIn') + await huey.relateTo(Paris, 'isIn') - await Promise.all([ - peterLustig.relateTo(racoon, 'rewarded'), - peterLustig.relateTo(rhino, 'rewarded'), - peterLustig.relateTo(wolf, 'rewarded'), - bobDerBaumeister.relateTo(racoon, 'rewarded'), - bobDerBaumeister.relateTo(turtle, 'rewarded'), - jennyRostock.relateTo(bear, 'rewarded'), - dagobert.relateTo(rabbit, 'rewarded'), + await peterLustig.relateTo(racoon, 'rewarded') + await peterLustig.relateTo(rhino, 'rewarded') + await peterLustig.relateTo(wolf, 'rewarded') + await bobDerBaumeister.relateTo(racoon, 'rewarded') + await bobDerBaumeister.relateTo(turtle, 'rewarded') + await jennyRostock.relateTo(bear, 'rewarded') + await dagobert.relateTo(rabbit, 'rewarded') - peterLustig.relateTo(bobDerBaumeister, 'friends'), - peterLustig.relateTo(jennyRostock, 'friends'), - bobDerBaumeister.relateTo(jennyRostock, 'friends'), + await peterLustig.relateTo(bobDerBaumeister, 'friends') + await peterLustig.relateTo(jennyRostock, 'friends') + await bobDerBaumeister.relateTo(jennyRostock, 'friends') - peterLustig.relateTo(jennyRostock, 'following'), - peterLustig.relateTo(huey, 'following'), - bobDerBaumeister.relateTo(huey, 'following'), - jennyRostock.relateTo(huey, 'following'), - huey.relateTo(dewey, 'following'), - dewey.relateTo(huey, 'following'), - louie.relateTo(jennyRostock, 'following'), + await peterLustig.relateTo(jennyRostock, 'following') + await peterLustig.relateTo(huey, 'following') + await bobDerBaumeister.relateTo(huey, 'following') + await jennyRostock.relateTo(huey, 'following') + await huey.relateTo(dewey, 'following') + await dewey.relateTo(huey, 'following') + await louie.relateTo(jennyRostock, 'following') - huey.relateTo(dagobert, 'muted'), - dewey.relateTo(dagobert, 'muted'), - louie.relateTo(dagobert, 'muted'), + await huey.relateTo(dagobert, 'muted') + await dewey.relateTo(dagobert, 'muted') + await louie.relateTo(dagobert, 'muted') - dagobert.relateTo(huey, 'blocked'), - dagobert.relateTo(dewey, 'blocked'), - dagobert.relateTo(louie, 'blocked'), - ]) + await dagobert.relateTo(huey, 'blocked') + await dagobert.relateTo(dewey, 'blocked') + await dagobert.relateTo(louie, 'blocked') + // categories await Promise.all( categories.map(({ icon, name }, index) => { return Factory.build('category', { @@ -287,23 +278,20 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] }), ) - const [environment, nature, democracy, freedom] = await Promise.all([ - Factory.build('tag', { - id: 'Environment', - }), - Factory.build('tag', { - id: 'Nature', - }), - Factory.build('tag', { - id: 'Democracy', - }), - Factory.build('tag', { - id: 'Freedom', - }), - ]) - - // Create Groups + const environment = await Factory.build('tag', { + id: 'Environment', + }) + const nature = await Factory.build('tag', { + id: 'Nature', + }) + const democracy = await Factory.build('tag', { + id: 'Democracy', + }) + const freedom = await Factory.build('tag', { + id: 'Freedom', + }) + // groups authenticatedUser = await peterLustig.toJson() await Promise.all([ mutate({ @@ -668,166 +656,164 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] eventStart: new Date(now.getFullYear(), now.getMonth(), now.getDate() - 3).toISOString(), }) - // Create Posts (Articles) - - const [p0, p1, p3, p4, p5, p6, p9, p10, p11, p13, p14, p15] = await Promise.all([ - Factory.build( - 'post', - { - id: 'p0', - language: sample(languages), - }, - { - categoryIds: ['cat16'], - author: peterLustig, - image: Factory.build('image', { - url: faker.image.unsplash.food(300, 169), - sensitive: true, - aspectRatio: 300 / 169, - }), - }, - ), - Factory.build( - 'post', - { - id: 'p1', - language: sample(languages), - }, - { - categoryIds: ['cat1'], - author: bobDerBaumeister, - image: Factory.build('image', { - url: faker.image.unsplash.technology(300, 1500), - aspectRatio: 300 / 1500, - }), - }, - ), - Factory.build( - 'post', - { - id: 'p3', - language: sample(languages), - }, - { - categoryIds: ['cat3'], - author: huey, - }, - ), - Factory.build( - 'post', - { - id: 'p4', - language: sample(languages), - }, - { - categoryIds: ['cat4'], - author: dewey, - }, - ), - Factory.build( - 'post', - { - id: 'p5', - language: sample(languages), - }, - { - categoryIds: ['cat5'], - author: louie, - }, - ), - Factory.build( - 'post', - { - id: 'p6', - language: sample(languages), - }, - { - categoryIds: ['cat6'], - author: peterLustig, - image: Factory.build('image', { - url: faker.image.unsplash.buildings(300, 857), - aspectRatio: 300 / 857, - }), - }, - ), - Factory.build( - 'post', - { - id: 'p9', - language: sample(languages), - }, - { - categoryIds: ['cat9'], - author: huey, - }, - ), - Factory.build( - 'post', - { - id: 'p10', - }, - { - categoryIds: ['cat10'], - author: dewey, - image: Factory.build('image', { - sensitive: true, - }), - }, - ), - Factory.build( - 'post', - { - id: 'p11', - language: sample(languages), - }, - { - categoryIds: ['cat11'], - author: louie, - image: Factory.build('image', { - url: faker.image.unsplash.people(300, 901), - aspectRatio: 300 / 901, - }), - }, - ), - Factory.build( - 'post', - { - id: 'p13', - language: sample(languages), - }, - { - categoryIds: ['cat13'], - author: bobDerBaumeister, - }, - ), - Factory.build( - 'post', - { - id: 'p14', - language: sample(languages), - }, - { - categoryIds: ['cat14'], - author: jennyRostock, - image: Factory.build('image', { - url: faker.image.unsplash.objects(300, 200), - aspectRatio: 300 / 450, - }), - }, - ), - Factory.build( - 'post', - { - id: 'p15', - language: sample(languages), - }, - { - categoryIds: ['cat15'], - author: huey, - }, - ), - ]) + // posts (articles) + const p0 = await Factory.build( + 'post', + { + id: 'p0', + language: sample(languages), + }, + { + categoryIds: ['cat16'], + author: peterLustig, + image: Factory.build('image', { + url: faker.image.unsplash.food(300, 169), + sensitive: true, + aspectRatio: 300 / 169, + }), + }, + ) + const p1 = await Factory.build( + 'post', + { + id: 'p1', + language: sample(languages), + }, + { + categoryIds: ['cat1'], + author: bobDerBaumeister, + image: Factory.build('image', { + url: faker.image.unsplash.technology(300, 1500), + aspectRatio: 300 / 1500, + }), + }, + ) + const p3 = await Factory.build( + 'post', + { + id: 'p3', + language: sample(languages), + }, + { + categoryIds: ['cat3'], + author: huey, + }, + ) + const p4 = await Factory.build( + 'post', + { + id: 'p4', + language: sample(languages), + }, + { + categoryIds: ['cat4'], + author: dewey, + }, + ) + const p5 = await Factory.build( + 'post', + { + id: 'p5', + language: sample(languages), + }, + { + categoryIds: ['cat5'], + author: louie, + }, + ) + const p6 = await Factory.build( + 'post', + { + id: 'p6', + language: sample(languages), + }, + { + categoryIds: ['cat6'], + author: peterLustig, + image: Factory.build('image', { + url: faker.image.unsplash.buildings(300, 857), + aspectRatio: 300 / 857, + }), + }, + ) + const p9 = await Factory.build( + 'post', + { + id: 'p9', + language: sample(languages), + }, + { + categoryIds: ['cat9'], + author: huey, + }, + ) + const p10 = await Factory.build( + 'post', + { + id: 'p10', + }, + { + categoryIds: ['cat10'], + author: dewey, + image: Factory.build('image', { + sensitive: true, + }), + }, + ) + const p11 = await Factory.build( + 'post', + { + id: 'p11', + language: sample(languages), + }, + { + categoryIds: ['cat11'], + author: louie, + image: Factory.build('image', { + url: faker.image.unsplash.people(300, 901), + aspectRatio: 300 / 901, + }), + }, + ) + const p13 = await Factory.build( + 'post', + { + id: 'p13', + language: sample(languages), + }, + { + categoryIds: ['cat13'], + author: bobDerBaumeister, + }, + ) + const p14 = await Factory.build( + 'post', + { + id: 'p14', + language: sample(languages), + }, + { + categoryIds: ['cat14'], + author: jennyRostock, + image: Factory.build('image', { + url: faker.image.unsplash.objects(300, 200), + aspectRatio: 300 / 450, + }), + }, + ) + const p15 = await Factory.build( + 'post', + { + id: 'p15', + language: sample(languages), + }, + { + categoryIds: ['cat15'], + author: huey, + }, + ) + // invite code await Factory.build( 'inviteCode', { @@ -924,8 +910,9 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] ]) authenticatedUser = null - const comments = await Promise.all([ - Factory.build( + const comments: any[] = [] + comments.push( + await Factory.build( 'comment', { id: 'c1', @@ -935,7 +922,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p1', }, ), - Factory.build( + await Factory.build( 'comment', { id: 'c2', @@ -945,7 +932,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p1', }, ), - Factory.build( + await Factory.build( 'comment', { id: 'c3', @@ -955,7 +942,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p3', }, ), - Factory.build( + await Factory.build( 'comment', { id: 'c5', @@ -965,7 +952,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p3', }, ), - Factory.build( + await Factory.build( 'comment', { id: 'c6', @@ -975,7 +962,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p4', }, ), - Factory.build( + await Factory.build( 'comment', { id: 'c7', @@ -985,7 +972,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p2', }, ), - Factory.build( + await Factory.build( 'comment', { id: 'c8', @@ -995,7 +982,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p15', }, ), - Factory.build( + await Factory.build( 'comment', { id: 'c9', @@ -1005,7 +992,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p15', }, ), - Factory.build( + await Factory.build( 'comment', { id: 'c10', @@ -1015,7 +1002,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p15', }, ), - Factory.build( + await Factory.build( 'comment', { id: 'c11', @@ -1025,7 +1012,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p15', }, ), - Factory.build( + await Factory.build( 'comment', { id: 'c12', @@ -1035,84 +1022,81 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] postId: 'p15', }, ), - ]) + ) const trollingComment = comments[0] - await Promise.all([ - democracy.relateTo(p3, 'post'), - democracy.relateTo(p11, 'post'), - democracy.relateTo(p15, 'post'), - democracy.relateTo(p7, 'post'), - environment.relateTo(p1, 'post'), - environment.relateTo(p5, 'post'), - environment.relateTo(p9, 'post'), - environment.relateTo(p13, 'post'), - freedom.relateTo(p0, 'post'), - freedom.relateTo(p4, 'post'), - freedom.relateTo(p8, 'post'), - freedom.relateTo(p12, 'post'), - nature.relateTo(p2, 'post'), - nature.relateTo(p6, 'post'), - nature.relateTo(p10, 'post'), - nature.relateTo(p14, 'post'), - peterLustig.relateTo(p15, 'emoted', { emotion: 'surprised' }), - bobDerBaumeister.relateTo(p15, 'emoted', { emotion: 'surprised' }), - jennyRostock.relateTo(p15, 'emoted', { emotion: 'surprised' }), - huey.relateTo(p15, 'emoted', { emotion: 'surprised' }), - dewey.relateTo(p15, 'emoted', { emotion: 'surprised' }), - louie.relateTo(p15, 'emoted', { emotion: 'surprised' }), - dagobert.relateTo(p15, 'emoted', { emotion: 'surprised' }), - bobDerBaumeister.relateTo(p14, 'emoted', { emotion: 'cry' }), - jennyRostock.relateTo(p13, 'emoted', { emotion: 'angry' }), - huey.relateTo(p12, 'emoted', { emotion: 'funny' }), - dewey.relateTo(p11, 'emoted', { emotion: 'surprised' }), - louie.relateTo(p10, 'emoted', { emotion: 'cry' }), - dewey.relateTo(p9, 'emoted', { emotion: 'happy' }), - huey.relateTo(p8, 'emoted', { emotion: 'angry' }), - jennyRostock.relateTo(p7, 'emoted', { emotion: 'funny' }), - bobDerBaumeister.relateTo(p6, 'emoted', { emotion: 'surprised' }), - peterLustig.relateTo(p5, 'emoted', { emotion: 'cry' }), - bobDerBaumeister.relateTo(p4, 'emoted', { emotion: 'happy' }), - jennyRostock.relateTo(p3, 'emoted', { emotion: 'angry' }), - huey.relateTo(p2, 'emoted', { emotion: 'funny' }), - dewey.relateTo(p1, 'emoted', { emotion: 'surprised' }), - louie.relateTo(p0, 'emoted', { emotion: 'cry' }), - ]) + await democracy.relateTo(p3, 'post') + await democracy.relateTo(p11, 'post') + await democracy.relateTo(p15, 'post') + await democracy.relateTo(p7, 'post') + await environment.relateTo(p1, 'post') + await environment.relateTo(p5, 'post') + await environment.relateTo(p9, 'post') + await environment.relateTo(p13, 'post') + await freedom.relateTo(p0, 'post') + await freedom.relateTo(p4, 'post') + await freedom.relateTo(p8, 'post') + await freedom.relateTo(p12, 'post') + await nature.relateTo(p2, 'post') + await nature.relateTo(p6, 'post') + await nature.relateTo(p10, 'post') + await nature.relateTo(p14, 'post') + await peterLustig.relateTo(p15, 'emoted', { emotion: 'surprised' }) + await bobDerBaumeister.relateTo(p15, 'emoted', { emotion: 'surprised' }) + await jennyRostock.relateTo(p15, 'emoted', { emotion: 'surprised' }) + await huey.relateTo(p15, 'emoted', { emotion: 'surprised' }) + await dewey.relateTo(p15, 'emoted', { emotion: 'surprised' }) + await louie.relateTo(p15, 'emoted', { emotion: 'surprised' }) + await dagobert.relateTo(p15, 'emoted', { emotion: 'surprised' }) + await bobDerBaumeister.relateTo(p14, 'emoted', { emotion: 'cry' }) + await jennyRostock.relateTo(p13, 'emoted', { emotion: 'angry' }) + await huey.relateTo(p12, 'emoted', { emotion: 'funny' }) + await dewey.relateTo(p11, 'emoted', { emotion: 'surprised' }) + await louie.relateTo(p10, 'emoted', { emotion: 'cry' }) + await dewey.relateTo(p9, 'emoted', { emotion: 'happy' }) + await huey.relateTo(p8, 'emoted', { emotion: 'angry' }) + await jennyRostock.relateTo(p7, 'emoted', { emotion: 'funny' }) + await bobDerBaumeister.relateTo(p6, 'emoted', { emotion: 'surprised' }) + await peterLustig.relateTo(p5, 'emoted', { emotion: 'cry' }) + await bobDerBaumeister.relateTo(p4, 'emoted', { emotion: 'happy' }) + await jennyRostock.relateTo(p3, 'emoted', { emotion: 'angry' }) + await huey.relateTo(p2, 'emoted', { emotion: 'funny' }) + await dewey.relateTo(p1, 'emoted', { emotion: 'surprised' }) + await louie.relateTo(p0, 'emoted', { emotion: 'cry' }) - await Promise.all([ - peterLustig.relateTo(p1, 'shouted'), - peterLustig.relateTo(p6, 'shouted'), - bobDerBaumeister.relateTo(p0, 'shouted'), - bobDerBaumeister.relateTo(p6, 'shouted'), - jennyRostock.relateTo(p6, 'shouted'), - jennyRostock.relateTo(p7, 'shouted'), - huey.relateTo(p8, 'shouted'), - huey.relateTo(p9, 'shouted'), - dewey.relateTo(p10, 'shouted'), - peterLustig.relateTo(p2, 'shouted'), - peterLustig.relateTo(p6, 'shouted'), - bobDerBaumeister.relateTo(p0, 'shouted'), - bobDerBaumeister.relateTo(p6, 'shouted'), - jennyRostock.relateTo(p6, 'shouted'), - jennyRostock.relateTo(p7, 'shouted'), - huey.relateTo(p8, 'shouted'), - huey.relateTo(p9, 'shouted'), - louie.relateTo(p10, 'shouted'), - ]) - const reports = await Promise.all([ - Factory.build('report'), - Factory.build('report'), - Factory.build('report'), - Factory.build('report'), - ]) + await peterLustig.relateTo(p1, 'shouted') + await peterLustig.relateTo(p6, 'shouted') + await bobDerBaumeister.relateTo(p0, 'shouted') + await bobDerBaumeister.relateTo(p6, 'shouted') + await jennyRostock.relateTo(p6, 'shouted') + await jennyRostock.relateTo(p7, 'shouted') + await huey.relateTo(p8, 'shouted') + await huey.relateTo(p9, 'shouted') + await dewey.relateTo(p10, 'shouted') + await peterLustig.relateTo(p2, 'shouted') + await peterLustig.relateTo(p6, 'shouted') + await bobDerBaumeister.relateTo(p0, 'shouted') + await bobDerBaumeister.relateTo(p6, 'shouted') + await jennyRostock.relateTo(p6, 'shouted') + await jennyRostock.relateTo(p7, 'shouted') + await huey.relateTo(p8, 'shouted') + await huey.relateTo(p9, 'shouted') + await louie.relateTo(p10, 'shouted') + + const reports: any[] = [] + reports.push( + await Factory.build('report'), + await Factory.build('report'), + await Factory.build('report'), + await Factory.build('report'), + ) const reportAgainstDagobert = reports[0] const reportAgainstTrollingPost = reports[1] const reportAgainstTrollingComment = reports[2] const reportAgainstDewey = reports[3] // report resource first time - await reportAgainstDagobert.relateTo(jennyRostock, 'filed', { resourceId: 'u7', reasonCategory: 'discrimination_etc', @@ -1139,27 +1123,25 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] await reportAgainstDewey.relateTo(dewey, 'belongsTo') // report resource a second time - await Promise.all([ - reportAgainstDagobert.relateTo(louie, 'filed', { - resourceId: 'u7', - reasonCategory: 'discrimination_etc', - reasonDescription: 'this user is attacking me for who I am!', - }), - reportAgainstDagobert.relateTo(dagobert, 'belongsTo'), - reportAgainstTrollingPost.relateTo(peterLustig, 'filed', { - resourceId: 'p2', - reasonCategory: 'discrimination_etc', - reasonDescription: 'This post is bigoted', - }), - reportAgainstTrollingPost.relateTo(p2, 'belongsTo'), + await reportAgainstDagobert.relateTo(louie, 'filed', { + resourceId: 'u7', + reasonCategory: 'discrimination_etc', + reasonDescription: 'this user is attacking me for who I am!', + }) + await reportAgainstDagobert.relateTo(dagobert, 'belongsTo') + await reportAgainstTrollingPost.relateTo(peterLustig, 'filed', { + resourceId: 'p2', + reasonCategory: 'discrimination_etc', + reasonDescription: 'This post is bigoted', + }) + await reportAgainstTrollingPost.relateTo(p2, 'belongsTo') - reportAgainstTrollingComment.relateTo(bobDerBaumeister, 'filed', { - resourceId: 'c1', - reasonCategory: 'pornographic_content_links', - reasonDescription: 'This comment is porno!!!', - }), - reportAgainstTrollingComment.relateTo(trollingComment, 'belongsTo'), - ]) + await reportAgainstTrollingComment.relateTo(bobDerBaumeister, 'filed', { + resourceId: 'c1', + reasonCategory: 'pornographic_content_links', + reasonDescription: 'This comment is porno!!!', + }) + await reportAgainstTrollingComment.relateTo(trollingComment, 'belongsTo') const disableVariables = { resourceId: 'undefined-resource', @@ -1168,46 +1150,46 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] } // review resource first time - await Promise.all([ - reportAgainstDagobert.relateTo(bobDerBaumeister, 'reviewed', { - ...disableVariables, - resourceId: 'u7', - }), - dagobert.update({ disabled: true, updatedAt: new Date().toISOString() }), - reportAgainstTrollingPost.relateTo(peterLustig, 'reviewed', { - ...disableVariables, - resourceId: 'p2', - }), - p2.update({ disabled: true, updatedAt: new Date().toISOString() }), - reportAgainstTrollingComment.relateTo(bobDerBaumeister, 'reviewed', { - ...disableVariables, - resourceId: 'c1', - }), - trollingComment.update({ disabled: true, updatedAt: new Date().toISOString() }), - ]) + await reportAgainstDagobert.relateTo(bobDerBaumeister, 'reviewed', { + ...disableVariables, + resourceId: 'u7', + }) + await dagobert.update({ disabled: true, updatedAt: new Date().toISOString() }) + await reportAgainstTrollingPost.relateTo(peterLustig, 'reviewed', { + ...disableVariables, + resourceId: 'p2', + }) + await p2.update({ disabled: true, updatedAt: new Date().toISOString() }) + await reportAgainstTrollingComment.relateTo(bobDerBaumeister, 'reviewed', { + ...disableVariables, + resourceId: 'c1', + }) + await trollingComment.update({ disabled: true, updatedAt: new Date().toISOString() }) // second review of resource and close report - await Promise.all([ - reportAgainstDagobert.relateTo(peterLustig, 'reviewed', { - resourceId: 'u7', - disable: false, - closed: true, - }), - dagobert.update({ disabled: false, updatedAt: new Date().toISOString(), closed: true }), - reportAgainstTrollingPost.relateTo(bobDerBaumeister, 'reviewed', { - resourceId: 'p2', - disable: true, - closed: true, - }), - p2.update({ disabled: true, updatedAt: new Date().toISOString(), closed: true }), - reportAgainstTrollingComment.relateTo(peterLustig, 'reviewed', { - ...disableVariables, - resourceId: 'c1', - disable: true, - closed: true, - }), - trollingComment.update({ disabled: true, updatedAt: new Date().toISOString(), closed: true }), - ]) + await reportAgainstDagobert.relateTo(peterLustig, 'reviewed', { + resourceId: 'u7', + disable: false, + closed: true, + }) + await dagobert.update({ disabled: false, updatedAt: new Date().toISOString(), closed: true }) + await reportAgainstTrollingPost.relateTo(bobDerBaumeister, 'reviewed', { + resourceId: 'p2', + disable: true, + closed: true, + }) + await p2.update({ disabled: true, updatedAt: new Date().toISOString(), closed: true }) + await reportAgainstTrollingComment.relateTo(peterLustig, 'reviewed', { + ...disableVariables, + resourceId: 'c1', + disable: true, + closed: true, + }) + await trollingComment.update({ + disabled: true, + updatedAt: new Date().toISOString(), + closed: true, + }) const additionalUsers = await Promise.all( [...Array(30).keys()].map(() => Factory.build('user')), diff --git a/backend/src/schema/types/type/Location.gql b/backend/src/schema/types/type/Location.gql index fad24cc26..9cb5c970a 100644 --- a/backend/src/schema/types/type/Location.gql +++ b/backend/src/schema/types/type/Location.gql @@ -25,4 +25,3 @@ type LocationMapBox { type Query { queryLocations(place: String!, lang: String!): [LocationMapBox]! } - diff --git a/backend/src/schema/types/type/Post.gql b/backend/src/schema/types/type/Post.gql index 0a7277515..7e6d1d0e7 100644 --- a/backend/src/schema/types/type/Post.gql +++ b/backend/src/schema/types/type/Post.gql @@ -84,8 +84,8 @@ input _PostFilter { group: _GroupFilter postsInMyGroups: Boolean postType_in: [PostType] - eventStart_gte: String - eventEnd_gte: String + eventStart_gte: String + eventEnd_gte: String } enum _PostOrdering { diff --git a/cypress/create-cucumber-html-report.js b/cypress/create-cucumber-html-report.js new file mode 100644 index 000000000..9720f4281 --- /dev/null +++ b/cypress/create-cucumber-html-report.js @@ -0,0 +1,12 @@ +const report = require("multiple-cucumber-html-reporter"); + +const reportTitle = "Ocelot webapp end-to-end test report" + +report.generate({ + jsonDir: "reports/json_logs", + reportPath: "./reports/cucumber_html_report", + pageTitle: reportTitle, + reportName: reportTitle, + pageFooter: "
", + hideMetadata: true +}); \ No newline at end of file diff --git a/cypress/cypress.config.js b/cypress/cypress.config.js index b169c0ce0..b1d80575e 100644 --- a/cypress/cypress.config.js +++ b/cypress/cypress.config.js @@ -21,13 +21,7 @@ async function setupNodeEvents(on, config) { return testStore[name] }, }); - - on("after:run", (results) => { - if (results) { - console.log(results.status); - } - }); - + return config; } diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 16fa6dc01..92e8bf1f7 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -13,7 +13,6 @@ // Cypress.Commands.add('login', (email, password) => { ... }) /* globals Cypress cy */ -import "cypress-file-upload"; import { GraphQLClient, request } from 'graphql-request' import CONFIG from '../../backend/build/src/config' diff --git a/cypress/support/step_definitions/Post.Images/I_should_be_able_to_{string}_a_teaser_image.js b/cypress/support/step_definitions/Post.Images/I_should_be_able_to_{string}_a_teaser_image.js index 019cc956a..478851f92 100644 --- a/cypress/support/step_definitions/Post.Images/I_should_be_able_to_{string}_a_teaser_image.js +++ b/cypress/support/step_definitions/Post.Images/I_should_be_able_to_{string}_a_teaser_image.js @@ -1,28 +1,27 @@ import { Then } from "@badeball/cypress-cucumber-preprocessor"; Then("I should be able to {string} a teaser image", condition => { - // cy.reload() + let postTeaserImage = "" + switch(condition){ - case 'change': - cy.get('.delete-image-button') + case "change": + postTeaserImage = "humanconnection.png" + cy.get(".delete-image-button") .click() - cy.fixture('humanconnection.png').as('postTeaserImage').then(function() { - cy.get("#postdropzone").upload( - { fileContent: this.postTeaserImage, fileName: 'humanconnection.png', mimeType: "image/png" }, - { subjectType: "drag-n-drop", force: true } - ).wait(750); - }) + cy.get("#postdropzone").selectFile( + { contents: `cypress/fixtures/${postTeaserImage}`, fileName: postTeaserImage, mimeType: "image/png" }, + { action: "drag-drop", force: true } + ).wait(750); break; - case 'add': - cy.fixture('onourjourney.png').as('postTeaserImage').then(function() { - cy.get("#postdropzone").upload( - { fileContent: this.postTeaserImage, fileName: 'onourjourney.png', mimeType: "image/png" }, - { subjectType: "drag-n-drop", force: true } - ).wait(750); - }) + case "add": + postTeaserImage = "onourjourney.png" + cy.get("#postdropzone").selectFile( + { contents: `cypress/fixtures/${postTeaserImage}`, fileName: postTeaserImage, mimeType: "image/png" }, + { action: "drag-drop", force: true } + ).wait(750); break; - case 'remove': - cy.get('.delete-image-button') + case "remove": + cy.get(".delete-image-button") .click() break; } diff --git a/cypress/support/step_definitions/UserProfile.Avatar/I_should_be_able_to_change_my_profile_picture.js b/cypress/support/step_definitions/UserProfile.Avatar/I_should_be_able_to_change_my_profile_picture.js index 27be5a99d..b1b2401e2 100644 --- a/cypress/support/step_definitions/UserProfile.Avatar/I_should_be_able_to_change_my_profile_picture.js +++ b/cypress/support/step_definitions/UserProfile.Avatar/I_should_be_able_to_change_my_profile_picture.js @@ -2,13 +2,11 @@ import { Then } from "@badeball/cypress-cucumber-preprocessor"; Then("I should be able to change my profile picture", () => { const avatarUpload = "onourjourney.png"; - - cy.fixture(avatarUpload, "base64").then(fileContent => { - cy.get("#customdropzone").upload( - { fileContent, fileName: avatarUpload, mimeType: "image/png" }, - { subjectType: "drag-n-drop", force: true } - ); - }); + + cy.get("#customdropzone").selectFile( + { contents: `cypress/fixtures/${avatarUpload}`, fileName: avatarUpload, mimeType: "image/png" }, + { action: "drag-drop" } + ); cy.get(".profile-page-avatar img") .should("have.attr", "src") .and("contains", "onourjourney"); diff --git a/deployment/configurations/stage.ocelot.social b/deployment/configurations/stage.ocelot.social index 350237c62..fdc2e52fa 160000 --- a/deployment/configurations/stage.ocelot.social +++ b/deployment/configurations/stage.ocelot.social @@ -1 +1 @@ -Subproject commit 350237c62dcff1a5c34f1e8d718f89b05ce3d33f +Subproject commit fdc2e52fa444b300e1c4736600bc0e9ae3314222 diff --git a/package.json b/package.json index 9f8399db7..afe65426a 100644 --- a/package.json +++ b/package.json @@ -10,13 +10,25 @@ "url": "https://github.com/Ocelot-Social-Community/Ocelot-Social.git" }, "cypress-cucumber-preprocessor": { - "nonGlobalStepDefinitions": true + "stepDefinitions": "cypress/support/step_definitions/**/*.js", + "json": { + "enabled": true, + "output": "cypress/reports/json_logs/cucumber_log.json", + "formatter": "cucumber-json-formatter" + }, + "messages": { + "enabled": true, + "output": "cypress/reports/json_logs/messages.ndjson" + }, + "html": { + "enabled": false + } }, "scripts": { "db:seed": "cd backend && yarn run db:seed", "db:reset": "cd backend && yarn run db:reset", - "cypress:run": "cypress run --browser electron --config-file ./cypress/cypress.config.js", - "cypress:open": "cypress open --browser electron --config-file ./cypress/cypress.config.js", + "cypress:run": "cypress run --e2e --browser electron --config-file ./cypress/cypress.config.js", + "cypress:open": "cypress open --e2e --browser electron --config-file ./cypress/cypress.config.js", "cucumber:setup": "cd backend && yarn run dev", "cucumber": "wait-on tcp:4000 && cucumber-js --require-module @babel/register --exit", "release": "yarn version --no-git-tag-version --no-commit-hooks --no-commit && auto-changelog --latest-version $(node -p -e \"require('./package.json').version\") && cd backend && yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version $(node -p -e \"require('./../package.json').version\") && cd ../webapp && yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version $(node -p -e \"require('./../package.json').version\") && cd ../webapp/maintenance/source && yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version $(node -p -e \"require('./../../../package.json').version\")" @@ -33,7 +45,6 @@ "cross-env": "^7.0.3", "cucumber": "^6.0.5", "cypress": "^12.17.0", - "cypress-file-upload": "^3.5.3", "cypress-network-idle": "^1.14.2", "date-fns": "^2.25.0", "dotenv": "^8.2.0", @@ -42,6 +53,7 @@ "import": "^0.0.6", "jsonwebtoken": "^8.5.1", "mock-socket": "^9.0.3", + "multiple-cucumber-html-reporter": "^3.4.0", "neo4j-driver": "^4.3.4", "neode": "^0.4.8", "rosie": "^2.1.0", diff --git a/webapp/assets/_new/icons/svgs/chat-bubble.svg b/webapp/assets/_new/icons/svgs/chat-bubble.svg new file mode 100644 index 000000000..377b52f2f --- /dev/null +++ b/webapp/assets/_new/icons/svgs/chat-bubble.svg @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/webapp/assets/_new/styles/export.scss b/webapp/assets/_new/styles/export.scss new file mode 100644 index 000000000..88b42bfc9 --- /dev/null +++ b/webapp/assets/_new/styles/export.scss @@ -0,0 +1,30 @@ + +:export { + colorPrimary: $color-primary; + colorPrimaryActive: $color-primary-active; + colorPrimaryLight: $color-primary-light; + + borderColorSoft: $border-color-soft; + + borderRadiusBase: $border-radius-base; + + textColorBase: $text-color-base; + textColorSoft: $text-color-soft; + textColorInverse: $text-color-inverse; + + boxShadowBase: $box-shadow-base; + + backgroundColorBase: $background-color-base; + backgroundColorSoft: $background-color-soft; + backgroundColorSoftest: $background-color-softest; + backgroundColorPrimary: $background-color-primary; + + colorNeutral30: $color-neutral-30; + + chatMessageColor: $chat-message-color; + + chatMessageBgMe: $chat-message-bg-me; + chatMessageBgOthers: $chat-message-bg-others; + + chatNewMessageColor: $chat-new-message-color; + } \ No newline at end of file diff --git a/webapp/assets/_new/styles/tokens.scss b/webapp/assets/_new/styles/tokens.scss index 22e0214ff..e001ffa84 100644 --- a/webapp/assets/_new/styles/tokens.scss +++ b/webapp/assets/_new/styles/tokens.scss @@ -406,4 +406,14 @@ $color-toast-green: $color-success; $color-ribbon-event: $background-color-third; $color-ribbon-event-active: $background-color-third-active; $color-ribbon-article: $background-color-secondary; -$color-ribbon-article-active: $background-color-secondary-active; \ No newline at end of file +$color-ribbon-article-active: $background-color-secondary-active; + +/** + * @tokens Chat Color + */ + +$chat-message-bg-me: $color-primary-light; +$chat-message-color: $text-color-base; +$chat-message-bg-others: $color-neutral-80; +$chat-sidemenu-bg: $color-secondary-active; +$chat-new-message-color: $color-secondary-active; diff --git a/webapp/components/Chat/Chat.vue b/webapp/components/Chat/Chat.vue index 2b9514bf3..cca6c4319 100644 --- a/webapp/components/Chat/Chat.vue +++ b/webapp/components/Chat/Chat.vue @@ -15,13 +15,42 @@ :rooms-loaded="true" show-files="false" show-audio="false" + :styles="JSON.stringify(computedChatStyle)" :show-footer="true" @send-message="sendMessage($event.detail[0])" @fetch-messages="fetchMessages($event.detail[0])" :responsive-breakpoint="responsiveBreakpoint" :single-room="singleRoom" @show-demo-options="showDemoOptions = $event" - /> + > +