mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2026-04-06 01:25:38 +00:00
fix(webapp): fix mobile invites, settings & global page paddings (#9478)
This commit is contained in:
parent
192104664d
commit
4c539406bc
@ -41,9 +41,6 @@ reviews:
|
|||||||
- "!**/*.min.css"
|
- "!**/*.min.css"
|
||||||
- "!**/.git/**"
|
- "!**/.git/**"
|
||||||
- "!**/storybook-static/**"
|
- "!**/storybook-static/**"
|
||||||
# TODO: Temporär - nach Merge des Cypress-Refactoring-PRs entfernen
|
|
||||||
- "!cypress/support/step_definitions/**"
|
|
||||||
- "!cypress/e2e/**/*.feature"
|
|
||||||
|
|
||||||
# Instruktionen für spezifische Pfade
|
# Instruktionen für spezifische Pfade
|
||||||
path_instructions:
|
path_instructions:
|
||||||
|
|||||||
9
.github/workflows/test-e2e.yml
vendored
9
.github/workflows/test-e2e.yml
vendored
@ -149,7 +149,7 @@ jobs:
|
|||||||
- name: List feature files
|
- name: List feature files
|
||||||
id: list
|
id: list
|
||||||
run: |
|
run: |
|
||||||
FEATURES=$(find cypress/e2e/ -maxdepth 1 -name "*.feature" -printf '%f\n' | sort | jq -R -s -c 'split("\n") | map(select(length > 0))')
|
FEATURES=$(cd cypress && find e2e/ -name "*.feature" -printf '%P\n' | sort | jq -R -s -c 'split("\n") | map(select(length > 0))')
|
||||||
echo "features=$FEATURES" >> $GITHUB_OUTPUT
|
echo "features=$FEATURES" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
fullstack_tests:
|
fullstack_tests:
|
||||||
@ -249,12 +249,17 @@ jobs:
|
|||||||
cd cypress/
|
cd cypress/
|
||||||
node create-cucumber-html-report.js
|
node create-cucumber-html-report.js
|
||||||
|
|
||||||
|
- name: Full stack tests | if tests failed, compute artifact name
|
||||||
|
id: artifact-name
|
||||||
|
if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }}
|
||||||
|
run: echo "name=e2e-report-$(echo '${{ matrix.feature }}' | tr '/' '-')" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Full stack tests | if tests failed, upload report
|
- name: Full stack tests | if tests failed, upload report
|
||||||
id: e2e-report
|
id: e2e-report
|
||||||
if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }}
|
if: ${{ failure() && steps.e2e-tests.conclusion == 'failure' }}
|
||||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||||
with:
|
with:
|
||||||
name: e2e-report-${{ matrix.feature }}
|
name: ${{ steps.artifact-name.outputs.name }}
|
||||||
path: /home/runner/work/Ocelot-Social/Ocelot-Social/cypress/reports/cucumber_html_report
|
path: /home/runner/work/Ocelot-Social/Ocelot-Social/cypress/reports/cucumber_html_report
|
||||||
|
|
||||||
e2e_status:
|
e2e_status:
|
||||||
|
|||||||
@ -830,15 +830,103 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
|
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
console.log('seed', 'invitecodes')
|
console.log('seed', 'invitecodes')
|
||||||
|
|
||||||
|
// Peter invited the core users: Jenny, Bob, Huey
|
||||||
await Factory.build(
|
await Factory.build(
|
||||||
'inviteCode',
|
'inviteCode',
|
||||||
{
|
{ code: 'PETER1', comment: 'For Jenny' },
|
||||||
code: 'ABCDEF',
|
{ generatedBy: peterLustig },
|
||||||
},
|
|
||||||
{
|
|
||||||
generatedBy: jennyRostock,
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
|
await Factory.build(
|
||||||
|
'inviteCode',
|
||||||
|
{ code: 'PETER2', comment: 'For Bob' },
|
||||||
|
{ generatedBy: peterLustig },
|
||||||
|
)
|
||||||
|
await Factory.build(
|
||||||
|
'inviteCode',
|
||||||
|
{ code: 'PETER3', comment: 'For Huey' },
|
||||||
|
{ generatedBy: peterLustig },
|
||||||
|
)
|
||||||
|
|
||||||
|
// Jenny invited Dewey, Louie, Dagobert
|
||||||
|
await Factory.build(
|
||||||
|
'inviteCode',
|
||||||
|
{ code: 'JENNY1', comment: 'For Dewey' },
|
||||||
|
{ generatedBy: jennyRostock },
|
||||||
|
)
|
||||||
|
await Factory.build(
|
||||||
|
'inviteCode',
|
||||||
|
{ code: 'JENNY2', comment: 'For Louie' },
|
||||||
|
{ generatedBy: jennyRostock },
|
||||||
|
)
|
||||||
|
await Factory.build(
|
||||||
|
'inviteCode',
|
||||||
|
{ code: 'JENNY3', comment: 'For Dagobert' },
|
||||||
|
{ generatedBy: jennyRostock },
|
||||||
|
)
|
||||||
|
// Jenny's shared code (used by additional users)
|
||||||
|
await Factory.build(
|
||||||
|
'inviteCode',
|
||||||
|
{ code: 'ABCDEF', comment: 'Share link' },
|
||||||
|
{ generatedBy: jennyRostock },
|
||||||
|
)
|
||||||
|
// Jenny's unused code (still active)
|
||||||
|
await Factory.build('inviteCode', { code: 'JNEW01' }, { generatedBy: jennyRostock })
|
||||||
|
// Jenny's invalidated code (was used once, then deactivated)
|
||||||
|
await Factory.build(
|
||||||
|
'inviteCode',
|
||||||
|
{ code: 'JENNY0', comment: 'Old link', expiresAt: new Date().toISOString() },
|
||||||
|
{ generatedBy: jennyRostock },
|
||||||
|
)
|
||||||
|
// Jenny total: JENNY1, JENNY2, JENNY3, ABCDEF, JNEW01 (5 active) + JENNY0 (1 expired) = 6 codes
|
||||||
|
|
||||||
|
// Create REDEEMED and INVITED relationships via Cypher
|
||||||
|
const inviteSession = database.driver.session()
|
||||||
|
try {
|
||||||
|
await inviteSession.writeTransaction((txc) =>
|
||||||
|
txc.run(`
|
||||||
|
// Peter's invitations
|
||||||
|
MATCH (jenny:User {id: 'u3'}), (code1:InviteCode {code: 'PETER1'}), (peter:User {id: 'u1'})
|
||||||
|
MERGE (jenny)-[:REDEEMED {createdAt: toString(datetime())}]->(code1)
|
||||||
|
MERGE (peter)-[:INVITED {createdAt: toString(datetime())}]->(jenny)
|
||||||
|
MERGE (jenny)-[:FOLLOWS {createdAt: toString(datetime())}]->(peter)
|
||||||
|
MERGE (peter)-[:FOLLOWS {createdAt: toString(datetime())}]->(jenny)
|
||||||
|
WITH 1 AS dummy
|
||||||
|
MATCH (bob:User {id: 'u2'}), (code2:InviteCode {code: 'PETER2'}), (peter:User {id: 'u1'})
|
||||||
|
MERGE (bob)-[:REDEEMED {createdAt: toString(datetime())}]->(code2)
|
||||||
|
MERGE (peter)-[:INVITED {createdAt: toString(datetime())}]->(bob)
|
||||||
|
MERGE (bob)-[:FOLLOWS {createdAt: toString(datetime())}]->(peter)
|
||||||
|
MERGE (peter)-[:FOLLOWS {createdAt: toString(datetime())}]->(bob)
|
||||||
|
WITH 1 AS dummy
|
||||||
|
MATCH (huey:User {id: 'u4'}), (code3:InviteCode {code: 'PETER3'}), (peter:User {id: 'u1'})
|
||||||
|
MERGE (huey)-[:REDEEMED {createdAt: toString(datetime())}]->(code3)
|
||||||
|
MERGE (peter)-[:INVITED {createdAt: toString(datetime())}]->(huey)
|
||||||
|
MERGE (huey)-[:FOLLOWS {createdAt: toString(datetime())}]->(peter)
|
||||||
|
MERGE (peter)-[:FOLLOWS {createdAt: toString(datetime())}]->(huey)
|
||||||
|
WITH 1 AS dummy
|
||||||
|
// Jenny's invitations
|
||||||
|
MATCH (dewey:User {id: 'u5'}), (code4:InviteCode {code: 'JENNY1'}), (jenny:User {id: 'u3'})
|
||||||
|
MERGE (dewey)-[:REDEEMED {createdAt: toString(datetime())}]->(code4)
|
||||||
|
MERGE (jenny)-[:INVITED {createdAt: toString(datetime())}]->(dewey)
|
||||||
|
MERGE (dewey)-[:FOLLOWS {createdAt: toString(datetime())}]->(jenny)
|
||||||
|
MERGE (jenny)-[:FOLLOWS {createdAt: toString(datetime())}]->(dewey)
|
||||||
|
WITH 1 AS dummy
|
||||||
|
MATCH (louie:User {id: 'u6'}), (code5:InviteCode {code: 'JENNY2'}), (jenny:User {id: 'u3'})
|
||||||
|
MERGE (louie)-[:REDEEMED {createdAt: toString(datetime())}]->(code5)
|
||||||
|
MERGE (jenny)-[:INVITED {createdAt: toString(datetime())}]->(louie)
|
||||||
|
MERGE (louie)-[:FOLLOWS {createdAt: toString(datetime())}]->(jenny)
|
||||||
|
MERGE (jenny)-[:FOLLOWS {createdAt: toString(datetime())}]->(louie)
|
||||||
|
WITH 1 AS dummy
|
||||||
|
MATCH (dagobert:User {id: 'u7'}), (code6:InviteCode {code: 'JENNY3'}), (jenny:User {id: 'u3'})
|
||||||
|
MERGE (dagobert)-[:REDEEMED {createdAt: toString(datetime())}]->(code6)
|
||||||
|
MERGE (jenny)-[:INVITED {createdAt: toString(datetime())}]->(dagobert)
|
||||||
|
MERGE (dagobert)-[:FOLLOWS {createdAt: toString(datetime())}]->(jenny)
|
||||||
|
MERGE (jenny)-[:FOLLOWS {createdAt: toString(datetime())}]->(dagobert)
|
||||||
|
`),
|
||||||
|
)
|
||||||
|
} finally {
|
||||||
|
await inviteSession.close()
|
||||||
|
}
|
||||||
|
|
||||||
authenticatedUser = await louie.toJson()
|
authenticatedUser = await louie.toJson()
|
||||||
const mention1 =
|
const mention1 =
|
||||||
@ -1234,6 +1322,32 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Jenny's first 99 additional users all redeemed code ABCDEF
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.log('seed', 'invite redemptions for additional users')
|
||||||
|
const jennyInviteSession = database.driver.session()
|
||||||
|
try {
|
||||||
|
for (let i = 0; i < Math.min(99, additionalUsers.length); i++) {
|
||||||
|
// eslint-disable-next-line security/detect-object-injection
|
||||||
|
const userObj = await additionalUsers[i].toJson()
|
||||||
|
const userId = userObj.id as string
|
||||||
|
await jennyInviteSession.writeTransaction((txc) =>
|
||||||
|
txc.run(
|
||||||
|
`
|
||||||
|
MATCH (user:User {id: $userId}), (inviteCode:InviteCode {code: 'ABCDEF'}), (jenny:User {id: 'u3'})
|
||||||
|
MERGE (user)-[:REDEEMED {createdAt: toString(datetime())}]->(inviteCode)
|
||||||
|
MERGE (jenny)-[:INVITED {createdAt: toString(datetime())}]->(user)
|
||||||
|
MERGE (user)-[:FOLLOWS {createdAt: toString(datetime())}]->(jenny)
|
||||||
|
MERGE (jenny)-[:FOLLOWS {createdAt: toString(datetime())}]->(user)
|
||||||
|
`,
|
||||||
|
{ userId },
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
await jennyInviteSession.close()
|
||||||
|
}
|
||||||
|
|
||||||
// Jenny users
|
// Jenny users
|
||||||
for (let i = 0; i < 30; i++) {
|
for (let i = 0; i < 30; i++) {
|
||||||
await Factory.build('user', { name: `Jenny${i}` })
|
await Factory.build('user', { name: `Jenny${i}` })
|
||||||
|
|||||||
39
cypress/e2e/settings/InviteCode.feature
Normal file
39
cypress/e2e/settings/InviteCode.feature
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
Feature: Invite Codes
|
||||||
|
As a User
|
||||||
|
I'd like to manage my invite codes
|
||||||
|
So I can invite friends to the network
|
||||||
|
|
||||||
|
Background:
|
||||||
|
Given the following "users" are in the database:
|
||||||
|
| email | password | id | name | slug | termsAndConditionsAgreedVersion |
|
||||||
|
| peterpan@example.org | 123 | id-of-peter-pan | Peter Pan | peter-pan | 0.0.4 |
|
||||||
|
And I am logged in as "peter-pan"
|
||||||
|
|
||||||
|
Scenario: View invite codes page
|
||||||
|
When I navigate to page "/settings/invites"
|
||||||
|
Then I am on page "/settings/invites"
|
||||||
|
And I see the invite code list title with count
|
||||||
|
|
||||||
|
Scenario: Generate a new invite code
|
||||||
|
When I navigate to page "/settings/invites"
|
||||||
|
Then I am on page "/settings/invites"
|
||||||
|
When I generate a new invite code
|
||||||
|
Then I see a toaster with status "success"
|
||||||
|
And the invite code count has increased
|
||||||
|
|
||||||
|
Scenario: Generate a new invite code with comment
|
||||||
|
When I navigate to page "/settings/invites"
|
||||||
|
Then I am on page "/settings/invites"
|
||||||
|
When I generate a new invite code with comment "For my friend"
|
||||||
|
Then I see a toaster with status "success"
|
||||||
|
And I see the comment "For my friend" on an invite code
|
||||||
|
|
||||||
|
Scenario: Invalidate an invite code
|
||||||
|
When I navigate to page "/settings/invites"
|
||||||
|
Then I am on page "/settings/invites"
|
||||||
|
When I generate a new invite code
|
||||||
|
Then I see a toaster with status "success"
|
||||||
|
When I invalidate the first invite code
|
||||||
|
And I confirm the action in the modal
|
||||||
|
Then I see a toaster with status "success"
|
||||||
|
And the invite code count has decreased
|
||||||
@ -8,10 +8,10 @@ CUR_JOB=$(expr $1 - 1)
|
|||||||
MAX_JOBS=$2
|
MAX_JOBS=$2
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
FEATURE_LIST=( $(find cypress/e2e/ -maxdepth 1 -name "*.feature") )
|
FEATURE_LIST=( $(find cypress/e2e/ -name "*.feature") )
|
||||||
|
|
||||||
# Calculation
|
# Calculation
|
||||||
MAX_FEATURES=$(find cypress/e2e/ -maxdepth 1 -name "*.feature" -print | wc -l)
|
MAX_FEATURES=$(find cypress/e2e/ -name "*.feature" -print | wc -l)
|
||||||
# adds overhead features to the first jobs
|
# adds overhead features to the first jobs
|
||||||
if [[ $CUR_JOB -lt $(expr ${MAX_FEATURES} % ${MAX_JOBS}) ]]
|
if [[ $CUR_JOB -lt $(expr ${MAX_FEATURES} % ${MAX_JOBS}) ]]
|
||||||
then
|
then
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
|
import { defineStep } from '@badeball/cypress-cucumber-preprocessor'
|
||||||
import './../../commands'
|
import './../../../commands'
|
||||||
import './../../factories'
|
import './../../../factories'
|
||||||
import 'cypress-network-idle'
|
import 'cypress-network-idle'
|
||||||
|
|
||||||
defineStep('somebody reported the following posts:', table => {
|
defineStep('somebody reported the following posts:', table => {
|
||||||
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