Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

697 google authentication end to end #713

Draft
wants to merge 4 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions cypress.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,15 @@ export default defineConfig({
baseUrl: 'http://localhost:3000',
viewportWidth: 375,
viewportHeight: 812,
chromeWebSecurity: false, // This allows cross-origin requests
},
env: {
googleClientId: process.env.REACT_APP_GOOGLE_CLIENT_ID,
},
component: {
devServer: {
framework: 'create-react-app',
bundler: 'webpack',
},
},
});
15 changes: 15 additions & 0 deletions cypress/e2e/existing-user.cy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import GoogleLogin from '../../src/features/auth/components/GoogleLogin';
import { mount } from '@cypress/react';
describe('Google Authentication', () => {
const navigateAfterLogin = cy.stub();
const text = 'Login with Google';
mount(<GoogleLogin navigateAfterLogin={navigateAfterLogin} text={text} />);
//Stepper should have initial count of 0 (default)
cy.get('[data-cy=counter]').should('have.text', '0');
});
it('should login with Google successfully', () => {
cy.loginWithGoogle();
// Add more assertions as needed
});

98 changes: 68 additions & 30 deletions cypress/e2e/new-user-a.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,26 @@ describe('New UserA', () => {
it('allows new userA to go through 10 questions, see his results (personal values) and sign up', () => {
// Load the HomePage and accept cookies
cy.visit('/');
cy.get('button').contains(/accept/i).click();
cy.get('button')
.contains(/accept/i)
.click();

// Transition to the PreQuizPage through button click
cy.get('button').contains(/get started/i).click({ force: true });
cy.get('button')
.contains(/get started/i)
.click({ force: true });
cy.location('pathname').should('equal', '/start');

// Transition to the QuizPage through button click
cy.get('button').contains(/take the quiz/i).click({ force: true });
cy.get('button')
.contains(/take the quiz/i)
.click({ force: true });
cy.location('pathname').should('equal', '/questionnaire');

// Complete the quiz.
for (let i = 0; i < 10; i++) {
cy.contains('Q' + (i+1));
cy.contains('/10')
cy.contains('Q' + (i + 1));
cy.contains('/10');
cy.contains(/not like me at all/i).click({ force: true });
cy.tick(300); // Skip the animation between questions
cy.wait(100); // Wait for the next question to appear
Expand All @@ -37,21 +43,32 @@ describe('New UserA', () => {
// Submit the feedback and finish the quiz
cy.contains(/bonus/i);
cy.get('input').type('Some custom feedback');
cy.get('button').contains(/finish quiz/i).click();
cy.get('button')
.contains(/finish quiz/i)
.click();

// Find out the results (personal values)
cy.location('pathname').should('equal', '/submit');
cy.get('button').contains(/find out my climate personality/i).click();
cy.get('button')
.contains(/find out my climate personality/i)
.click();
cy.location('pathname').should('equal', '/personal-values');

cy.contains(/power/i).should('be.visible');
cy.contains(/security/i).should('be.visible');
cy.contains(/tradition/i).should('be.visible');

cy.get('canvas[typeof="radar"]').should('be.visible');
cy.tick(300);
cy.wait(100);
cy.contains(/power/i).scrollIntoView().should('be.visible');
cy.contains(/security/i)
.scrollIntoView()
.should('be.visible');
cy.contains(/tradition/i)
.scrollIntoView()
.should('be.visible');

cy.get('canvas[typeof="radar"]').scrollIntoView().should('be.visible');

// Complete by going to the sign up page
cy.get('button').contains(/dive in/i).click();
cy.get('button')
.contains(/dive in/i)
.click();
cy.location('pathname').should('equal', '/sign-up');

// At first the sign up button should be disabled
Expand All @@ -64,26 +81,34 @@ describe('New UserA', () => {
cy.get('input[id="confirmPassword"]').type('asdf1234');

// Now the sign up button should be enabled and login the user as well
cy.get('button').contains(/create account/i).click();
cy.get('button')
.contains(/create account/i)
.click();
cy.location('pathname').should('equal', '/climate-feed');
});

it('allows new userA to go through 20 questions, see his results (personal values) and sign up', () => {
// Load the HomePage and accept cookies
cy.visit('/');
cy.get('button').contains(/accept/i).click();
cy.get('button')
.contains(/accept/i)
.click();

// Transition to the PreQuizPage through button click
cy.get('button').contains(/get started/i).click({ force: true });
cy.get('button')
.contains(/get started/i)
.click({ force: true });
cy.location('pathname').should('equal', '/start');

// Transition to the QuizPage through button click
cy.get('button').contains(/take the quiz/i).click({ force: true });
cy.get('button')
.contains(/take the quiz/i)
.click({ force: true });
cy.location('pathname').should('equal', '/questionnaire');

// Complete the quiz.
for (let i = 0; i < 10; i++) {
cy.contains('Q' + (i+1));
cy.contains('Q' + (i + 1));
cy.contains('/10');
cy.contains(/not like me at all/i).click({ force: true });
cy.tick(300); // Skip the animation between questions
Expand All @@ -93,16 +118,20 @@ describe('New UserA', () => {
// Submit the feedback and finish the quiz
cy.contains(/bonus/i);
cy.get('input').type('Some custom feedback');
cy.get('button').contains(/finish quiz/i).click();
cy.get('button')
.contains(/finish quiz/i)
.click();

// Continue with the next 10 questions
cy.location('pathname').should('equal', '/submit');
cy.get('button').contains(/continue/i).click();
cy.get('button')
.contains(/continue/i)
.click();
cy.location('pathname').should('equal', '/questionnaire');

// Complete the quiz.
for (let i = 10; i < 20; i++) {
cy.contains('Q' + (i+1));
cy.contains('Q' + (i + 1));
cy.contains('/20');
cy.contains(/not like me at all/i).click({ force: true });
cy.tick(300); // Skip the animation between questions
Expand All @@ -111,17 +140,26 @@ describe('New UserA', () => {

// Find out the results (personal values)
cy.location('pathname').should('equal', '/submit-set-two');
cy.get('button').contains(/find out my climate personality/i).click();
cy.get('button')
.contains(/find out my climate personality/i)
.click();
cy.location('pathname').should('equal', '/personal-values');

cy.contains(/power/i).should('be.visible');
cy.contains(/security/i).should('be.visible');
cy.contains(/tradition/i).should('be.visible');

cy.get('canvas[typeof="radar"]').should('be.visible');
cy.tick(300);
cy.wait(100);
cy.contains(/power/i).scrollIntoView().should('be.visible');
cy.contains(/security/i)
.scrollIntoView()
.should('be.visible');
cy.contains(/tradition/i)
.scrollIntoView()
.should('be.visible');

cy.get('canvas[typeof="radar"]').scrollIntoView().should('be.visible');

// Complete by going to the sign up page
cy.get('button').contains(/dive in/i).click();
cy.get('button')
.contains(/dive in/i)
.click();
cy.location('pathname').should('equal', '/sign-up');
});
});
144 changes: 107 additions & 37 deletions cypress/support/commands.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,107 @@
/// <reference types="cypress" />
// ***********************************************
// This example commands.ts shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
//
// declare global {
// namespace Cypress {
// interface Chainable {
// login(email: string, password: string): Chainable<void>
// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
// }
// }
// }
// In your commands.js or commands.ts file

Cypress.Commands.add('loginWithGoogle', () => {
cy.log('Starting Google login process');

// Visit the page where Google login is implemented
cy.visit('/');

// Wait for the Google Sign-In SDK to potentially load
cy.wait(1000); // Adjust this wait time as necessary

// // Mock the Google Sign-In API
// cy.window().then((win) => {
// win.google = {
// accounts: {
// id: {
// initialize: cy.stub().as('googleInitialize'),
// prompt: cy.stub().as('googlePrompt'),
// callback: cy.stub().as('googleCallback'),
// },
// },
// };
// });

cy.get('button')
.contains(/accept/i)
.click();
cy.wait(1000);
cy.get('button').contains(/login/i).click();

// Trigger the Google login process
cy.contains('button', /log in with google/i).click();

// Intercept the initialization of Google Sign-In
// cy.get('@googleInitialize').should('be.called');

// // Simulate the Google credential response
// cy.window().then((win) => {
// const mockCredentialResponse = {
// credential:
// 'eyJhbGciOiJSUzI1NiIsImtpZCI6ImE1MGY2ZTcwZWY0YjU0OGE1ZmQ5MTQyZWVjZDFmYjhmNTRkY2U5ZWUiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhenAiOiI0MDg0ODk2MjY2Ny12dTQya3A0MmJhMTZxM21jMWFoOGw4cm1tMDI4anNrZi5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImF1ZCI6IjQwODQ4OTYyNjY3LXZ1NDJrcDQyYmExNnEzbWMxYWg4bDhybW0wMjhqc2tmLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwic3ViIjoiMTEwNTUyOTU0MTYwNTY0MzY3MzUzIiwiZW1haWwiOiJraXJzdGllLmwuaGF5ZXNAZ29vZ2xlbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwibmJmIjoxNzI4NjUzMzYyLCJuYW1lIjoiS2lyc3RpZSBIIiwicGljdHVyZSI6Imh0dHBzOi8vbGgzLmdvb2dsZXVzZXJjb250ZW50LmNvbS9hL0FDZzhvY0tfQWU1TlpWVnlkbjR3ck9panRxdzA1OHdKYmNxRGJDNE1jbmlpX21QVTRqVVdhdGc9czk2LWMiLCJnaXZlbl9uYW1lIjoiS2lyc3RpZSIsImZhbWlseV9uYW1lIjoiSCIsImlhdCI6MTcyODY1MzY2MiwiZXhwIjoxNzI4NjU3MjYyLCJqdGkiOiIyMDlmYjFjMmIzZGFhZDljNWY1MjhlNDVlYWQ2ZjQwZDFiMmY3ZjJiIn0.uUWZGh-AyBUK-QSUaXpxY1caonOznq-Lkm4QFdxrZJTFpSUiXbdogHcUfESTgv59Wc9Cvzr_yJHNKa3wU-CMXtw5bfmwbpgG84sPF_rOrZyN_6hxBjqVhgH5yxE9DTBDR0D4QF_wjdylPhBPpqEz4XGoRXQv7_3OVzxvO7QPlZMRjElYqUJ8pvccMzEgVfkRPALkq49wGwk6o2rQKbONR0sGyOpqWWzMp79s7DGACextBS5VYzt6Enf7Ts2ZVJBD5H9SwSO1YQC-bckMQev32UKtZmap5ZDl4WYNkLFKK5wgFL6RCS6vXdrbfMTQSGfJ8O2rqu946K68qsVDT7TlPA',
// };

// // Get the callback function that was passed to initialize
// const initializeCall = win.google.accounts.id.initialize.getCall(0);
// const options = initializeCall.args[0];
// const callback = options.callback;

// // Call the callback function with the mock credential
// callback(mockCredentialResponse);
// });

// // Intercept the POST request to your backend
// cy.intercept('POST', '**/auth/google').as('googleAuth');

// // Wait for the auth request to complete
// cy.wait('@googleAuth').then((interception) => {
// expect(interception.response.statusCode).to.eq(200);
// });


cy.window().then((win) => {
// Assuming you have Google API initialized already in your app
win.google.accounts.id.prompt(); // This will trigger the Google sign-in prompt

// Define the credential response callback function
const handleCredentialResponse = (credential) => {
// Simulate handling the credential response
// You may need to replace this with your actual login logic
const credentialResponse = { credential };

// You can now call your login function with the credential
cy.task('GoogleSocialLogin', credentialResponse).then(({ cookies }) => {
// Set cookies as received from your task
cookies.forEach((cookie) => {
cy.setCookie(cookie.name, cookie.value, {
domain: cookie.domain,
expiry: cookie.expires,
httpOnly: cookie.httpOnly,
path: cookie.path,
secure: cookie.secure,
});
});

// Assert the user is logged in
cy.get('h6.dropdown-header').should('contain', name);
});
};

// Mock the Google accounts object
win.google = {
accounts: {
id: {
prompt: () => {
// Simulate successful response
handleCredentialResponse({
credential: 'mocked_google_credential', // Replace this with actual credential handling if needed
});
},
},
},
};
});

// Check for successful login (adjust according to your app's behavior)
cy.url().should('include', '/climate-feed');
});
13 changes: 13 additions & 0 deletions cypress/support/googleToken.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const CLIENT_ID = process.env.REACT_APP_GOOGLE_CLIENT_ID;

const handleCredentialResponse = (response: any) => {
const credential = response.credential;
// Pass the credential to your login function
return credential;
};

const handleGoogleLogin = () => {
(window as any).google.accounts.id.prompt(); // Triggers the Google sign-in prompt
};

handleGoogleLogin();
5 changes: 5 additions & 0 deletions cypress/support/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
declare namespace Cypress {
interface Chainable {
loginWithGoogle(): Chainable<void>;
}
}
15 changes: 15 additions & 0 deletions cypress/support/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export {};

declare global {
interface Window {
google: {
accounts: {
id: {
initialize: (options: any) => void;
prompt: () => void;
callback: (response: { credential: string }) => void;
};
};
};
}
}
2 changes: 1 addition & 1 deletion cypress/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
"lib": ["es5", "dom"],
"types": ["cypress", "node"]
},
"include": ["**/*.ts"]
"include": ["**/*.ts", "e2e/existing-user.cy.tsx"]
}
Loading