diff --git a/apps/protocol-frontend-e2e/src/integration/03_createContribution.cy.ts b/apps/protocol-frontend-e2e/src/integration/03_createContribution.cy.ts deleted file mode 100644 index f4236566f..000000000 --- a/apps/protocol-frontend-e2e/src/integration/03_createContribution.cy.ts +++ /dev/null @@ -1,125 +0,0 @@ -/// - -before(() => { - const getChaintTypeID = `SELECT id - FROM "ChainType" - WHERE name = 'Goerli-Test'`; - const chainTypeName = 'Goerli-Test'; - - //seed ChainType table - cy.task('create_chainType', chainTypeName); - - //seed User table - cy.fixture('users.json').then(users => { - const userData = users[0]; - cy.task('queryDatabase', getChaintTypeID).then(res => { - const chainTypeID = res.rows[0].id; - userData['chain_type_id'] = chainTypeID; - cy.task('create_user', userData); - }); - }); - - //seed Guild table - cy.fixture('daos.json').then(guilds => { - for (const guild of guilds) { - cy.task('create_guild', guild.name); - } - }); - - cy.fixture('contributions.json').then(contributions => { - this.contributions = contributions; - }); - - cy.fixture('testaccounts.json').then(accounts => { - this.accounts = accounts; - cy.login(this.accounts[0].address, this.accounts[0].privateKey); - }); - - cy.get('[data-cy="myDashboards-btn"]', { timeout: 15000 }) - .scrollIntoView() - .should('be.visible') - .click(); - - cy.get('[data-cy="contributionsSidebar-btn"]', { timeout: 15000 }) - .should('be.visible') - .click(); - - cy.get('[data-cy="reportFirstContribution-btn"]', { - timeout: 10000, - }) - .should('be.visible') - .click({ force: true }); - // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(5000); -}); -after(() => { - const getUserID = `SELECT id - FROM "User" - WHERE name = 'testusernamegovrne2etesting2022'`; - const chainTypeName = 'Goerli-Test'; - - //teardown UserActivity table - cy.task('queryDatabase', getUserID).then(res => { - const userID = res.rows[0].id; - cy.task('delete_UserActivity', userID); - }); - - //teardown Guild table - cy.fixture('daos.json').then(guilds => { - for (const guild of guilds) { - const guild_name = guild.name; - cy.task('delete_guild', guild_name); - } - }); - - //teardown Contribution table - cy.fixture('contributions.json').then(contributions => { - const name = contributions[0].name; - cy.task('delete_contribution', name); - }); - - //teardown User table - cy.fixture('users.json').then(users => { - const username = users[0].username; - cy.task('delete_user', username); - }); - - //teardown ChainType table - cy.task('delete_chainType', chainTypeName); -}); - -describe('Create First Contribution', () => { - it('Report your first contribution', () => { - const contribution = this.contributions[0]; - - cy.get('input[data-testid="reportForm-name"]', { timeout: 20000 }) - .should('be.visible') - .type(contribution.name) - .should('have.value', contribution.name); - - cy.get('[data-cy="daoCreatableSelect-testing"]') - .should('be.visible') - .children() - .find('input') - .type(`${contribution.activityType}{enter}`); - - cy.get('textarea[data-testid="textarea-test"]') - .click() - .type(contribution.details); - - cy.get('input[data-testid="reportForm-proof"]').type(contribution.proof); - - cy.get('[data-cy="daoSelect-testing"]') - .should('be.visible') - .children() - .find('input') - .type(`${contribution.dao}{enter}`); - - cy.get('[data-cy="addContribution-btn"]').click(); - - cy.contains( - 'Please select at least one contribution to attribute to a DAO or mint.', - { timeout: 20000 }, - ); - }); -}); diff --git a/apps/protocol-frontend-e2e/src/integration/04_updateContribution.cy.ts b/apps/protocol-frontend-e2e/src/integration/04_updateContribution.cy.ts deleted file mode 100644 index 7fc6816e1..000000000 --- a/apps/protocol-frontend-e2e/src/integration/04_updateContribution.cy.ts +++ /dev/null @@ -1,152 +0,0 @@ -/// - -beforeEach(() => { - const chainTypeName = 'Goerli-Test'; - const getChaintTypeID = `SELECT id - FROM "ChainType" - WHERE name = 'Goerli-Test'`; - const getUserID = `SELECT id - FROM "User" - WHERE name = 'testusernamegovrne2etesting2022'`; - const getActivityTypeID = `SELECT id - FROM "ActivityType" - WHERE name = 'Pull Request'`; - - //seed ChainType table - cy.task('create_chainType', chainTypeName); - - //seed ContributionStatus table (not sure if this is necessary?) - cy.task('contribution_status'); - - //seed User table - cy.fixture('users.json').then(users => { - const userData = users[0]; - cy.task('queryDatabase', getChaintTypeID).then(res => { - const chainTypeID = res.rows[0].id; - userData['chain_type_id'] = chainTypeID; - cy.task('create_user', userData); - }); - }); - - //seed Guild table - cy.fixture('daos.json').then(guilds => { - for (const guild of guilds) { - const guild_name = guild.name; - cy.task('create_guild', guild_name); - } - }); - - //seed Contribution table - cy.fixture('contributions.json').then(contributions => { - const contributionData = contributions[0]; - cy.task('queryDatabase', getUserID).then(res => { - const userID = res.rows[0].id; - contributionData['userID'] = userID; - }); - cy.task('queryDatabase', getActivityTypeID).then(res => { - const ActivityTypeID = res.rows[0].id; - contributionData['activityTypeID'] = ActivityTypeID; - }); - cy.task('create_contribution', contributionData); - }); - - //Login User - cy.fixture('testaccounts.json').then(accounts => { - this.accounts = accounts; - cy.login(this.accounts[0].address, this.accounts[0].privateKey); - }); - - cy.fixture('contributions.json').then(contributions => { - this.contributions = contributions; - }); - - cy.get('[data-cy="myDashboards-btn"]', { timeout: 60000 }) - .should('be.enabled') - .click(); - - cy.get('[data-cy="contributionsSidebar-btn"]', { timeout: 100000 }) - .should('be.visible') - .click(); - - cy.get('.infinite-scroll-component').scrollTo('500px'); - - cy.get('[data-testid="editContribution-test"]', { timeout: 60000 }) - .should('be.visible') - .click({ force: true }); - // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(5000); -}); -after(() => { - const chainTypeName = 'Goerli-Test'; - const getUserID = `SELECT id - FROM "User" - WHERE name = 'testusernamegovrne2etesting2022'`; - - //teardown UserActivity table - cy.task('queryDatabase', getUserID).then(res => { - const userID = res.rows[0].id; - cy.task('delete_UserActivity', userID); - }); - - //teardown Guild table - cy.fixture('daos.json').then(guilds => { - for (const guild of guilds) { - const guild_name = guild.name; - cy.task('delete_guild', guild_name); - } - }); - - //teardown Contribution table - cy.fixture('contributions.json').then(contributions => { - const name = contributions[1].name; - cy.task('delete_contribution', name); - }); - - //teardown User table - cy.fixture('users.json').then(users => { - const username = users[0].username; - cy.task('delete_user', username); - }); - cy.task('delete_chainType', chainTypeName); -}); - -describe('Edit first Contribution', () => { - it('Update/Edit Contribution', () => { - const contribution = this.contributions[1]; - - cy.get('input[data-testid="editContributionForm-name"]') - .clear() - .type(contribution.name) - .should('have.value', contribution.name); - - cy.get('[data-cy="daoCreatableSelect-testing"]') - .should('be.visible') - .children() - .find('input') - .type(`${contribution.activityType}{enter}`); - - cy.get('textarea[data-testid="textarea-test"]') - .clear() - .click() - .type(contribution.details); - - cy.get('input[data-testid="editContributionForm-proof"]') - .clear() - .type(contribution.proof); - - cy.get('[data-cy="daoSelect-testing"]') - .should('be.visible') - .children() - .find('input') - .type(`${contribution.dao}{enter}`); - - cy.get('[ data-cy="updateContribution-test-btn"]', { timeout: 30000 }) - .should('exist') - .should('be.visible') - .click(); - - cy.contains( - 'Please select at least one contribution to attribute to a DAO or mint.', - ); - }); -}); diff --git a/apps/protocol-frontend-e2e/src/integration/05_attestation.cy.ts b/apps/protocol-frontend-e2e/src/integration/05_attestation.cy.ts deleted file mode 100644 index b77baad79..000000000 --- a/apps/protocol-frontend-e2e/src/integration/05_attestation.cy.ts +++ /dev/null @@ -1,218 +0,0 @@ -/// - -beforeEach(() => { - const getChainTypeID = `SELECT id - FROM "ChainType" - WHERE name = 'Goerli-Test'`; - const getUser1ID = `SELECT id - FROM "User" - WHERE name = 'testusernamegovrne2etesting2022'`; - const getUser2ID = `SELECT id - FROM "User" - WHERE name = 'johnDoeGovrnE2eTesting2022'`; - const getGuildID = `SELECT id - FROM "Guild" - WHERE name = 'GovrnE2eTesting2022'`; - const getMembershipStatusId = `SELECT id - FROM "GuildMembershipStatus" - WHERE name = 'Supporter'`; - const getActivityTypeID = `SELECT id - FROM "ActivityType" - WHERE name = 'Pull Request'`; - const getContributionID = `SELECT id - FROM "Contribution" - WHERE name = 'e2eTesting2022-Govrn Protocol Note Taking'`; - const getstatusID = `SELECT id - FROM "ContributionStatus" - WHERE name = 'minted'`; - const urlToContributionsPage = 'http://localhost:3000/#/contributions'; - const chainTypeName = 'Goerli-Test'; - const GuildUser1Object = {}; - const GuildUser2Object = {}; - const GuildContribution2Object = {}; - - // Guilds - cy.fixture('daos.json').then(guilds => { - for (const guild of guilds) { - const guild_name = guild.name; - cy.task('create_guild', guild_name); - } - }); - - cy.task('create_MembershipStatus'); - - // seed ChainType - cy.task('create_chainType', chainTypeName); - - // seed ContributionStatus - cy.task('contribution_status'); - - // User1 - cy.fixture('users.json').then(users => { - const userData = users[0]; - cy.task('queryDatabase', getChainTypeID).then(res => { - const chainTypeID = res.rows[0].id; - userData['chain_type_id'] = chainTypeID; - cy.task('create_user', userData); - }); - }); - - // User2 - cy.fixture('users.json').then(users => { - const userData = users[1]; - cy.task('queryDatabase', getChainTypeID).then(res => { - const chainTypeID = res.rows[0].id; - userData['chain_type_id'] = chainTypeID; - cy.task('create_user', userData); - }); - }); - - // GuildUser1 - cy.task('queryDatabase', getUser1ID).then(res => { - const userID = res.rows[0].id; - GuildUser1Object['userID'] = userID; - }); - cy.task('queryDatabase', getGuildID).then(res => { - const guildID = res.rows[0].id; - cy.task('queryDatabase', getMembershipStatusId).then(res => { - const membershipID = res.rows[0].id; - GuildUser1Object['guildID'] = guildID; - GuildUser1Object['membershipID'] = membershipID; - cy.task('create_GuildUser', GuildUser1Object); - }); - }); - - //GuildUser2 - cy.task('queryDatabase', getUser2ID).then(res => { - const userID = res.rows[0].id; - GuildUser2Object['userID'] = userID; - }); - cy.task('queryDatabase', getGuildID).then(res => { - const guildID = res.rows[0].id; - cy.task('queryDatabase', getMembershipStatusId).then(res => { - const membershipID = res.rows[0].id; - GuildUser2Object['guildID'] = guildID; - GuildUser2Object['membershipID'] = membershipID; - cy.task('create_GuildUser', GuildUser2Object); - }); - }); - - // User-02 creates minted contribution - cy.fixture('contributions.json').then(contributions => { - const contributionData = contributions[1]; - cy.task('queryDatabase', getUser2ID).then(res => { - const userID = res.rows[0].id; - contributionData['userID'] = userID; - }); - cy.task('queryDatabase', getActivityTypeID).then(res => { - const ActivityTypeID = res.rows[0].id; - contributionData['activityTypeID'] = ActivityTypeID; - }); - cy.task('queryDatabase', getstatusID).then(res => { - const statusID = res.rows[0].id; - contributionData['statusID'] = statusID; - }); - cy.task('queryDatabase', getChainTypeID).then(res => { - const onChainId = res.rows[0].id; - contributionData['onChainId'] = onChainId; - }); - - cy.task('create_MintedContribution', contributionData); - }); - - // GuildContribution User-02 - cy.task('queryDatabase', getContributionID).then(res => { - const contributionID = res.rows[0].id; - GuildContribution2Object['contributionID'] = contributionID; - }); - cy.task('queryDatabase', getGuildID).then(res => { - const guildID = res.rows[0].id; - GuildContribution2Object['guildID'] = guildID; - cy.task('create_GuildContribution', GuildContribution2Object); - }); - - // Login as User-01 - cy.fixture('testaccounts.json').then(accounts => { - this.accounts = accounts; - cy.login(this.accounts[0].address, this.accounts[0].privateKey); - }); - - cy.get('[data-cy="myDashboards-btn"]', { timeout: 15000 }) - .should('be.visible') - .click({ force: true }); - - cy.visit(urlToContributionsPage); - - cy.contains('Attestations').click({ force: true }); - - // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(5000); -}); - -afterEach(() => { - const getUser1ID = `SELECT id - FROM "User" - WHERE name = 'testusernamegovrne2etesting2022'`; - const getGuildID = `SELECT id - FROM "Guild" - WHERE name = 'GovrnE2eTesting2022'`; - const users = [ - 'johnDoeGovrnE2eTesting2022', - 'testusernamegovrne2etesting2022', - ]; - const guilds = ['GovrnE2eTesting2022', 'MGDEe2eTesting2022']; - const target_contributionName = 'e2eTesting2022-Govrn Protocol Note Taking'; - - // teardown Attestation - cy.task('queryDatabase', getUser1ID).then(res => { - const userID = res.rows[0].id; - cy.task('delete_attestation', userID); - }); - - // teardown GuildUser and GuildContribution - cy.task('queryDatabase', getGuildID).then(res => { - const guildID = res.rows[0].id; - cy.task('delete_GuildContribution', guildID); - cy.task('delete_GuildUser', guildID); - cy.task('delete_MembershipStatus'); - }); - - // teardown Contribution - cy.task('delete_contribution', target_contributionName); - - // teardown Guild - for (const guild of guilds) { - cy.task('delete_guild', guild); - } - - // teardown User - for (const user of users) { - cy.task('delete_user', user); - } -}); - -describe('Attestation flow', () => { - it('attest to a minted Contribution', () => { - cy.get('[testid="toggle-row-selected"]').click({ multiple: true }); - - cy.get('[data-testId="attest-testId"]').click(); - - cy.contains('Attest to DAO Contributions').should('be.visible'); - - cy.get('[data-testId="addAttestations-btn"]').click(); - - cy.get(`.chakra-modal__close-btn`, { timeout: 10000 }).click({ - force: true, - }); - - // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(5000); //wait for the attestation loading-process - cy.contains('My Attestations', { timeout: 10000 }) - .should('be.visible') - .click({ force: true }); - - cy.contains(`These are contributions that you have already attested to.`, { - timeout: 10000, - }).should('be.visible'); - }); -}); diff --git a/apps/protocol-frontend-e2e/src/integration/06_create2ndContribution.cy.ts b/apps/protocol-frontend-e2e/src/integration/06_create2ndContribution.cy.ts deleted file mode 100644 index 4b59e3f92..000000000 --- a/apps/protocol-frontend-e2e/src/integration/06_create2ndContribution.cy.ts +++ /dev/null @@ -1,158 +0,0 @@ -/// - -before(() => { - const getChainTypeID = `SELECT id - FROM "ChainType" - WHERE name = 'Goerli-Test'`; - const getUser1ID = `SELECT id - FROM "User" - WHERE name = 'testusernamegovrne2etesting2022'`; - const getActivityTypeID = `SELECT id - FROM "ActivityType" - WHERE name = 'Pull Request'`; - const getStagingStatusID = `SELECT id - FROM "ContributionStatus" - WHERE name = 'staging'`; - const chainTypeName = 'Goerli-Test'; - - //seed Guild - cy.fixture('daos.json').then(guilds => { - for (const guild of guilds) { - cy.task('create_guild', guild.name); - } - }); - - // seed ChainType - cy.task('create_chainType', chainTypeName); - - //seed User table - cy.fixture('users.json').then(users => { - const userData = users[0]; - cy.task('queryDatabase', getChainTypeID).then(res => { - const chainTypeID = res.rows[0].id; - userData['chain_type_id'] = chainTypeID; - cy.task('create_user', userData); - }); - }); - - //seed ContributionStatus - cy.task('contribution_status'); - - //seed Contribution - cy.fixture('contributions.json').then(contributions => { - const contributionData = contributions[1]; - cy.task('queryDatabase', getUser1ID).then(res => { - const userID = res.rows[0].id; - contributionData['userID'] = userID; - }); - cy.task('queryDatabase', getActivityTypeID).then(res => { - const ActivityTypeID = res.rows[0].id; - contributionData['activityTypeID'] = ActivityTypeID; - }); - cy.task('queryDatabase', getStagingStatusID).then(res => { - const statusID = res.rows[0].id; - contributionData['statusID'] = statusID; - }); - cy.task('create_contribution', contributionData); - }); - - cy.fixture('users.json').then(users => { - this.users = users; - }); - - cy.fixture('testaccounts.json').then(accounts => { - this.accounts = accounts; - cy.login(this.accounts[0].address, this.accounts[0].privateKey); - }); - - cy.get('[data-cy="myDashboards-btn"]', { timeout: 15000 }) - .should('be.visible') - .click(); - - cy.get('[data-testid="floatingreportbtn-testid"]', { - timeout: 10000, - }) - .should('be.visible') - .click(); - - cy.fixture('contributions.json').then(contributions => { - this.contributions = contributions; - }); - // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(5000); -}); -afterEach(() => { - const contributionNames = [ - 'e2eTesting2022-Test Automation', - 'e2eTesting2022-Govrn Protocol Note Taking', - ]; - const getUserID = `SELECT id - FROM "User" - WHERE name = 'testusernamegovrne2etesting2022'`; - const chainTypeName = 'Goerli-Test'; - - //teardown UserActivity table - cy.task('queryDatabase', getUserID).then(res => { - const userID = res.rows[0].id; - cy.task('delete_UserActivity', userID); - }); - - //teardown Guild table - cy.fixture('daos.json').then(guilds => { - for (const guild of guilds) { - const guild_name = guild.name; - cy.task('delete_guild', guild_name); - } - }); - - //teardown Contribution table - for (const contributionName of contributionNames) { - cy.task('delete_contribution', contributionName); - } - - //teardown User table - cy.fixture('users.json').then(users => { - const username = users[0].username; - cy.task('delete_user', username); - }); - - //teardown ChainType table - cy.task('delete_chainType', chainTypeName); -}); - -describe('Create Second Contribution', () => { - it('Report your Second Contribution', () => { - const contribution = this.contributions[2]; - - cy.get('input[data-testid="reportForm-name"]', { timeout: 20000 }) - .should('be.visible') - .type(contribution.name) - .should('have.value', contribution.name); - - cy.get('[data-cy="daoCreatableSelect-testing"]') - .should('be.visible') - .children() - .find('input') - .type(`${contribution.activityType}{enter}`); - - cy.get('textarea[data-testid="textarea-test"]') - .click() - .type(contribution.details); - - cy.get('input[data-testid="reportForm-proof"]').type(contribution.proof); - - cy.get('[data-cy="daoSelect-testing"]') - .should('be.visible') - .children() - .find('input') - .type(`${contribution.dao}{enter}`); - - cy.get('[data-cy="addContribution-btn"]').click(); - // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(3000); - cy.contains( - 'Please select at least one contribution to attribute to a DAO or mint.', - { timeout: 20000 }, - ); - }); -}); diff --git a/apps/protocol-frontend-e2e/src/integration/07_deleteContribution.cy.ts b/apps/protocol-frontend-e2e/src/integration/07_deleteContribution.cy.ts deleted file mode 100644 index 9ca719259..000000000 --- a/apps/protocol-frontend-e2e/src/integration/07_deleteContribution.cy.ts +++ /dev/null @@ -1,133 +0,0 @@ -/// - -beforeEach(() => { - const chainTypeName = 'Goerli-Test'; - const getChaintTypeID = `SELECT id - FROM "ChainType" - WHERE name = 'Goerli-Test'`; - const getUserID = `SELECT id - FROM "User" - WHERE name = 'testusernamegovrne2etesting2022'`; - const getActivityTypeID = `SELECT id - FROM "ActivityType" - WHERE name = 'Pull Request'`; - const getContributionID = `SELECT id - FROM "Contribution" - WHERE name = 'e2eTesting2022-Govrn Protocol Pull Request'`; - - //seed ChainType table - cy.task('create_chainType', chainTypeName); - - //seed ContributionStatus table (not sure if this is necessary?) - cy.task('contribution_status'); - - //seed User table - cy.fixture('users.json').then(users => { - const userData = users[0]; - cy.task('queryDatabase', getChaintTypeID).then(res => { - const chainTypeID = res.rows[0].id; - userData['chain_type_id'] = chainTypeID; - cy.task('create_user', userData); - }); - }); - - //seed Guild table - cy.fixture('daos.json').then(guilds => { - for (const guild of guilds) { - const guild_name = guild.name; - cy.task('create_guild', guild_name); - } - }); - - //seed Contribution table - cy.fixture('contributions.json').then(contributions => { - const contributionData = contributions[0]; - cy.task('queryDatabase', getUserID).then(res => { - const userID = res.rows[0].id; - contributionData['userID'] = userID; - }); - cy.task('queryDatabase', getActivityTypeID).then(res => { - const ActivityTypeID = res.rows[0].id; - contributionData['activityTypeID'] = ActivityTypeID; - }); - cy.task('create_contribution', contributionData); - }); - - //Login User - cy.fixture('testaccounts.json').then(accounts => { - this.accounts = accounts; - cy.login(this.accounts[0].address, this.accounts[0].privateKey); - }); - - cy.get('[data-cy="myDashboards-btn"]', { timeout: 60000 }) - .should('be.enabled') - .click(); - - cy.get('[data-cy="contributionsSidebar-btn"]', { timeout: 100000 }) - .should('be.visible') - .click(); - - cy.get('.infinite-scroll-component').scrollTo('500px'); - - // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(5000); -}); -after(() => { - const chainTypeName = 'Goerli-Test'; - const getUserID = `SELECT id - FROM "User" - WHERE name = 'testusernamegovrne2etesting2022'`; - const getContributionID = `SELECT id - FROM "Contribution" - WHERE name = 'e2eTesting2022-Govrn Protocol Pull Request'`; - - //teardown UserActivity table - cy.task('queryDatabase', getUserID).then(res => { - const userID = res.rows[0].id; - cy.task('delete_UserActivity', userID); - }); - - //teardown Guild table - cy.fixture('daos.json').then(guilds => { - for (const guild of guilds) { - const guild_name = guild.name; - cy.task('delete_guild', guild_name); - } - }); - - //teardown Contribution table - cy.fixture('contributions.json').then(contributions => { - const name = contributions[0].name; - cy.task('delete_contribution', name); - }); - - //confirm contribution is deleted in db - cy.task('queryDatabase', getContributionID).then(res => { - console.log(res.rows[0]); - expect(res.rows.length).to.equal(0); - }); - - //teardown User table - cy.fixture('users.json').then(users => { - const username = users[0].username; - cy.task('delete_user', username); - }); - cy.task('delete_chainType', chainTypeName); -}); - -describe('Delete a Contribution', () => { - it('Deletes a Contribution', () => { - cy.get('[data-testid="deleteContribution-test"]', { timeout: 60000 }) - .should('be.visible') - .click(); - - cy.get('[data-testid="deleteContributionConfirm-test"]') - .should('be.visible') - .click(); - - cy.contains( - 'Please select at least one contribution to attribute to a DAO or mint.', - { timeout: 20000 }, - ); - }); -}); diff --git a/apps/protocol-frontend-e2e/src/integration/08_mintContributionFlow.cy.ts b/apps/protocol-frontend-e2e/src/integration/08_mintContributionFlow.cy.ts deleted file mode 100644 index b1d596522..000000000 --- a/apps/protocol-frontend-e2e/src/integration/08_mintContributionFlow.cy.ts +++ /dev/null @@ -1,114 +0,0 @@ -/// - -beforeEach(() => { - const chainTypeName = 'Goerli-Test'; - const getChaintTypeID = `SELECT id - FROM "ChainType" - WHERE name = 'Goerli-Test'`; - const getUserID = `SELECT id - FROM "User" - WHERE name = 'testusernamegovrne2etesting2022'`; - const getActivityTypeID = `SELECT id - FROM "ActivityType" - WHERE name = 'Pull Request'`; - - //seed ChainType table - cy.task('create_chainType', chainTypeName); - - //seed ContributionStatus table (not sure if this is necessary?) - cy.task('contribution_status'); - - //seed User table - cy.fixture('users.json').then(users => { - const userData = users[0]; - cy.task('queryDatabase', getChaintTypeID).then(res => { - const chainTypeID = res.rows[0].id; - userData['chain_type_id'] = chainTypeID; - cy.task('create_user', userData); - }); - }); - - //seed Guild table - cy.fixture('daos.json').then(guilds => { - for (const guild of guilds) { - const guild_name = guild.name; - cy.task('create_guild', guild_name); - } - }); - - //seed Contribution table - cy.fixture('contributions.json').then(contributions => { - const contributionData = contributions[0]; - cy.task('queryDatabase', getUserID).then(res => { - const userID = res.rows[0].id; - contributionData['userID'] = userID; - }); - cy.task('queryDatabase', getActivityTypeID).then(res => { - const ActivityTypeID = res.rows[0].id; - contributionData['activityTypeID'] = ActivityTypeID; - }); - cy.task('create_contribution', contributionData); - }); - - //Login User - cy.fixture('testaccounts.json').then(accounts => { - this.accounts = accounts; - cy.login(this.accounts[0].address, this.accounts[0].privateKey); - }); - - cy.get('[data-cy="myDashboards-btn"]', { timeout: 60000 }) - .should('be.enabled') - .click(); - - cy.get('[data-cy="contributionsSidebar-btn"]', { timeout: 100000 }) - .should('be.visible') - .click(); - - // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(5000); -}); -after(() => { - const chainTypeName = 'Goerli-Test'; - const getUserID = `SELECT id - FROM "User" - WHERE name = 'testusernamegovrne2etesting2022'`; - - //teardown UserActivity table - cy.task('queryDatabase', getUserID).then(res => { - const userID = res.rows[0].id; - cy.task('delete_UserActivity', userID); - }); - - //teardown Guild table - cy.fixture('daos.json').then(guilds => { - for (const guild of guilds) { - const guild_name = guild.name; - cy.task('delete_guild', guild_name); - } - }); - - //teardown Contribution table - cy.fixture('contributions.json').then(contributions => { - const name = contributions[0].name; - cy.task('delete_contribution', name); - }); - - //teardown User table - cy.fixture('users.json').then(users => { - const username = users[0].username; - cy.task('delete_user', username); - }); - cy.task('delete_chainType', chainTypeName); -}); - -describe('Edit first Contribution', () => { - it('Update/Edit Contribution', () => { - cy.get('[testid="toggle-row-selected"]').click(); - - cy.get('[data-testid="mint-btn-test"]').click(); - - cy.get('[data-testid="checkbox-testid"]').click(); - - cy.get('[data-testid="mintContribution-test"]').should('be.enabled'); - }); -}); diff --git a/apps/protocol-frontend-e2e/src/integration/09_createBulkMint.cy.ts b/apps/protocol-frontend-e2e/src/integration/09_createBulkMint.cy.ts deleted file mode 100644 index 04f3e7b14..000000000 --- a/apps/protocol-frontend-e2e/src/integration/09_createBulkMint.cy.ts +++ /dev/null @@ -1,120 +0,0 @@ -/// - -beforeEach(() => { - const chainTypeName = 'Goerli-Test'; - const getChaintTypeID = `SELECT id - FROM "ChainType" - WHERE name = 'Goerli-Test'`; - const getUserID = `SELECT id - FROM "User" - WHERE name = 'testusernamegovrne2etesting2022'`; - const getActivityTypeID = `SELECT id - FROM "ActivityType" - WHERE name = 'Pull Request'`; - - //seed ChainType table - cy.task('create_chainType', chainTypeName); - - //seed ContributionStatus table (not sure if this is necessary?) - cy.task('contribution_status'); - - //seed User table - cy.fixture('users.json').then(users => { - const userData = users[0]; - cy.task('queryDatabase', getChaintTypeID).then(res => { - const chainTypeID = res.rows[0].id; - userData['chain_type_id'] = chainTypeID; - cy.task('create_user', userData); - }); - }); - - //seed Guild table - cy.fixture('daos.json').then(guilds => { - for (const guild of guilds) { - const guild_name = guild.name; - cy.task('create_guild', guild_name); - } - }); - - //seed Contribution table - cy.fixture('contributions.json').then(contributionData => { - for (const contribution of contributionData) { - if (contribution.activityType === 'Pull Request') { - cy.task('queryDatabase', getUserID).then(res => { - const userID = res.rows[0].id; - contribution['userID'] = userID; - }); - cy.task('queryDatabase', getActivityTypeID).then(res => { - const ActivityTypeID = res.rows[0].id; - contribution['activityTypeID'] = ActivityTypeID; - }); - cy.task('create_contribution', contribution); - } - } - }); - - //Login User - cy.fixture('testaccounts.json').then(accounts => { - this.accounts = accounts; - cy.login(this.accounts[0].address, this.accounts[0].privateKey); - }); - - cy.get('[data-cy="myDashboards-btn"]', { timeout: 60000 }) - .should('be.enabled') - .click(); - - cy.get('[data-cy="contributionsSidebar-btn"]', { timeout: 100000 }) - .should('be.visible') - .click(); - - // eslint-disable-next-line cypress/no-unnecessary-waiting - cy.wait(5000); -}); -after(() => { - const chainTypeName = 'Goerli-Test'; - const getUserID = `SELECT id - FROM "User" - WHERE name = 'testusernamegovrne2etesting2022'`; - const contribution_names = [ - 'e2eTesting2022-Govrn Protocol Pull Request', - 'e2eTesting2022-Test Automation', - ]; - - //teardown UserActivity table - cy.task('queryDatabase', getUserID).then(res => { - const userID = res.rows[0].id; - cy.task('delete_UserActivity', userID); - }); - - //teardown Guild table - cy.fixture('daos.json').then(guilds => { - for (const guild of guilds) { - const guild_name = guild.name; - cy.task('delete_guild', guild_name); - } - }); - - //teardown Contribution table - for (const contribution_name of contribution_names) { - cy.task('delete_contribution', contribution_name); - } - - //teardown User table - cy.fixture('users.json').then(users => { - const username = users[0].username; - cy.task('delete_user', username); - }); - cy.task('delete_chainType', chainTypeName); -}); - -describe('Edit first Contribution', () => { - it('Update/Edit Contribution', () => { - cy.get('[testid="toggle-row-selected"]').click({ multiple: true }); - - cy.get('[data-testid="mint-btn-test"]').click(); - - cy.get('[data-testid="checkbox-testid"]').click(); - - cy.get('[data-testid="mintContribution-test"]').should('be.enabled'); - }); -}); diff --git a/apps/protocol-frontend-e2e/src/integration/app.cy.ts b/apps/protocol-frontend-e2e/src/integration/app.cy.ts deleted file mode 100644 index 67f42a215..000000000 --- a/apps/protocol-frontend-e2e/src/integration/app.cy.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { getGreeting } from '../support/app.po'; - -describe('protocol-frontend', () => { - beforeEach(() => cy.visit('/')); - - it('should have visually hidden h1 for "Govrn" which still shows up in the DOM', () => { - // Custom command example, see `../support/commands.ts` file - // cy.login('my-email@something.com', 'myPassword'); - - getGreeting().contains('Govrn'); - }); -}); diff --git a/apps/protocol-frontend/src/components/ContributionTypesTable.tsx b/apps/protocol-frontend/src/components/ContributionTypesTable.tsx index 973532e1a..46bcde397 100644 --- a/apps/protocol-frontend/src/components/ContributionTypesTable.tsx +++ b/apps/protocol-frontend/src/components/ContributionTypesTable.tsx @@ -13,7 +13,6 @@ import { Getter, } from '@tanstack/react-table'; import { UIContribution } from '@govrn/ui-types'; -import { mergePages } from '../utils/arrays'; type ContributionTypesTableType = { id: number; @@ -76,14 +75,14 @@ const columnsDefs: ColumnDef[] = [ const ContributionTypesTable = ({ contributionTypesData, }: { - contributionTypesData: UIContribution[][]; + contributionTypesData: UIContribution[]; }) => { const [sorting, setSorting] = useState([]); const uniqueContributions: UIContribution[] = useMemo( () => [ ...new Map( - mergePages(contributionTypesData) + contributionTypesData .sort((firstContribution, nextContribution) => isAfter( new Date(firstContribution.date_of_engagement), @@ -106,7 +105,7 @@ const ContributionTypesTable = ({ uniqueContributions.map(contributionType => ({ id: contributionType.id, name: contributionType.name, - total: mergePages(contributionTypesData).filter( + total: contributionTypesData.filter( contribution => contribution.activity_type.name === contributionType.activity_type.name, diff --git a/apps/protocol-frontend/src/components/ContributionsTable.tsx b/apps/protocol-frontend/src/components/ContributionsTable.tsx index ec78bc0f9..40038ab54 100644 --- a/apps/protocol-frontend/src/components/ContributionsTable.tsx +++ b/apps/protocol-frontend/src/components/ContributionsTable.tsx @@ -1,4 +1,4 @@ -import { useEffect, useMemo, useState } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import { Box, chakra, @@ -44,9 +44,9 @@ import DeleteContributionDialog from './DeleteContributionDialog'; import { BLOCK_EXPLORER_URLS } from '../utils/constants'; import { GovrnSpinner } from '@govrn/protocol-ui'; import InfiniteScroll from 'react-infinite-scroll-component'; -import { mergePages } from '../utils/arrays'; import { formatDate } from '../utils/date'; import { RowSelectionState } from '@tanstack/table-core'; +import { statusEmojiSelect } from '../utils/statusEmojiSelect'; export type DialogProps = { isOpen: boolean; @@ -55,23 +55,13 @@ export type DialogProps = { contributionId: number; }; -const emojiSelect = (status: string) => { - if (status === 'minted') { - return '🌞'; - } else if (status === 'pending') { - return '🕒'; - } else { - return '👀'; - } -}; - const ContributionsTable = ({ - contributionsData, + data, setSelectedContributions, hasMoreItems, nextPage, }: { - contributionsData: UIContribution[][]; + data: UIContribution[]; setSelectedContributions: (rows: UIContribution[]) => void; hasMoreItems: boolean; nextPage: () => void; @@ -93,15 +83,18 @@ const ContributionsTable = ({ contributionId: 0, }); - const handleDeleteContribution = (contributionId: number) => { - setDialog({ - ...dialog, - isOpen: true, //this opens AlertDialog - title: - "Are you sure you want to delete this contribution? You can't undo this action.", - contributionId: contributionId, - }); - }; + const handleDeleteContribution = useCallback( + (contributionId: number) => { + setDialog({ + ...dialog, + isOpen: true, //this opens AlertDialog + title: + "Are you sure you want to delete this contribution? You can't undo this action.", + contributionId: contributionId, + }); + }, + [dialog], + ); const [rowSelection, setRowSelection] = useState({}); const [selectedRows, setSelectedRows] = useState([]); @@ -112,10 +105,6 @@ const ContributionsTable = ({ setRowSelection({}); }; - const data = useMemo(() => { - return mergePages(contributionsData); - }, [contributionsData]); - const columnsDefs = useMemo[]>(() => { return [ { @@ -136,7 +125,6 @@ const ContributionsTable = ({ checked: row.getIsSelected(), indeterminate: row.getIsSomeSelected(), onChange: row.getToggleSelectedHandler(), - disabled: row.original.status.name !== 'staging', }} /> ), @@ -174,9 +162,9 @@ const ContributionsTable = ({ {getValue().name}{' '} - {emojiSelect(getValue().name)} + {statusEmojiSelect(getValue().name)} {' '} ); @@ -206,55 +194,38 @@ const ContributionsTable = ({ header: 'Actions', cell: ({ row }) => ( - {row.original.status.name === 'minted' || - row.original.status.name === 'pending' ? ( - - {row.original.tx_hash !== null && ( - - - - } - aria-label="View on Block Explorer" - variant="ghost" - color="gray.800" - padding={1} - /> - - - - )} - {row.original.status.name !== 'pending' && ( - } - variant="ghost" - color="gray.800" - disabled={row.original.user.id !== userData?.id} - aria-label="Delete Contribution" - data-testid="deleteContribution-test" - onClick={() => handleDeleteContribution(row.original.id)} - /> - )} - - ) : ( + {row.original.status.name === 'pending' && + row.original.tx_hash !== null && ( + + + + } + aria-label="View on Block Explorer" + variant="ghost" + color="gray.800" + padding={1} + /> + + + + )} + + {row.original.status.name === 'staging' && ( } variant="ghost" color="gray.800" aria-label="Edit Contribution" - disabled={ - row.original.user.id !== userData?.id || - row.original.status.name === 'minted' || - row.original.status.name === 'pending' - } + disabled={row.original.user.id !== userData?.id} data-testid="editContribution-test" onClick={() => handleEditContributionFormModal(row.original.id) @@ -275,9 +246,9 @@ const ContributionsTable = ({ ), }, ]; - }, []); + }, [handleDeleteContribution, handleEditContributionFormModal, userData?.id]); - const table = useReactTable({ + const table = useReactTable({ data, columns: columnsDefs, state: { @@ -285,7 +256,7 @@ const ContributionsTable = ({ rowSelection: rowSelection, globalFilter, }, - enableRowSelection: row => row.original.status.name === 'staging', + enableRowSelection: true, onSortingChange: setSorting, onRowSelectionChange: setRowSelection, onGlobalFilterChange: setGlobalFilter, @@ -387,7 +358,7 @@ const ContributionsTable = ({ content={ localContribution.id === selectedContribution, )! @@ -395,13 +366,6 @@ const ContributionsTable = ({ /> } /> - } - /> { const { userData } = useUser(); const { - data: contributions, + data: nonMintedContributionPages, isFetching, hasNextPage, fetchNextPage, } = useContributionInfiniteList({ where: { user_id: { equals: userData?.id }, + status: { isNot: { name: { equals: 'minted' } } }, }, }); + const { + data: mintedContributionPages, + isFetching: isMintedFetching, + hasNextPage: hasMintedNextPage, + fetchNextPage: fetchMintedNextPage, + } = useContributionInfiniteList({ + where: { + user_id: { equals: userData?.id }, + status: { is: { name: { equals: 'minted' } } }, + }, + }); + + const nonMintedContributions = useMemo(() => { + return mergePages([...(nonMintedContributionPages?.pages ?? [])]); + }, [nonMintedContributionPages]); + + const mintedContributions = useMemo(() => { + return mergePages([...(mintedContributionPages?.pages ?? [])]); + }, [mintedContributionPages]); + + const allContributions = useMemo(() => { + return [...nonMintedContributions, ...mintedContributions]; + }, [nonMintedContributions, mintedContributions]); + const { setModals } = useOverlay(); const [selectedContributions, setSelectedContributions] = useState< UIContribution[] @@ -57,9 +84,9 @@ const ContributionsTableShell = () => { maxWidth="1200px" > Contributions - {isFetching && contributions && contributions.pages.length === 0 ? ( + {isFetching && isMintedFetching ? ( - ) : contributions && contributions.pages.length > 0 ? ( + ) : allContributions.length > 0 ? ( { > Contributions + + Minted Contributions + Contribution Types + + + {nonMintedContributions.length > 0 ? ( + + + + + My Contributions + + {selectedContributions?.length === 0 ? ( + + + + 🌞 + {' '} + Please select at least one contribution to + attribute to a DAO or mint. + + + ) : ( + + + Attribute to DAO + + + {selectedContributions?.length > 1 + ? 'Bulk Mint' + : 'Mint'} + + + )} + + + + + + + ) : ( + + + + )} + + { > - - - My Contributions - - {selectedContributions?.length === 0 ? ( - - - - 🌞 - {' '} - Please select at least one contribution to attribute - to a DAO or mint. - - - ) : ( - - - Attribute to DAO - - - {selectedContributions?.length > 1 - ? 'Bulk Mint' - : 'Mint'} - - - )} - + + My Minted Contributions{' '} + + 🌞 + + - @@ -160,13 +227,9 @@ const ContributionsTableShell = () => { - {contributions.pages.length > 0 ? ( - - ) : ( - - )} + diff --git a/apps/protocol-frontend/src/components/MintedContributionsTable.tsx b/apps/protocol-frontend/src/components/MintedContributionsTable.tsx new file mode 100644 index 000000000..4e56ed74d --- /dev/null +++ b/apps/protocol-frontend/src/components/MintedContributionsTable.tsx @@ -0,0 +1,235 @@ +import { useCallback, useMemo, useState } from 'react'; +import { + Box, + chakra, + Flex, + HStack, + IconButton, + Stack, + Table, + Tbody, + Td, + Text, + Th, + Thead, + Tr, +} from '@chakra-ui/react'; +import { useUser } from '../contexts/UserContext'; +import { + ColumnDef, + getCoreRowModel, + getFilteredRowModel, + useReactTable, + flexRender, + SortingState, + getSortedRowModel, + Getter, + Row, +} from '@tanstack/react-table'; +import { Link } from 'react-router-dom'; +import { IoArrowDown, IoArrowUp } from 'react-icons/io5'; +import GlobalFilter from './GlobalFilter'; +import { UIContribution } from '@govrn/ui-types'; +import DeleteContributionDialog from './DeleteContributionDialog'; +import { GovrnSpinner } from '@govrn/protocol-ui'; +import InfiniteScroll from 'react-infinite-scroll-component'; +import { formatDate } from '../utils/date'; +import { FiTrash2 } from 'react-icons/fi'; + +export type DialogProps = { + isOpen: boolean; + title: string; + onConfirm: boolean; + contributionId: number; +}; + +const MintedContributionsTable = ({ + data, + hasMoreItems, + nextPage, +}: { + data: UIContribution[]; + hasMoreItems: boolean; + nextPage: () => void; +}) => { + const { userData } = useUser(); + + const [dialog, setDialog] = useState({ + isOpen: false, + title: '', + onConfirm: false, + contributionId: 0, + }); + + const handleDeleteContribution = useCallback( + (contributionId: number) => { + setDialog({ + ...dialog, + isOpen: true, //this opens AlertDialog + title: + "Are you sure you want to delete this contribution? You can't undo this action.", + contributionId: contributionId, + }); + }, + [dialog], + ); + const [sorting, setSorting] = useState([]); + const [globalFilter, setGlobalFilter] = useState(''); + + const columnsDefs: ColumnDef[] = useMemo< + ColumnDef[] + >(() => { + return [ + { + header: 'Name', + accessorKey: 'name', + cell: ({ + row, + getValue, + }: { + row: Row; + getValue: Getter; + }) => { + return ( + + + {getValue()} + + + ); + }, + }, + { + header: 'Engagement Date', + accessorFn: contribution => formatDate(contribution.date_of_engagement), + }, + { + header: 'Attestations', + accessorFn: contribution => String(contribution.attestations.length), + cell: ({ getValue }: { getValue: Getter }) => { + return {getValue()} ; + }, + }, + { + header: 'DAO', + accessorFn: contribution => + contribution.guilds.map(guildObj => guildObj.guild.name)[0] ?? '---', + cell: ({ getValue }: { getValue: Getter }) => { + return {getValue()}; + }, + }, + { + id: 'actions', + header: 'Actions', + cell: ({ row }) => ( + + } + variant="ghost" + color="gray.800" + disabled={row.original.user.id !== userData?.id} + aria-label="Delete Contribution" + data-testid="deleteContribution-test" + onClick={() => handleDeleteContribution(row.original.id)} + /> + + ), + }, + ]; + }, [handleDeleteContribution, userData?.id]); + + const table = useReactTable({ + data, + columns: columnsDefs, + state: { + sorting, + globalFilter, + }, + onSortingChange: setSorting, + onGlobalFilterChange: setGlobalFilter, + getCoreRowModel: getCoreRowModel(), + getSortedRowModel: getSortedRowModel(), + getFilteredRowModel: getFilteredRowModel(), + debugAll: false, + }); + + return ( + + r.original)} + globalFilter={globalFilter} + setGlobalFilter={setGlobalFilter} + /> + + } + > + + + {table.getHeaderGroups().map(headerGroup => ( + + {headerGroup.headers.map(header => ( + + {header.isPlaceholder ? null : ( + + {flexRender( + header.column.columnDef.header, + header.getContext(), + )} + + + {{ + asc: , + desc: ( + + ), + }[header.column.getIsSorted() as string] ?? null} + + + )} + + ))} + + + ))} + + + + {table.getRowModel().rows.length > 0 && + table.getRowModel().rows.map(row => { + return ( + + {row.getVisibleCells().map(cell => { + return ( + + {flexRender( + cell.column.columnDef.cell, + cell.getContext(), + )} + + ); + })} + + ); + })} + + + + + + + ); +}; + +export default MintedContributionsTable; diff --git a/apps/protocol-frontend/src/components/MyAttestationsTable.tsx b/apps/protocol-frontend/src/components/MyAttestationsTable.tsx index 16e0a3390..cb572aca5 100644 --- a/apps/protocol-frontend/src/components/MyAttestationsTable.tsx +++ b/apps/protocol-frontend/src/components/MyAttestationsTable.tsx @@ -30,6 +30,7 @@ import InfiniteScroll from 'react-infinite-scroll-component'; import { UIContribution } from '@govrn/ui-types'; import { GovrnSpinner } from '@govrn/protocol-ui'; import { Link } from 'react-router-dom'; +import { statusEmojiSelect } from '../utils/statusEmojiSelect'; type MyAttestationsTableType = { id: number; @@ -72,7 +73,7 @@ const columnsDef: ColumnDef[] = [ role="img" aria-labelledby="Emoji indicating Contribution status: Sun emoji for minted and Eyes emoji for staging." > - {getValue() === 'minted' ? '🌞' : '👀'} + {statusEmojiSelect(getValue())} {' '} ); diff --git a/apps/protocol-frontend/src/utils/statusEmojiSelect.ts b/apps/protocol-frontend/src/utils/statusEmojiSelect.ts new file mode 100644 index 000000000..45d715643 --- /dev/null +++ b/apps/protocol-frontend/src/utils/statusEmojiSelect.ts @@ -0,0 +1,9 @@ +const emojis: { [key: string]: string } = { + minted: '🌞', + staging: '🕒', + pending: '👀', +}; + +export const statusEmojiSelect = (status: string) => { + return emojis[status] ?? '👀'; +};