diff --git a/.editorconfig b/.editorconfig
index 21cb9608a0..e90faf856b 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -8,8 +8,6 @@ root = true
end_of_line = lf
insert_final_newline = true
charset = utf-8
-indent_style = space
-indent_size = 2
# makefile
[makefile]
diff --git a/.eslintrc.json b/.eslintrc.json
index 21ffb13a09..20c968413a 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -1,55 +1,55 @@
{
- "parser": "@typescript-eslint/parser",
- "extends": [
- "plugin:prettier/recommended",
- "plugin:@typescript-eslint/recommended",
- "plugin:react/recommended",
- "prettier",
- "plugin:jsx-a11y/recommended",
- "plugin:functional/no-mutations",
- "plugin:react-hooks/recommended",
- "plugin:@guardian/source-foundations/recommended",
- "plugin:@guardian/source-react-components/recommended",
- "plugin:storybook/recommended"
- ],
- "parserOptions": {
- "ecmaFeatures": {
- "jsx": true
- }
- },
- "plugins": ["functional"],
- "rules": {
- "react/prop-types": 0,
- "@typescript-eslint/explicit-function-return-type": 0,
- "@typescript-eslint/explicit-module-boundary-types": 0,
- "functional/prefer-readonly-type": 0,
- "functional/no-method-signature": 0,
- "functional/immutable-data": [
- "error",
- {
- "ignoreImmediateMutation": true
- }
- ],
- "functional/prefer-immutable-types": 0,
- "functional/type-declaration-immutability": 0,
- "no-var": "error",
- "no-param-reassign": "error",
- "prefer-const": "error",
- "no-sequences": "error",
- "no-console": "error",
- "react/no-unknown-property": ["error", { "ignore": ["css"] }]
- },
- "overrides": [
- {
- "files": ["*.stories.tsx"],
- "rules": {
- "functional/immutable-data": 0
- }
- }
- ],
- "settings": {
- "react": {
- "version": "detect"
- }
- }
+ "parser": "@typescript-eslint/parser",
+ "extends": [
+ "plugin:prettier/recommended",
+ "plugin:@typescript-eslint/recommended",
+ "plugin:react/recommended",
+ "prettier",
+ "plugin:jsx-a11y/recommended",
+ "plugin:functional/no-mutations",
+ "plugin:react-hooks/recommended",
+ "plugin:@guardian/source-foundations/recommended",
+ "plugin:@guardian/source-react-components/recommended",
+ "plugin:storybook/recommended"
+ ],
+ "parserOptions": {
+ "ecmaFeatures": {
+ "jsx": true
+ }
+ },
+ "plugins": ["functional"],
+ "rules": {
+ "react/prop-types": 0,
+ "@typescript-eslint/explicit-function-return-type": 0,
+ "@typescript-eslint/explicit-module-boundary-types": 0,
+ "functional/prefer-readonly-type": 0,
+ "functional/no-method-signature": 0,
+ "functional/immutable-data": [
+ "error",
+ {
+ "ignoreImmediateMutation": true
+ }
+ ],
+ "functional/prefer-immutable-types": 0,
+ "functional/type-declaration-immutability": 0,
+ "no-var": "error",
+ "no-param-reassign": "error",
+ "prefer-const": "error",
+ "no-sequences": "error",
+ "no-console": "error",
+ "react/no-unknown-property": ["error", { "ignore": ["css"] }]
+ },
+ "overrides": [
+ {
+ "files": ["*.stories.tsx"],
+ "rules": {
+ "functional/immutable-data": 0
+ }
+ }
+ ],
+ "settings": {
+ "react": {
+ "version": "detect"
+ }
+ }
}
diff --git a/.prettierrc b/.prettierrc
index 51bdee92e5..1ddbdff6f0 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,6 +1 @@
-{
- "tabWidth": 2,
- "trailingComma": "all",
- "singleQuote": true,
- "bracketSpacing": true
-}
+"@guardian/prettier"
diff --git a/.ratelimit.example.json b/.ratelimit.example.json
index 36fd4da0af..71d0ef88ba 100644
--- a/.ratelimit.example.json
+++ b/.ratelimit.example.json
@@ -1,15 +1,15 @@
{
- "enabled": false,
- "settings": {
- "logOnly": false,
- "trackBucketCapacity": false
- },
- "defaultBuckets": {
- "globalBucket": { "capacity": 500, "addTokenMs": 50 },
- "ipBucket": { "capacity": 100, "addTokenMs": 50 },
- "emailBucket": { "capacity": 100, "addTokenMs": 50 },
- "oktaIdentifierBucket": { "capacity": 100, "addTokenMs": 50 },
- "accessTokenBucket": { "capacity": 100, "addTokenMs": 50 }
- },
- "routeBuckets": {}
+ "enabled": false,
+ "settings": {
+ "logOnly": false,
+ "trackBucketCapacity": false
+ },
+ "defaultBuckets": {
+ "globalBucket": { "capacity": 500, "addTokenMs": 50 },
+ "ipBucket": { "capacity": 100, "addTokenMs": 50 },
+ "emailBucket": { "capacity": 100, "addTokenMs": 50 },
+ "oktaIdentifierBucket": { "capacity": 100, "addTokenMs": 50 },
+ "accessTokenBucket": { "capacity": 100, "addTokenMs": 50 }
+ },
+ "routeBuckets": {}
}
diff --git a/.storybook/clientStateDecorator.tsx b/.storybook/clientStateDecorator.tsx
index a653ed6a04..4d206c8184 100644
--- a/.storybook/clientStateDecorator.tsx
+++ b/.storybook/clientStateDecorator.tsx
@@ -2,19 +2,19 @@ import React from 'react';
import { DecoratorFn } from '@storybook/react';
import {
- ClientStateProvider,
- defaultClientState,
+ ClientStateProvider,
+ defaultClientState,
} from '../src/client/components/ClientState';
const clientStateDecorator: DecoratorFn = (StoryToDecorate, context) => (
-
-
-
+
+
+
);
export default clientStateDecorator;
diff --git a/.storybook/main.js b/.storybook/main.js
index 3cab22db5c..82e558b314 100644
--- a/.storybook/main.js
+++ b/.storybook/main.js
@@ -3,17 +3,17 @@ const { neutral } = require('@guardian/source-foundations');
const deepmerge = require('deepmerge');
const sharedLoader = require('../.swcrc.config');
const config = {
- stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
- addons: [
- '@storybook/addon-links',
- '@storybook/addon-essentials',
- '@storybook/addon-styling',
- ],
- babel: async (options) => {
- options.presets.push('@emotion/babel-preset-css-prop');
- return options;
- },
- previewHead: (head) => `
+ stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
+ addons: [
+ '@storybook/addon-links',
+ '@storybook/addon-essentials',
+ '@storybook/addon-styling',
+ ],
+ babel: async (options) => {
+ options.presets.push('@emotion/babel-preset-css-prop');
+ return options;
+ },
+ previewHead: (head) => `
${head}
`,
- webpackFinal: async (config) => {
- // Add the @client alias to prevent imports using it from failing
- // Nb. __dirname is the current working directory, so .storybook in this case
- config.resolve.alias = {
- ...config.resolve.alias,
- '@': path.join(__dirname, '../src'),
- react: 'preact/compat',
- 'react-dom/test-utils': 'preact/test-utils',
- 'react-dom': 'preact/compat',
- // Must be below test-utils
- 'react/jsx-runtime': 'preact/jsx-runtime',
- mjml: 'mjml-browser',
- // We stub these libraries required by mjml because Storybook cannot run these on the client side.
- 'uglify-js': false,
- 'clean-css': false,
- };
+ webpackFinal: async (config) => {
+ // Add the @client alias to prevent imports using it from failing
+ // Nb. __dirname is the current working directory, so .storybook in this case
+ config.resolve.alias = {
+ ...config.resolve.alias,
+ '@': path.join(__dirname, '../src'),
+ react: 'preact/compat',
+ 'react-dom/test-utils': 'preact/test-utils',
+ 'react-dom': 'preact/compat',
+ // Must be below test-utils
+ 'react/jsx-runtime': 'preact/jsx-runtime',
+ mjml: 'mjml-browser',
+ // We stub these libraries required by mjml because Storybook cannot run these on the client side.
+ 'uglify-js': false,
+ 'clean-css': false,
+ };
- // transpile certain modules so we can get them to work with ie11 storybook
- const transpileModules = {
- include: [/node_modules[\\\/]@guardian/],
- test: /\.(m?)(j|t)s(x?)/,
- use: [
- deepmerge(sharedLoader, {
- options: {
- env: {
- targets: {
- chrome: '100',
- },
- },
- },
- }),
- ],
- };
+ // transpile certain modules so we can get them to work with ie11 storybook
+ const transpileModules = {
+ include: [/node_modules[\\\/]@guardian/],
+ test: /\.(m?)(j|t)s(x?)/,
+ use: [
+ deepmerge(sharedLoader, {
+ options: {
+ env: {
+ targets: {
+ chrome: '100',
+ },
+ },
+ },
+ }),
+ ],
+ };
- // Return the altered config
- return {
- ...config,
- module: {
- ...config.module,
- rules: [...config.module.rules, transpileModules],
- },
- target: ['web'],
- };
- },
- typescript: {
- reactDocgen: 'react-docgen-typescript-plugin',
- },
- framework: {
- name: '@storybook/react-webpack5',
- options: {},
- },
- docs: {
- autodocs: false,
- },
+ // Return the altered config
+ return {
+ ...config,
+ module: {
+ ...config.module,
+ rules: [...config.module.rules, transpileModules],
+ },
+ target: ['web'],
+ };
+ },
+ typescript: {
+ reactDocgen: 'react-docgen-typescript-plugin',
+ },
+ framework: {
+ name: '@storybook/react-webpack5',
+ options: {},
+ },
+ docs: {
+ autodocs: false,
+ },
};
export default config;
diff --git a/.storybook/preview-head.html b/.storybook/preview-head.html
index 618d9372b8..9824d89961 100644
--- a/.storybook/preview-head.html
+++ b/.storybook/preview-head.html
@@ -1,5 +1,5 @@
diff --git a/.storybook/preview.js b/.storybook/preview.js
index 6c6704dc4f..a4f8ceb535 100644
--- a/.storybook/preview.js
+++ b/.storybook/preview.js
@@ -9,87 +9,87 @@ import clientStateDecorator from './clientStateDecorator';
import { neutral } from '@guardian/source-foundations';
const GlobalStyles = () => (
-
+
);
/* Source provides a global utility that manages the appearance of focus styles. When enabled,
* focus styles will be hidden while the user interacts using the mouse.
* They will appear when the tab key is pressed to begin keyboard navigation. */
const FocusManagerDecorator = (storyFn) => {
- React.useEffect(() => {
- FocusStyleManager.onlyShowFocusOnTabs();
- }, []);
+ React.useEffect(() => {
+ FocusStyleManager.onlyShowFocusOnTabs();
+ }, []);
- return <>{storyFn()}>;
+ return <>{storyFn()}>;
};
const customViewports = {};
for (let breakpoint in Breakpoints) {
- if (isNaN(Number(breakpoint))) {
- // Breakpoints is an enum, not an object, so it also loops the values which we want to avoid here
- customViewports[breakpoint] = {
- name: `${breakpoint} (${Breakpoints[breakpoint]})`,
- styles: {
- width: `${Breakpoints[breakpoint]}px`,
- height: '100vh',
- },
- };
- }
+ if (isNaN(Number(breakpoint))) {
+ // Breakpoints is an enum, not an object, so it also loops the values which we want to avoid here
+ customViewports[breakpoint] = {
+ name: `${breakpoint} (${Breakpoints[breakpoint]})`,
+ styles: {
+ width: `${Breakpoints[breakpoint]}px`,
+ height: '100vh',
+ },
+ };
+ }
}
const decorators = [
- withThemeFromJSXProvider({
- GlobalStyles,
- }),
- FocusManagerDecorator,
- clientStateDecorator,
+ withThemeFromJSXProvider({
+ GlobalStyles,
+ }),
+ FocusManagerDecorator,
+ clientStateDecorator,
];
const parameters = {
- actions: { argTypesRegex: '^on[A-Z].*' },
- controls: {
- matchers: {
- color: /(background|color)$/i,
- date: /Date$/,
- },
- },
- viewport: {
- viewports: {
- ...customViewports,
- ...INITIAL_VIEWPORTS,
- },
- defaultViewport: 'MOBILE',
- },
+ actions: { argTypesRegex: '^on[A-Z].*' },
+ controls: {
+ matchers: {
+ color: /(background|color)$/i,
+ date: /Date$/,
+ },
+ },
+ viewport: {
+ viewports: {
+ ...customViewports,
+ ...INITIAL_VIEWPORTS,
+ },
+ defaultViewport: 'MOBILE',
+ },
};
const preview = {
- decorators,
- parameters,
+ decorators,
+ parameters,
};
export default preview;
diff --git a/.swcrc.config.js b/.swcrc.config.js
index 16305f872b..16c6c6183f 100644
--- a/.swcrc.config.js
+++ b/.swcrc.config.js
@@ -1,35 +1,35 @@
const mode =
- process.env.ENVIRONMENT === 'production' ? 'production' : 'development';
+ process.env.ENVIRONMENT === 'production' ? 'production' : 'development';
module.exports = {
- loader: 'swc-loader',
- options: {
- jsc: {
- parser: {
- syntax: 'typescript',
- tsx: true,
- decorators: false,
- dynamicImport: true,
- },
- transform: {
- react: {
- runtime: 'automatic',
- throwIfNamespace: true,
- importSource: '@emotion/react',
- },
- },
- experimental: {
- plugins: [
- [
- '@swc/plugin-emotion',
- {
- // only in development, as this increases bundle size in production
- sourceMap: mode === 'development',
- },
- ],
- ],
- },
- },
- sourceMaps: true,
- },
+ loader: 'swc-loader',
+ options: {
+ jsc: {
+ parser: {
+ syntax: 'typescript',
+ tsx: true,
+ decorators: false,
+ dynamicImport: true,
+ },
+ transform: {
+ react: {
+ runtime: 'automatic',
+ throwIfNamespace: true,
+ importSource: '@emotion/react',
+ },
+ },
+ experimental: {
+ plugins: [
+ [
+ '@swc/plugin-emotion',
+ {
+ // only in development, as this increases bundle size in production
+ sourceMap: mode === 'development',
+ },
+ ],
+ ],
+ },
+ },
+ sourceMaps: true,
+ },
};
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index df4da5f863..e63b735ae4 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -1,9 +1,9 @@
{
- "recommendations": [
- "editorconfig.editorconfig",
- "dbaeumer.vscode-eslint",
- "esbenp.prettier-vscode",
- "visualstudioexptteam.vscodeintellicode",
- "ms-vsliveshare.vsliveshare"
- ]
+ "recommendations": [
+ "editorconfig.editorconfig",
+ "dbaeumer.vscode-eslint",
+ "esbenp.prettier-vscode",
+ "visualstudioexptteam.vscodeintellicode",
+ "ms-vsliveshare.vsliveshare"
+ ]
}
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 7989999885..c694989589 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,8 +1,8 @@
{
- "json.schemas": [
- {
- "fileMatch": [".ratelimit.json", ".ratelimit.example.json"],
- "url": "./.ratelimit.schema.json"
- }
- ]
+ "json.schemas": [
+ {
+ "fileMatch": [".ratelimit.json", ".ratelimit.example.json"],
+ "url": "./.ratelimit.schema.json"
+ }
+ ]
}
diff --git a/artifact.json b/artifact.json
index 007b4c0770..9d0f73a650 100644
--- a/artifact.json
+++ b/artifact.json
@@ -1,16 +1,16 @@
{
- "projectName": "identity:identity-gateway",
- "vcsURL": "https://github.com/guardian/gateway",
- "actions": [
- {
- "action": "identity-gateway",
- "path": "build",
- "compress": "zip"
- },
- {
- "action": "gateway-cloudformation",
- "path": "cloudformation.yaml",
- "compress": false
- }
- ]
+ "projectName": "identity:identity-gateway",
+ "vcsURL": "https://github.com/guardian/gateway",
+ "actions": [
+ {
+ "action": "identity-gateway",
+ "path": "build",
+ "compress": "zip"
+ },
+ {
+ "action": "gateway-cloudformation",
+ "path": "cloudformation.yaml",
+ "compress": false
+ }
+ ]
}
diff --git a/babel.config.js b/babel.config.js
index 407556570d..41d146631d 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -1,19 +1,19 @@
/* eslint-disable functional/immutable-data */
// only used by storybook
module.exports = {
- presets: [
- [
- '@babel/preset-env',
- {
- shippedProposals: true,
- useBuiltIns: 'usage',
- corejs: '3',
- modules: false,
- targets: { chrome: '100' },
- },
- ],
- '@babel/preset-typescript',
- '@babel/preset-react',
- ],
- plugins: [],
+ presets: [
+ [
+ '@babel/preset-env',
+ {
+ shippedProposals: true,
+ useBuiltIns: 'usage',
+ corejs: '3',
+ modules: false,
+ targets: { chrome: '100' },
+ },
+ ],
+ '@babel/preset-typescript',
+ '@babel/preset-react',
+ ],
+ plugins: [],
};
diff --git a/cypress.config.ts b/cypress.config.ts
index 7fa637e4ee..55a4df6f6c 100644
--- a/cypress.config.ts
+++ b/cypress.config.ts
@@ -1,28 +1,28 @@
import { defineConfig } from 'cypress';
export default defineConfig({
- video: false,
- chromeWebSecurity: false,
- defaultCommandTimeout: 12000,
- responseTimeout: 12000,
- requestTimeout: 12000,
- env: {
- mockingEndpoint: 'localhost:9000/mock',
- },
- e2e: {
- baseUrl: 'https://profile.thegulocal.com',
- specPattern: 'cypress/integration/**/*.cy.ts',
- excludeSpecPattern: '*.shared.ts',
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
- setupNodeEvents(on, config) {
- on('task', {
- log(message) {
- // eslint-disable-next-line no-console
- console.log(`CYPRESS: ${message}`);
+ video: false,
+ chromeWebSecurity: false,
+ defaultCommandTimeout: 12000,
+ responseTimeout: 12000,
+ requestTimeout: 12000,
+ env: {
+ mockingEndpoint: 'localhost:9000/mock',
+ },
+ e2e: {
+ baseUrl: 'https://profile.thegulocal.com',
+ specPattern: 'cypress/integration/**/*.cy.ts',
+ excludeSpecPattern: '*.shared.ts',
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ setupNodeEvents(on, config) {
+ on('task', {
+ log(message) {
+ // eslint-disable-next-line no-console
+ console.log(`CYPRESS: ${message}`);
- return null;
- },
- });
- },
- },
+ return null;
+ },
+ });
+ },
+ },
});
diff --git a/cypress/fixtures/okta-responses/error/authentication-failed.json b/cypress/fixtures/okta-responses/error/authentication-failed.json
index 249c65f1ce..21dc9ba010 100644
--- a/cypress/fixtures/okta-responses/error/authentication-failed.json
+++ b/cypress/fixtures/okta-responses/error/authentication-failed.json
@@ -1,10 +1,10 @@
{
- "code": 401,
- "response": {
- "errorCode": "E0000004",
- "errorSummary": "Authentication failed",
- "errorLink": "E0000004",
- "errorId": "mocked-error-id",
- "errorCauses": []
- }
+ "code": 401,
+ "response": {
+ "errorCode": "E0000004",
+ "errorSummary": "Authentication failed",
+ "errorLink": "E0000004",
+ "errorId": "mocked-error-id",
+ "errorCauses": []
+ }
}
diff --git a/cypress/fixtures/okta-responses/error/no-permission.json b/cypress/fixtures/okta-responses/error/no-permission.json
index 2afdcc20ed..d75d0c997d 100644
--- a/cypress/fixtures/okta-responses/error/no-permission.json
+++ b/cypress/fixtures/okta-responses/error/no-permission.json
@@ -1,10 +1,10 @@
{
- "code": 403,
- "response": {
- "errorCode": "E0000006",
- "errorSummary": "You do not have permission to perform the requested action",
- "errorLink": "E0000006",
- "errorId": "mocked-error-id",
- "errorCauses": []
- }
+ "code": 403,
+ "response": {
+ "errorCode": "E0000006",
+ "errorSummary": "You do not have permission to perform the requested action",
+ "errorLink": "E0000006",
+ "errorId": "mocked-error-id",
+ "errorCauses": []
+ }
}
diff --git a/cypress/fixtures/okta-responses/error/user-exists.json b/cypress/fixtures/okta-responses/error/user-exists.json
index ded5454d26..dcc2dedb6c 100644
--- a/cypress/fixtures/okta-responses/error/user-exists.json
+++ b/cypress/fixtures/okta-responses/error/user-exists.json
@@ -1,14 +1,14 @@
{
- "code": 401,
- "response": {
- "errorCode": "E0000001",
- "errorSummary": "Api validation failed: login",
- "errorLink": "E0000001",
- "errorId": "mocked-error-id",
- "errorCauses": [
- {
- "errorSummary": "login: An object with this field already exists in the current organization"
- }
- ]
- }
+ "code": 401,
+ "response": {
+ "errorCode": "E0000001",
+ "errorSummary": "Api validation failed: login",
+ "errorLink": "E0000001",
+ "errorId": "mocked-error-id",
+ "errorCauses": [
+ {
+ "errorSummary": "login: An object with this field already exists in the current organization"
+ }
+ ]
+ }
}
diff --git a/cypress/fixtures/okta-responses/error/user-not-found.json b/cypress/fixtures/okta-responses/error/user-not-found.json
index ec7de80c92..cd5a25e127 100644
--- a/cypress/fixtures/okta-responses/error/user-not-found.json
+++ b/cypress/fixtures/okta-responses/error/user-not-found.json
@@ -1,10 +1,10 @@
{
- "code": 404,
- "response": {
- "errorCode": "E0000007",
- "errorSummary": "Not found: Resource not found: example@example.com (User)",
- "errorLink": "E0000007",
- "errorId": "mocked-error-id",
- "errorCauses": []
- }
+ "code": 404,
+ "response": {
+ "errorCode": "E0000007",
+ "errorSummary": "Not found: Resource not found: example@example.com (User)",
+ "errorLink": "E0000007",
+ "errorId": "mocked-error-id",
+ "errorCauses": []
+ }
}
diff --git a/cypress/fixtures/okta-responses/success/auth-reset-password.json b/cypress/fixtures/okta-responses/success/auth-reset-password.json
index 81a31ffefd..49f11bf074 100644
--- a/cypress/fixtures/okta-responses/success/auth-reset-password.json
+++ b/cypress/fixtures/okta-responses/success/auth-reset-password.json
@@ -1,21 +1,21 @@
{
- "code": 200,
- "response": {
- "expiresAt": "2015-11-03T10:15:57.000Z",
- "status": "SUCCESS",
- "sessionToken": "mocked_session_token",
- "_embedded": {
- "user": {
- "id": "mocked_user_id",
- "passwordChanged": "2015-11-08T20:14:45.000Z",
- "profile": {
- "login": "test.testerson@example.com",
- "firstName": "Test",
- "lastName": "Testerson",
- "locale": "en_US",
- "timeZone": "America/Los_Angeles"
- }
- }
- }
- }
+ "code": 200,
+ "response": {
+ "expiresAt": "2015-11-03T10:15:57.000Z",
+ "status": "SUCCESS",
+ "sessionToken": "mocked_session_token",
+ "_embedded": {
+ "user": {
+ "id": "mocked_user_id",
+ "passwordChanged": "2015-11-08T20:14:45.000Z",
+ "profile": {
+ "login": "test.testerson@example.com",
+ "firstName": "Test",
+ "lastName": "Testerson",
+ "locale": "en_US",
+ "timeZone": "America/Los_Angeles"
+ }
+ }
+ }
+ }
}
diff --git a/cypress/fixtures/okta-responses/success/forgot-password-email-factor.json b/cypress/fixtures/okta-responses/success/forgot-password-email-factor.json
index 6764f21039..c390ecf6f0 100644
--- a/cypress/fixtures/okta-responses/success/forgot-password-email-factor.json
+++ b/cypress/fixtures/okta-responses/success/forgot-password-email-factor.json
@@ -1,9 +1,9 @@
{
- "code": 200,
- "response": {
- "status": "RECOVERY_CHALLENGE",
- "factorResult": "WAITING",
- "factorType": "EMAIL",
- "recoveryType": "PASSWORD"
- }
+ "code": 200,
+ "response": {
+ "status": "RECOVERY_CHALLENGE",
+ "factorResult": "WAITING",
+ "factorType": "EMAIL",
+ "recoveryType": "PASSWORD"
+ }
}
diff --git a/cypress/fixtures/okta-responses/success/reset-password.json b/cypress/fixtures/okta-responses/success/reset-password.json
index ff5f12332a..140fe769a9 100644
--- a/cypress/fixtures/okta-responses/success/reset-password.json
+++ b/cypress/fixtures/okta-responses/success/reset-password.json
@@ -1,6 +1,6 @@
{
- "code": 200,
- "response": {
- "resetPasswordUrl": "https://$OKTA_ORG_URL/reset_password/XE6wE17zmphl3KqAPFxO"
- }
+ "code": 200,
+ "response": {
+ "resetPasswordUrl": "https://$OKTA_ORG_URL/reset_password/XE6wE17zmphl3KqAPFxO"
+ }
}
diff --git a/cypress/fixtures/okta-responses/success/social-user.json b/cypress/fixtures/okta-responses/success/social-user.json
index 2aeff70cd9..cce3a43060 100644
--- a/cypress/fixtures/okta-responses/success/social-user.json
+++ b/cypress/fixtures/okta-responses/success/social-user.json
@@ -1,15 +1,15 @@
{
- "code": 200,
- "response": {
- "id": "mocked-id",
- "status": "ACTIVE",
- "profile": {
- "firstName": null,
- "lastName": null,
- "email": "example@example.com",
- "login": "example@example.com",
- "isGuardianUser": true
- },
- "credentials": { "provider": { "type": "SOCIAL", "name": "SOCIAL" } }
- }
+ "code": 200,
+ "response": {
+ "id": "mocked-id",
+ "status": "ACTIVE",
+ "profile": {
+ "firstName": null,
+ "lastName": null,
+ "email": "example@example.com",
+ "login": "example@example.com",
+ "isGuardianUser": true
+ },
+ "credentials": { "provider": { "type": "SOCIAL", "name": "SOCIAL" } }
+ }
}
diff --git a/cypress/fixtures/okta-responses/success/token.json b/cypress/fixtures/okta-responses/success/token.json
index 35d7066b5e..b383bde747 100644
--- a/cypress/fixtures/okta-responses/success/token.json
+++ b/cypress/fixtures/okta-responses/success/token.json
@@ -1,7 +1,7 @@
{
- "code": 200,
- "response": {
- "activationUrl": "https://$OKTA_ORG_URL/welcome/XE6wE17zmphl3KqAPFxO",
- "activationToken": "XE6wE17zmphl3KqAPFxO"
- }
+ "code": 200,
+ "response": {
+ "activationUrl": "https://$OKTA_ORG_URL/welcome/XE6wE17zmphl3KqAPFxO",
+ "activationToken": "XE6wE17zmphl3KqAPFxO"
+ }
}
diff --git a/cypress/fixtures/okta-responses/success/user.json b/cypress/fixtures/okta-responses/success/user.json
index b9334a5fd0..fd3defbae4 100644
--- a/cypress/fixtures/okta-responses/success/user.json
+++ b/cypress/fixtures/okta-responses/success/user.json
@@ -1,15 +1,15 @@
{
- "code": 200,
- "response": {
- "id": "mocked-id",
- "status": "$STATUS",
- "profile": {
- "firstName": null,
- "lastName": null,
- "email": "example@example.com",
- "login": "example@example.com",
- "isGuardianUser": true
- },
- "credentials": { "provider": { "type": "OKTA", "name": "OKTA" } }
- }
+ "code": 200,
+ "response": {
+ "id": "mocked-id",
+ "status": "$STATUS",
+ "profile": {
+ "firstName": null,
+ "lastName": null,
+ "email": "example@example.com",
+ "login": "example@example.com",
+ "isGuardianUser": true
+ },
+ "credentials": { "provider": { "type": "OKTA", "name": "OKTA" } }
+ }
}
diff --git a/cypress/fixtures/okta-responses/success/valid-user-groups.json b/cypress/fixtures/okta-responses/success/valid-user-groups.json
index 83d8649abf..1599c8f4bb 100644
--- a/cypress/fixtures/okta-responses/success/valid-user-groups.json
+++ b/cypress/fixtures/okta-responses/success/valid-user-groups.json
@@ -1,12 +1,12 @@
{
- "code": 200,
- "response": [
- {
- "id": "123",
- "profile": {
- "name": "GuardianUser-EmailValidated",
- "description": "User has validated their email"
- }
- }
- ]
+ "code": 200,
+ "response": [
+ {
+ "id": "123",
+ "profile": {
+ "name": "GuardianUser-EmailValidated",
+ "description": "User has validated their email"
+ }
+ }
+ ]
}
diff --git a/cypress/fixtures/okta-responses/success/valid-user.json b/cypress/fixtures/okta-responses/success/valid-user.json
index 85ef3bd370..0635f3c09d 100644
--- a/cypress/fixtures/okta-responses/success/valid-user.json
+++ b/cypress/fixtures/okta-responses/success/valid-user.json
@@ -1,21 +1,21 @@
{
- "code": 200,
- "response": {
- "expiresAt": "2022-08-11T11:54:13.000Z",
- "status": "SUCCESS",
- "sessionToken": "session-token",
- "_embedded": {
- "user": {
- "id": "user-id",
- "passwordChanged": "2022-08-11T11:24:42.000Z",
- "profile": {
- "login": "example@example.com",
- "firstName": null,
- "lastName": null,
- "locale": "en_US",
- "timeZone": "America/Los_Angeles"
- }
- }
- }
- }
+ "code": 200,
+ "response": {
+ "expiresAt": "2022-08-11T11:54:13.000Z",
+ "status": "SUCCESS",
+ "sessionToken": "session-token",
+ "_embedded": {
+ "user": {
+ "id": "user-id",
+ "passwordChanged": "2022-08-11T11:24:42.000Z",
+ "profile": {
+ "login": "example@example.com",
+ "firstName": null,
+ "lastName": null,
+ "locale": "en_US",
+ "timeZone": "America/Los_Angeles"
+ }
+ }
+ }
+ }
}
diff --git a/cypress/fixtures/okta-responses/success/verify-recovery-token.json b/cypress/fixtures/okta-responses/success/verify-recovery-token.json
index c43aada839..f27dcf817b 100644
--- a/cypress/fixtures/okta-responses/success/verify-recovery-token.json
+++ b/cypress/fixtures/okta-responses/success/verify-recovery-token.json
@@ -1,21 +1,21 @@
{
- "code": 200,
- "response": {
- "stateToken": "some_mocked_state_token",
- "expiresAt": "2015-11-03T10:15:57.000Z",
- "status": "RECOVERY",
- "_embedded": {
- "user": {
- "id": "some_user_id",
- "passwordChanged": "2015-09-08T20:14:45.000Z",
- "profile": {
- "login": "test.testerson@example.com",
- "firstName": "Test",
- "lastName": "Testerson",
- "locale": "en_US",
- "timeZone": "America/Los_Angeles"
- }
- }
- }
- }
+ "code": 200,
+ "response": {
+ "stateToken": "some_mocked_state_token",
+ "expiresAt": "2015-11-03T10:15:57.000Z",
+ "status": "RECOVERY",
+ "_embedded": {
+ "user": {
+ "id": "some_user_id",
+ "passwordChanged": "2015-09-08T20:14:45.000Z",
+ "profile": {
+ "login": "test.testerson@example.com",
+ "firstName": "Test",
+ "lastName": "Testerson",
+ "locale": "en_US",
+ "timeZone": "America/Los_Angeles"
+ }
+ }
+ }
+ }
}
diff --git a/cypress/fixtures/users.json b/cypress/fixtures/users.json
index 8efff910bb..12399acbf0 100644
--- a/cypress/fixtures/users.json
+++ b/cypress/fixtures/users.json
@@ -1,8 +1,8 @@
{
- "validEmail": {
- "email": "mrtest@theguardian.com"
- },
- "emailNotRegistered": {
- "email": "mxunregistered@theguardian.com"
- }
+ "validEmail": {
+ "email": "mrtest@theguardian.com"
+ },
+ "emailNotRegistered": {
+ "email": "mxunregistered@theguardian.com"
+ }
}
diff --git a/cypress/integration/ete-okta/jobs_terms.4.cy.ts b/cypress/integration/ete-okta/jobs_terms.4.cy.ts
index 1881e47366..6f03f2d686 100644
--- a/cypress/integration/ete-okta/jobs_terms.4.cy.ts
+++ b/cypress/integration/ete-okta/jobs_terms.4.cy.ts
@@ -1,219 +1,219 @@
describe('Jobs terms and conditions flow in Okta', () => {
- context('Shows the terms and conditions page on Sign In', () => {
- it('visits /agree/GRS after sign in if clientId=jobs parameter is set', () => {
- cy.intercept('GET', 'https://jobs.theguardian.com/', (req) => {
- req.reply(200);
- });
-
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress, finalPassword }) => {
- const visitUrl =
- '/signin?clientId=jobs&returnUrl=https%3A%2F%2Fjobs.theguardian.com%2F';
- cy.visit(visitUrl);
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', '/agree/GRS');
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', 'https://jobs.theguardian.com/');
- });
- });
- });
-
- context('Accepts Jobs terms and conditions and sets their name', () => {
- it('should redirect users with an invalid session cookie to reauthenticate', () => {
- // load the consents page as its on the same domain
- const termsAcceptPageUrl = `https://${Cypress.env(
- 'BASE_URI',
- )}/agree/GRS?returnUrl=https://profile.thegulocal.com/signin?returnUrl=https%3A%2F%2Fm.code.dev-theguardian.com%2F`;
- cy.setCookie('sid', 'invalid-cookie');
- cy.visit(termsAcceptPageUrl);
- cy.url().should(
- 'include',
- 'https://profile.thegulocal.com/reauthenticate',
- );
- });
-
- it('should redirect users with no session cookie to the signin page', () => {
- // load the consents page as its on the same domain
- const termsAcceptPageUrl = `https://${Cypress.env(
- 'BASE_URI',
- )}/agree/GRS?returnUrl=https://profile.thegulocal.com/healthcheck`;
- cy.visit(termsAcceptPageUrl);
- cy.url().should(
- 'include',
- 'https://profile.thegulocal.com/signin?fromURI=',
- );
- });
-
- it('should show the jobs terms page for users who do not have first/last name set, but are jobs users', () => {
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress, finalPassword }) => {
- cy.visit('/signin');
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
-
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.url().should('include', '/signin/success');
-
- const termsAcceptPageUrl = `https://${Cypress.env(
- 'BASE_URI',
- )}/agree/GRS?returnUrl=https://profile.thegulocal.com/healthcheck`;
-
- // Create a test user without a first/last name who has `isJobsUser` set to true.
- cy.updateOktaTestUserProfile(emailAddress, {
- firstName: '',
- lastName: '',
- isJobsUser: true,
- }).then(() => {
- // clear oauth token cookies to simulate the user profile update
- cy.clearCookie('GU_ID_TOKEN', { domain: Cypress.env('BASE_URI') });
- cy.clearCookie('GU_ACCESS_TOKEN', {
- domain: Cypress.env('BASE_URI'),
- });
-
- cy.visit(termsAcceptPageUrl);
- cy.contains('Please complete your details for');
- cy.contains(emailAddress);
- cy.contains('We will use these details on your job applications');
-
- cy.get('input[name=firstName]').should('be.empty');
- cy.get('input[name=secondName]').should('be.empty');
-
- cy.get('input[name=firstName]').type('First Name');
- cy.get('input[name=secondName]').type('Second Name');
-
- cy.findByText('Save and continue').click();
-
- // User should have `isJobsUser` set to true and First/Last name set to our custom values.
- cy.getTestOktaUser(emailAddress).then(({ profile, status }) => {
- const { firstName, lastName, isJobsUser } = profile;
- expect(status).to.eq('ACTIVE');
- expect(firstName).to.eq('First Name');
- expect(lastName).to.eq('Second Name');
- expect(isJobsUser).to.eq(true);
- });
- });
- });
- });
-
- it('should redirect users who have already accepted the terms away', () => {
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress, finalPassword }) => {
- // load the consents page as its on the same domain
- const termsAcceptPageUrl = `https://${Cypress.env(
- 'BASE_URI',
- )}/agree/GRS?returnUrl=https://profile.thegulocal.com/healthcheck`;
-
- cy.visit('/signin');
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
-
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.url().should('include', '/signin/success');
-
- cy.updateOktaTestUserProfile(emailAddress, {
- firstName: 'Test',
- lastName: 'User',
- isJobsUser: true,
- }).then(() => {
- cy.visit(termsAcceptPageUrl);
-
- cy.url().should(
- 'include',
- 'https://profile.thegulocal.com/healthcheck',
- );
-
- const finalTermsAcceptPageUrl = `https://${Cypress.env(
- 'BASE_URI',
- )}/agree/GRS?returnUrl=https://profile.thegulocal.com/maintenance`;
-
- cy.visit(finalTermsAcceptPageUrl, { failOnStatusCode: false });
-
- // Make sure the returnURL is respected.
- cy.url().should(
- 'include',
- 'https://profile.thegulocal.com/maintenance',
- );
- });
- });
- });
-
- it('should allow a non-jobs user to enter their first/last name and accept the terms', () => {
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress, finalPassword }) => {
- // load the consents page as its on the same domain
- const termsAcceptPageUrl = `https://${Cypress.env(
- 'BASE_URI',
- )}/agree/GRS?returnUrl=https://jobs.theguardian.com/`;
-
- cy.visit('/signin');
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
-
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.url().should('include', '/signin/success');
-
- cy.visit(termsAcceptPageUrl);
-
- // check sign in has worked first
- cy.url().should('include', `/agree/GRS`);
- // check session cookie is set
- cy.getCookie('sid').should('exist');
- // check idapi cookies are set
- cy.getCookie('SC_GU_U').should('exist');
- cy.getCookie('SC_GU_LA').should('exist');
- cy.getCookie('GU_U').should('exist');
-
- cy.contains('Welcome to Guardian Jobs');
-
- // User should not be a jobs user yet and have their original first/last name.
- cy.getTestOktaUser(emailAddress).then(({ profile, status }) => {
- const { firstName, lastName, isJobsUser } = profile;
- expect(status).to.eq('ACTIVE');
- cy.get('input[name=firstName]').should('contain.value', firstName);
- cy.get('input[name=secondName]').should('contain.value', lastName);
- expect(isJobsUser).to.eq(false);
- });
-
- cy.get('input[name=firstName]').clear().type('First Name');
- cy.get('input[name=secondName]').clear().type('Second Name');
-
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', 'https://jobs.theguardian.com/', (req) => {
- req.reply(200);
- });
-
- cy.findByText('Continue').click();
-
- // Make sure the returnURL is respected.
- cy.url().should('include', 'https://jobs.theguardian.com/');
-
- // User should have `isJobsUser` set to true and their First/Last name set.
- cy.getTestOktaUser(emailAddress).then(({ profile, status }) => {
- const { firstName, lastName, isJobsUser } = profile;
- expect(status).to.eq('ACTIVE');
- expect(firstName).to.eq('First Name');
- expect(lastName).to.eq('Second Name');
- expect(isJobsUser).to.eq(true);
- });
- });
- });
- });
+ context('Shows the terms and conditions page on Sign In', () => {
+ it('visits /agree/GRS after sign in if clientId=jobs parameter is set', () => {
+ cy.intercept('GET', 'https://jobs.theguardian.com/', (req) => {
+ req.reply(200);
+ });
+
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress, finalPassword }) => {
+ const visitUrl =
+ '/signin?clientId=jobs&returnUrl=https%3A%2F%2Fjobs.theguardian.com%2F';
+ cy.visit(visitUrl);
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', '/agree/GRS');
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', 'https://jobs.theguardian.com/');
+ });
+ });
+ });
+
+ context('Accepts Jobs terms and conditions and sets their name', () => {
+ it('should redirect users with an invalid session cookie to reauthenticate', () => {
+ // load the consents page as its on the same domain
+ const termsAcceptPageUrl = `https://${Cypress.env(
+ 'BASE_URI',
+ )}/agree/GRS?returnUrl=https://profile.thegulocal.com/signin?returnUrl=https%3A%2F%2Fm.code.dev-theguardian.com%2F`;
+ cy.setCookie('sid', 'invalid-cookie');
+ cy.visit(termsAcceptPageUrl);
+ cy.url().should(
+ 'include',
+ 'https://profile.thegulocal.com/reauthenticate',
+ );
+ });
+
+ it('should redirect users with no session cookie to the signin page', () => {
+ // load the consents page as its on the same domain
+ const termsAcceptPageUrl = `https://${Cypress.env(
+ 'BASE_URI',
+ )}/agree/GRS?returnUrl=https://profile.thegulocal.com/healthcheck`;
+ cy.visit(termsAcceptPageUrl);
+ cy.url().should(
+ 'include',
+ 'https://profile.thegulocal.com/signin?fromURI=',
+ );
+ });
+
+ it('should show the jobs terms page for users who do not have first/last name set, but are jobs users', () => {
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress, finalPassword }) => {
+ cy.visit('/signin');
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.url().should('include', '/signin/success');
+
+ const termsAcceptPageUrl = `https://${Cypress.env(
+ 'BASE_URI',
+ )}/agree/GRS?returnUrl=https://profile.thegulocal.com/healthcheck`;
+
+ // Create a test user without a first/last name who has `isJobsUser` set to true.
+ cy.updateOktaTestUserProfile(emailAddress, {
+ firstName: '',
+ lastName: '',
+ isJobsUser: true,
+ }).then(() => {
+ // clear oauth token cookies to simulate the user profile update
+ cy.clearCookie('GU_ID_TOKEN', { domain: Cypress.env('BASE_URI') });
+ cy.clearCookie('GU_ACCESS_TOKEN', {
+ domain: Cypress.env('BASE_URI'),
+ });
+
+ cy.visit(termsAcceptPageUrl);
+ cy.contains('Please complete your details for');
+ cy.contains(emailAddress);
+ cy.contains('We will use these details on your job applications');
+
+ cy.get('input[name=firstName]').should('be.empty');
+ cy.get('input[name=secondName]').should('be.empty');
+
+ cy.get('input[name=firstName]').type('First Name');
+ cy.get('input[name=secondName]').type('Second Name');
+
+ cy.findByText('Save and continue').click();
+
+ // User should have `isJobsUser` set to true and First/Last name set to our custom values.
+ cy.getTestOktaUser(emailAddress).then(({ profile, status }) => {
+ const { firstName, lastName, isJobsUser } = profile;
+ expect(status).to.eq('ACTIVE');
+ expect(firstName).to.eq('First Name');
+ expect(lastName).to.eq('Second Name');
+ expect(isJobsUser).to.eq(true);
+ });
+ });
+ });
+ });
+
+ it('should redirect users who have already accepted the terms away', () => {
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress, finalPassword }) => {
+ // load the consents page as its on the same domain
+ const termsAcceptPageUrl = `https://${Cypress.env(
+ 'BASE_URI',
+ )}/agree/GRS?returnUrl=https://profile.thegulocal.com/healthcheck`;
+
+ cy.visit('/signin');
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.url().should('include', '/signin/success');
+
+ cy.updateOktaTestUserProfile(emailAddress, {
+ firstName: 'Test',
+ lastName: 'User',
+ isJobsUser: true,
+ }).then(() => {
+ cy.visit(termsAcceptPageUrl);
+
+ cy.url().should(
+ 'include',
+ 'https://profile.thegulocal.com/healthcheck',
+ );
+
+ const finalTermsAcceptPageUrl = `https://${Cypress.env(
+ 'BASE_URI',
+ )}/agree/GRS?returnUrl=https://profile.thegulocal.com/maintenance`;
+
+ cy.visit(finalTermsAcceptPageUrl, { failOnStatusCode: false });
+
+ // Make sure the returnURL is respected.
+ cy.url().should(
+ 'include',
+ 'https://profile.thegulocal.com/maintenance',
+ );
+ });
+ });
+ });
+
+ it('should allow a non-jobs user to enter their first/last name and accept the terms', () => {
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress, finalPassword }) => {
+ // load the consents page as its on the same domain
+ const termsAcceptPageUrl = `https://${Cypress.env(
+ 'BASE_URI',
+ )}/agree/GRS?returnUrl=https://jobs.theguardian.com/`;
+
+ cy.visit('/signin');
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.url().should('include', '/signin/success');
+
+ cy.visit(termsAcceptPageUrl);
+
+ // check sign in has worked first
+ cy.url().should('include', `/agree/GRS`);
+ // check session cookie is set
+ cy.getCookie('sid').should('exist');
+ // check idapi cookies are set
+ cy.getCookie('SC_GU_U').should('exist');
+ cy.getCookie('SC_GU_LA').should('exist');
+ cy.getCookie('GU_U').should('exist');
+
+ cy.contains('Welcome to Guardian Jobs');
+
+ // User should not be a jobs user yet and have their original first/last name.
+ cy.getTestOktaUser(emailAddress).then(({ profile, status }) => {
+ const { firstName, lastName, isJobsUser } = profile;
+ expect(status).to.eq('ACTIVE');
+ cy.get('input[name=firstName]').should('contain.value', firstName);
+ cy.get('input[name=secondName]').should('contain.value', lastName);
+ expect(isJobsUser).to.eq(false);
+ });
+
+ cy.get('input[name=firstName]').clear().type('First Name');
+ cy.get('input[name=secondName]').clear().type('Second Name');
+
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', 'https://jobs.theguardian.com/', (req) => {
+ req.reply(200);
+ });
+
+ cy.findByText('Continue').click();
+
+ // Make sure the returnURL is respected.
+ cy.url().should('include', 'https://jobs.theguardian.com/');
+
+ // User should have `isJobsUser` set to true and their First/Last name set.
+ cy.getTestOktaUser(emailAddress).then(({ profile, status }) => {
+ const { firstName, lastName, isJobsUser } = profile;
+ expect(status).to.eq('ACTIVE');
+ expect(firstName).to.eq('First Name');
+ expect(lastName).to.eq('Second Name');
+ expect(isJobsUser).to.eq(true);
+ });
+ });
+ });
+ });
});
diff --git a/cypress/integration/ete-okta/onboarding_flow.5.cy.ts b/cypress/integration/ete-okta/onboarding_flow.5.cy.ts
index 0dbf5c5f12..c8b46a28b4 100644
--- a/cypress/integration/ete-okta/onboarding_flow.5.cy.ts
+++ b/cypress/integration/ete-okta/onboarding_flow.5.cy.ts
@@ -1,7 +1,7 @@
import { setMvtId } from '../../support/commands/setMvtId';
import {
- randomMailosaurEmail,
- randomPassword,
+ randomMailosaurEmail,
+ randomPassword,
} from '../../support/commands/testUser';
import CommunicationsPage from '../../support/pages/onboarding/communications_page';
import NewslettersPage from '../../support/pages/onboarding/newsletters_page';
@@ -9,223 +9,223 @@ import ReviewPage from '../../support/pages/onboarding/review_page';
import YourDataPage from '../../support/pages/onboarding/your_data_page';
describe('Onboarding flow', () => {
- beforeEach(() => {
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', 'https://m.code.dev-theguardian.com/', (req) => {
- req.reply(200);
- });
- setMvtId('0');
- });
+ beforeEach(() => {
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', 'https://m.code.dev-theguardian.com/', (req) => {
+ req.reply(200);
+ });
+ setMvtId('0');
+ });
- context('Full flow', () => {
- it('goes through the full flow, opt in all consents/marketing, preserve returnUrl', () => {
- const returnUrl =
- 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
- const unregisteredEmail = randomMailosaurEmail();
+ context('Full flow', () => {
+ it('goes through the full flow, opt in all consents/marketing, preserve returnUrl', () => {
+ const returnUrl =
+ 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
+ const unregisteredEmail = randomMailosaurEmail();
- cy.visit(`/register?returnUrl=${returnUrl}`);
+ cy.visit(`/register?returnUrl=${returnUrl}`);
- const timeRequestWasMade = new Date();
- cy.get('input[name=email]').type(unregisteredEmail);
- cy.get('[data-cy="main-form-submit-button"]').click();
+ const timeRequestWasMade = new Date();
+ cy.get('input[name=email]').type(unregisteredEmail);
+ cy.get('[data-cy="main-form-submit-button"]').click();
- cy.contains('Check your email inbox');
- cy.contains(unregisteredEmail);
- cy.contains('Resend email');
- cy.contains('Change email address');
+ cy.contains('Check your email inbox');
+ cy.contains(unregisteredEmail);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
- cy.checkForEmailAndGetDetails(
- unregisteredEmail,
- timeRequestWasMade,
- /welcome\/([^"]*)/,
- ).then(({ body, token }) => {
- expect(body).to.have.string('Complete registration');
- cy.enableCMP();
- cy.setCookie('GU_geo_country', 'FR');
+ cy.checkForEmailAndGetDetails(
+ unregisteredEmail,
+ timeRequestWasMade,
+ /welcome\/([^"]*)/,
+ ).then(({ body, token }) => {
+ expect(body).to.have.string('Complete registration');
+ cy.enableCMP();
+ cy.setCookie('GU_geo_country', 'FR');
- cy.visit(`/welcome/${token}`);
- cy.acceptCMP();
+ cy.visit(`/welcome/${token}`);
+ cy.acceptCMP();
- cy.contains('Save and continue');
+ cy.contains('Save and continue');
- cy.get('input[name=password]').type(randomPassword());
+ cy.get('input[name=password]').type(randomPassword());
- cy.get('[data-cy="change-password-button"]').click();
+ cy.get('[data-cy="change-password-button"]').click();
- cy.url().should('include', CommunicationsPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
+ cy.url().should('include', CommunicationsPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
- CommunicationsPage.backButton().should('not.exist');
- CommunicationsPage.allCheckboxes().should('not.be.checked');
- CommunicationsPage.allCheckboxes().click({ multiple: true });
+ CommunicationsPage.backButton().should('not.exist');
+ CommunicationsPage.allCheckboxes().should('not.be.checked');
+ CommunicationsPage.allCheckboxes().click({ multiple: true });
- CommunicationsPage.saveAndContinueButton().click();
+ CommunicationsPage.saveAndContinueButton().click();
- cy.url().should('include', NewslettersPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
+ cy.url().should('include', NewslettersPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
- NewslettersPage.backButton()
- .should('have.attr', 'href')
- .and('include', CommunicationsPage.URL);
+ NewslettersPage.backButton()
+ .should('have.attr', 'href')
+ .and('include', CommunicationsPage.URL);
- NewslettersPage.allCheckboxes()
- .should('not.be.checked')
- .click({ multiple: true });
+ NewslettersPage.allCheckboxes()
+ .should('not.be.checked')
+ .click({ multiple: true });
- NewslettersPage.saveAndContinueButton().click();
+ NewslettersPage.saveAndContinueButton().click();
- cy.url().should('include', YourDataPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
+ cy.url().should('include', YourDataPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
- YourDataPage.backButton()
- .should('have.attr', 'href')
- .and('include', NewslettersPage.URL);
+ YourDataPage.backButton()
+ .should('have.attr', 'href')
+ .and('include', NewslettersPage.URL);
- YourDataPage.personalisedAdvertisingOptInInput().should(
- 'not.be.checked',
- );
+ YourDataPage.personalisedAdvertisingOptInInput().should(
+ 'not.be.checked',
+ );
- YourDataPage.personalisedAdvertisingOptInSwitch().click();
- YourDataPage.marketingOptInSwitch().should('be.checked');
- YourDataPage.personalisedAdvertisingOptInInput().should('be.checked');
+ YourDataPage.personalisedAdvertisingOptInSwitch().click();
+ YourDataPage.marketingOptInSwitch().should('be.checked');
+ YourDataPage.personalisedAdvertisingOptInInput().should('be.checked');
- YourDataPage.saveAndContinueButton().click();
+ YourDataPage.saveAndContinueButton().click();
- cy.url().should('include', ReviewPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
+ cy.url().should('include', ReviewPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
- ReviewPage.backButton().should('not.exist');
- ReviewPage.saveAndContinueButton().should('not.exist');
+ ReviewPage.backButton().should('not.exist');
+ ReviewPage.saveAndContinueButton().should('not.exist');
- // contains opted in newsletters
- cy.contains('Down to Earth');
- cy.contains('The Long Read');
- cy.contains('First Edition');
+ // contains opted in newsletters
+ cy.contains('Down to Earth');
+ cy.contains('The Long Read');
+ cy.contains('First Edition');
- // contains consents
- cy.contains(ReviewPage.CONTENT.SUPPORTER_CONSENT);
- cy.contains(ReviewPage.CONTENT.PROFILING_CONSENT);
- cy.contains(ReviewPage.CONTENT.PERSONALISED_ADVERTISING_CONSENT);
+ // contains consents
+ cy.contains(ReviewPage.CONTENT.SUPPORTER_CONSENT);
+ cy.contains(ReviewPage.CONTENT.PROFILING_CONSENT);
+ cy.contains(ReviewPage.CONTENT.PERSONALISED_ADVERTISING_CONSENT);
- // does not contain messaging encouraging user to consider other newsletters
- cy.contains(ReviewPage.CONTENT.NO_NEWSLETTERS_TITLE).should(
- 'not.exist',
- );
+ // does not contain messaging encouraging user to consider other newsletters
+ cy.contains(ReviewPage.CONTENT.NO_NEWSLETTERS_TITLE).should(
+ 'not.exist',
+ );
- ReviewPage.returnButton()
- .should('have.attr', 'href')
- .and('include', decodeURIComponent(returnUrl));
+ ReviewPage.returnButton()
+ .should('have.attr', 'href')
+ .and('include', decodeURIComponent(returnUrl));
- ReviewPage.returnButton().click();
+ ReviewPage.returnButton().click();
- cy.url().should('include', decodeURIComponent(returnUrl));
- });
- });
+ cy.url().should('include', decodeURIComponent(returnUrl));
+ });
+ });
- it('goes through full fow, opt out of all consents/newsletters, preserve returnUrl', () => {
- const returnUrl =
- 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
- const unregisteredEmail = randomMailosaurEmail();
+ it('goes through full fow, opt out of all consents/newsletters, preserve returnUrl', () => {
+ const returnUrl =
+ 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
+ const unregisteredEmail = randomMailosaurEmail();
- cy.visit(`/register?returnUrl=${returnUrl}`);
+ cy.visit(`/register?returnUrl=${returnUrl}`);
- const timeRequestWasMade = new Date();
- cy.get('input[name=email]').type(unregisteredEmail);
- cy.get('[data-cy="main-form-submit-button"]').click();
+ const timeRequestWasMade = new Date();
+ cy.get('input[name=email]').type(unregisteredEmail);
+ cy.get('[data-cy="main-form-submit-button"]').click();
- cy.contains('Check your email inbox');
- cy.contains(unregisteredEmail);
- cy.contains('Resend email');
- cy.contains('Change email address');
+ cy.contains('Check your email inbox');
+ cy.contains(unregisteredEmail);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
- cy.checkForEmailAndGetDetails(
- unregisteredEmail,
- timeRequestWasMade,
- /welcome\/([^"]*)/,
- ).then(({ body, token }) => {
- expect(body).to.have.string('Complete registration');
- cy.enableCMP();
- cy.setCookie('GU_geo_country', 'FR');
+ cy.checkForEmailAndGetDetails(
+ unregisteredEmail,
+ timeRequestWasMade,
+ /welcome\/([^"]*)/,
+ ).then(({ body, token }) => {
+ expect(body).to.have.string('Complete registration');
+ cy.enableCMP();
+ cy.setCookie('GU_geo_country', 'FR');
- cy.visit(`/welcome/${token}`);
- cy.acceptCMP();
+ cy.visit(`/welcome/${token}`);
+ cy.acceptCMP();
- cy.contains('Save and continue');
+ cy.contains('Save and continue');
- cy.get('input[name=password]').type(randomPassword());
+ cy.get('input[name=password]').type(randomPassword());
- cy.get('[data-cy="change-password-button"]').click();
+ cy.get('[data-cy="change-password-button"]').click();
- cy.url().should('include', CommunicationsPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
+ cy.url().should('include', CommunicationsPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
- CommunicationsPage.backButton().should('not.exist');
- CommunicationsPage.allCheckboxes().should('not.be.checked');
+ CommunicationsPage.backButton().should('not.exist');
+ CommunicationsPage.allCheckboxes().should('not.be.checked');
- CommunicationsPage.saveAndContinueButton().click();
+ CommunicationsPage.saveAndContinueButton().click();
- cy.url().should('include', NewslettersPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
+ cy.url().should('include', NewslettersPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
- NewslettersPage.backButton()
- .should('have.attr', 'href')
- .and('include', CommunicationsPage.URL);
+ NewslettersPage.backButton()
+ .should('have.attr', 'href')
+ .and('include', CommunicationsPage.URL);
- NewslettersPage.allCheckboxes().should('not.be.checked');
+ NewslettersPage.allCheckboxes().should('not.be.checked');
- NewslettersPage.saveAndContinueButton().click();
+ NewslettersPage.saveAndContinueButton().click();
- cy.url().should('include', YourDataPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
+ cy.url().should('include', YourDataPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
- YourDataPage.backButton()
- .should('have.attr', 'href')
- .and('include', NewslettersPage.URL);
+ YourDataPage.backButton()
+ .should('have.attr', 'href')
+ .and('include', NewslettersPage.URL);
- YourDataPage.personalisedAdvertisingOptInInput().should(
- 'not.be.checked',
- );
- YourDataPage.marketingOptInSwitch().should('be.checked');
+ YourDataPage.personalisedAdvertisingOptInInput().should(
+ 'not.be.checked',
+ );
+ YourDataPage.marketingOptInSwitch().should('be.checked');
- YourDataPage.marketingOptInSwitch().click({ force: true });
+ YourDataPage.marketingOptInSwitch().click({ force: true });
- YourDataPage.marketingOptInSwitch().should('not.be.checked');
- YourDataPage.personalisedAdvertisingOptInInput().should(
- 'not.be.checked',
- );
+ YourDataPage.marketingOptInSwitch().should('not.be.checked');
+ YourDataPage.personalisedAdvertisingOptInInput().should(
+ 'not.be.checked',
+ );
- YourDataPage.saveAndContinueButton().click();
+ YourDataPage.saveAndContinueButton().click();
- cy.url().should('include', ReviewPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
+ cy.url().should('include', ReviewPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
- ReviewPage.backButton().should('not.exist');
- ReviewPage.saveAndContinueButton().should('not.exist');
+ ReviewPage.backButton().should('not.exist');
+ ReviewPage.saveAndContinueButton().should('not.exist');
- // contains opted in newsletters
- cy.contains('Down to Earth').should('not.exist');
- cy.contains('The Long Read').should('not.exist');
- cy.contains('First Edition').should('not.exist');
+ // contains opted in newsletters
+ cy.contains('Down to Earth').should('not.exist');
+ cy.contains('The Long Read').should('not.exist');
+ cy.contains('First Edition').should('not.exist');
- // contains consents
- cy.contains(ReviewPage.CONTENT.SUPPORTER_CONSENT).should('not.exist');
- cy.contains(ReviewPage.CONTENT.PROFILING_CONSENT).should('not.exist');
- cy.contains(ReviewPage.CONTENT.PERSONALISED_ADVERTISING_CONSENT).should(
- 'not.exist',
- );
+ // contains consents
+ cy.contains(ReviewPage.CONTENT.SUPPORTER_CONSENT).should('not.exist');
+ cy.contains(ReviewPage.CONTENT.PROFILING_CONSENT).should('not.exist');
+ cy.contains(ReviewPage.CONTENT.PERSONALISED_ADVERTISING_CONSENT).should(
+ 'not.exist',
+ );
- // contains messaging encouraging user to consider other newsletters
- cy.contains(ReviewPage.CONTENT.NO_NEWSLETTERS_TITLE).should('exist');
+ // contains messaging encouraging user to consider other newsletters
+ cy.contains(ReviewPage.CONTENT.NO_NEWSLETTERS_TITLE).should('exist');
- ReviewPage.returnButton()
- .should('have.attr', 'href')
- .and('include', decodeURIComponent(returnUrl));
+ ReviewPage.returnButton()
+ .should('have.attr', 'href')
+ .and('include', decodeURIComponent(returnUrl));
- ReviewPage.returnButton().click();
+ ReviewPage.returnButton().click();
- cy.url().should('include', decodeURIComponent(returnUrl));
- });
- });
- });
+ cy.url().should('include', decodeURIComponent(returnUrl));
+ });
+ });
+ });
});
diff --git a/cypress/integration/ete-okta/post_sign_in_prompt.5.cy.ts b/cypress/integration/ete-okta/post_sign_in_prompt.5.cy.ts
index d01ef50cf1..ab48e6517b 100644
--- a/cypress/integration/ete-okta/post_sign_in_prompt.5.cy.ts
+++ b/cypress/integration/ete-okta/post_sign_in_prompt.5.cy.ts
@@ -1,105 +1,105 @@
describe('Post sign-in prompt', () => {
- beforeEach(() => {
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', 'https://m.code.dev-theguardian.com/', (req) => {
- req.reply(200);
- });
- cy.clearCookie('GU_ran_experiments');
- });
+ beforeEach(() => {
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', 'https://m.code.dev-theguardian.com/', (req) => {
+ req.reply(200);
+ });
+ cy.clearCookie('GU_ran_experiments');
+ });
- it('allows user to opt in and continue', () => {
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress, finalPassword }) => {
- const visitUrl = '/signin';
- cy.visit(visitUrl);
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', `/signin/success`);
- cy.url().should(
- 'include',
- `returnUrl=${encodeURIComponent(
- 'https://m.code.dev-theguardian.com/',
- )}`,
- );
- const checkbox = cy.findByLabelText('Yes, sign me up');
- checkbox.should('not.be.checked');
- checkbox.click();
- checkbox.should('be.checked');
- cy.findByText('Continue to the Guardian').click();
- cy.url().should('include', 'https://m.code.dev-theguardian.com/');
- });
- });
+ it('allows user to opt in and continue', () => {
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress, finalPassword }) => {
+ const visitUrl = '/signin';
+ cy.visit(visitUrl);
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', `/signin/success`);
+ cy.url().should(
+ 'include',
+ `returnUrl=${encodeURIComponent(
+ 'https://m.code.dev-theguardian.com/',
+ )}`,
+ );
+ const checkbox = cy.findByLabelText('Yes, sign me up');
+ checkbox.should('not.be.checked');
+ checkbox.click();
+ checkbox.should('be.checked');
+ cy.findByText('Continue to the Guardian').click();
+ cy.url().should('include', 'https://m.code.dev-theguardian.com/');
+ });
+ });
- it('allows user to opt out and continue', () => {
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress, finalPassword }) => {
- const visitUrl = '/signin';
- cy.visit(visitUrl);
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', `/signin/success`);
- cy.url().should(
- 'include',
- `returnUrl=${encodeURIComponent(
- 'https://m.code.dev-theguardian.com/',
- )}`,
- );
- const checkbox = cy.findByLabelText('Yes, sign me up');
- checkbox.should('not.be.checked');
+ it('allows user to opt out and continue', () => {
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress, finalPassword }) => {
+ const visitUrl = '/signin';
+ cy.visit(visitUrl);
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', `/signin/success`);
+ cy.url().should(
+ 'include',
+ `returnUrl=${encodeURIComponent(
+ 'https://m.code.dev-theguardian.com/',
+ )}`,
+ );
+ const checkbox = cy.findByLabelText('Yes, sign me up');
+ checkbox.should('not.be.checked');
- cy.findByText('Continue to the Guardian').click();
- cy.url().should('include', 'https://m.code.dev-theguardian.com/');
- });
- });
+ cy.findByText('Continue to the Guardian').click();
+ cy.url().should('include', 'https://m.code.dev-theguardian.com/');
+ });
+ });
- it("doesn't show the prompt if the user has already seen it", () => {
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress, finalPassword }) => {
- const returnUrl = `https://${Cypress.env(
- 'BASE_URI',
- )}/signout?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/signin`,
- )}`;
- const visitUrl = `/signin?returnUrl=${encodeURIComponent(returnUrl)}`;
- cy.visit(visitUrl);
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', `/signin/success`);
- cy.url().should(
- 'include',
- `returnUrl=${encodeURIComponent(
- 'https://m.code.dev-theguardian.com/',
- )}`,
- );
- const checkbox = cy.findByLabelText('Yes, sign me up');
- checkbox.should('not.be.checked');
- checkbox.click();
- checkbox.should('be.checked');
- cy.findByText('Continue to the Guardian').click();
- cy.url().should('include', 'https://m.code.dev-theguardian.com/');
- cy.visit(
- `/signout?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/signin`,
- )}`,
- );
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('not.include', `/signin/success`);
- cy.url().should('include', 'https://m.code.dev-theguardian.com/');
- });
- });
+ it("doesn't show the prompt if the user has already seen it", () => {
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress, finalPassword }) => {
+ const returnUrl = `https://${Cypress.env(
+ 'BASE_URI',
+ )}/signout?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/signin`,
+ )}`;
+ const visitUrl = `/signin?returnUrl=${encodeURIComponent(returnUrl)}`;
+ cy.visit(visitUrl);
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', `/signin/success`);
+ cy.url().should(
+ 'include',
+ `returnUrl=${encodeURIComponent(
+ 'https://m.code.dev-theguardian.com/',
+ )}`,
+ );
+ const checkbox = cy.findByLabelText('Yes, sign me up');
+ checkbox.should('not.be.checked');
+ checkbox.click();
+ checkbox.should('be.checked');
+ cy.findByText('Continue to the Guardian').click();
+ cy.url().should('include', 'https://m.code.dev-theguardian.com/');
+ cy.visit(
+ `/signout?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/signin`,
+ )}`,
+ );
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('not.include', `/signin/success`);
+ cy.url().should('include', 'https://m.code.dev-theguardian.com/');
+ });
+ });
});
diff --git a/cypress/integration/ete-okta/reauthenticate.4.cy.ts b/cypress/integration/ete-okta/reauthenticate.4.cy.ts
index 505d455c4a..d1d216f716 100644
--- a/cypress/integration/ete-okta/reauthenticate.4.cy.ts
+++ b/cypress/integration/ete-okta/reauthenticate.4.cy.ts
@@ -1,100 +1,100 @@
describe('Reauthenticate flow, Okta enabled', () => {
- beforeEach(() => {
- // Disable redirect to /signin/success by default
- cy.setCookie(
- 'GU_ran_experiments',
- new URLSearchParams({
- OptInPromptPostSignIn: Date.now().toString(),
- }).toString(),
- );
- });
- it('keeps User A signed in when User A attempts to reauthenticate', () => {
- cy
- .createTestUser({ isUserEmailValidated: true })
- ?.then(({ emailAddress, finalPassword }) => {
- // First, sign in
- cy.visit(
- `/signin?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/consents/data`,
- )}`,
- );
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', '/consents/data');
+ beforeEach(() => {
+ // Disable redirect to /signin/success by default
+ cy.setCookie(
+ 'GU_ran_experiments',
+ new URLSearchParams({
+ OptInPromptPostSignIn: Date.now().toString(),
+ }).toString(),
+ );
+ });
+ it('keeps User A signed in when User A attempts to reauthenticate', () => {
+ cy
+ .createTestUser({ isUserEmailValidated: true })
+ ?.then(({ emailAddress, finalPassword }) => {
+ // First, sign in
+ cy.visit(
+ `/signin?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/consents/data`,
+ )}`,
+ );
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', '/consents/data');
- // Then, try to reauthenticate
- cy.visit(
- `/reauthenticate?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/consents/data`,
- )}`,
- );
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', '/consents/data');
+ // Then, try to reauthenticate
+ cy.visit(
+ `/reauthenticate?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/consents/data`,
+ )}`,
+ );
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', '/consents/data');
- // Get the current session data
- cy.getCookie('sid').then((sidCookie) => {
- const sid = sidCookie?.value;
- expect(sid).to.exist;
- if (sid) {
- cy.getCurrentOktaSession(sid).then((session) => {
- expect(session.login).to.equal(emailAddress);
- });
- }
- });
- });
- });
- it('signs in User B when User B attempts to reauthenticate while User A is logged in', () => {
- // Create User A
- cy
- .createTestUser({ isUserEmailValidated: true })
- ?.then(
- ({ emailAddress: emailAddressA, finalPassword: finalPasswordA }) => {
- // First, sign in as User A
- cy.visit(
- `/signin?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/consents/data`,
- )}`,
- );
- cy.get('input[name=email]').type(emailAddressA);
- cy.get('input[name=password]').type(finalPasswordA);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', '/consents/data');
+ // Get the current session data
+ cy.getCookie('sid').then((sidCookie) => {
+ const sid = sidCookie?.value;
+ expect(sid).to.exist;
+ if (sid) {
+ cy.getCurrentOktaSession(sid).then((session) => {
+ expect(session.login).to.equal(emailAddress);
+ });
+ }
+ });
+ });
+ });
+ it('signs in User B when User B attempts to reauthenticate while User A is logged in', () => {
+ // Create User A
+ cy
+ .createTestUser({ isUserEmailValidated: true })
+ ?.then(
+ ({ emailAddress: emailAddressA, finalPassword: finalPasswordA }) => {
+ // First, sign in as User A
+ cy.visit(
+ `/signin?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/consents/data`,
+ )}`,
+ );
+ cy.get('input[name=email]').type(emailAddressA);
+ cy.get('input[name=password]').type(finalPasswordA);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', '/consents/data');
- // Create User B
- cy
- .createTestUser({ isUserEmailValidated: true })
- ?.then(
- ({
- emailAddress: emailAddressB,
- finalPassword: finalPasswordB,
- }) => {
- // Then, try to reauthenticate as User B
- cy.visit(
- `/reauthenticate?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/consents/data`,
- )}`,
- );
- cy.get('input[name=email]').type(emailAddressB);
- cy.get('input[name=password]').type(finalPasswordB);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', '/consents/data');
+ // Create User B
+ cy
+ .createTestUser({ isUserEmailValidated: true })
+ ?.then(
+ ({
+ emailAddress: emailAddressB,
+ finalPassword: finalPasswordB,
+ }) => {
+ // Then, try to reauthenticate as User B
+ cy.visit(
+ `/reauthenticate?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/consents/data`,
+ )}`,
+ );
+ cy.get('input[name=email]').type(emailAddressB);
+ cy.get('input[name=password]').type(finalPasswordB);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', '/consents/data');
- // Get the current session data
- cy.getCookie('sid').then((sidCookie) => {
- const sid = sidCookie?.value;
- expect(sid).to.exist;
- if (sid) {
- cy.getCurrentOktaSession(sid).then((session) => {
- expect(session.login).to.equal(emailAddressB);
- });
- }
- });
- },
- );
- },
- );
- });
+ // Get the current session data
+ cy.getCookie('sid').then((sidCookie) => {
+ const sid = sidCookie?.value;
+ expect(sid).to.exist;
+ if (sid) {
+ cy.getCurrentOktaSession(sid).then((session) => {
+ expect(session.login).to.equal(emailAddressB);
+ });
+ }
+ });
+ },
+ );
+ },
+ );
+ });
});
diff --git a/cypress/integration/ete-okta/registration.2.cy.ts b/cypress/integration/ete-okta/registration.2.cy.ts
index 0ef33fa912..08e3987a3e 100644
--- a/cypress/integration/ete-okta/registration.2.cy.ts
+++ b/cypress/integration/ete-okta/registration.2.cy.ts
@@ -1,1338 +1,1338 @@
import {
- randomMailosaurEmail,
- randomPassword,
+ randomMailosaurEmail,
+ randomPassword,
} from '../../support/commands/testUser';
import { Status } from '../../../src/server/models/okta/User';
describe('Registration flow', () => {
- context('Registering with Okta', () => {
- it('successfully registers using an email with no existing account', () => {
- const encodedReturnUrl =
- 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
- const unregisteredEmail = randomMailosaurEmail();
- const encodedRef = 'https%3A%2F%2Fm.theguardian.com';
- const refViewId = 'testRefViewId';
- const clientId = 'jobs';
-
- // these params should *not* persist between initial registration and welcome page
- // despite the fact that they PersistableQueryParams, as these are set by the Okta SDK sign in method
- // and subsequent interception, and not by gateway
- const appClientId = 'appClientId1';
- const fromURI = 'fromURI1';
-
- cy.visit(
- `/register?returnUrl=${encodedReturnUrl}&ref=${encodedRef}&refViewId=${refViewId}&clientId=${clientId}&appClientId=${appClientId}&fromURI=${fromURI}`,
- );
-
- const timeRequestWasMade = new Date();
- cy.get('input[name=email]').type(unregisteredEmail);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(unregisteredEmail);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- unregisteredEmail,
- timeRequestWasMade,
- /welcome\/([^"]*)/,
- ).then(({ body, token }) => {
- expect(body).to.have.string('Complete registration');
- cy.visit(`/welcome/${token}`);
- cy.contains('Save and continue');
-
- cy.get('form')
- .should('have.attr', 'action')
- .and('match', new RegExp(encodedReturnUrl))
- .and('match', new RegExp(refViewId))
- .and('match', new RegExp(encodedRef))
- .and('match', new RegExp(clientId))
- .and('not.match', new RegExp(appClientId))
- .and('not.match', new RegExp(fromURI));
-
- //we are reloading here to make sure the params are persisted even on page refresh
- cy.reload();
-
- cy.get('input[name="firstName"]').type('First Name');
- cy.get('input[name="secondName"]').type('Last Name');
- cy.get('input[name="password"]').type(randomPassword());
- cy.get('button[type="submit"]').click();
- cy.url().should('contain', encodedReturnUrl);
- cy.url().should('contain', refViewId);
- cy.url().should('contain', encodedRef);
- cy.url().should('contain', clientId);
- cy.url().should('not.contain', appClientId);
- cy.url().should('not.contain', fromURI);
- });
- });
-
- it('successfully registers using an email with no existing account, and has a prefixed activation token when using a native app', () => {
- const encodedReturnUrl =
- 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
- const unregisteredEmail = randomMailosaurEmail();
- const encodedRef = 'https%3A%2F%2Fm.theguardian.com';
- const refViewId = 'testRefViewId';
- const clientId = 'jobs';
-
- // these params should *not* persist between initial registration and welcome page
- // despite the fact that they PersistableQueryParams, as these are set by the Okta SDK sign in method
- // and subsequent interception, and not by gateway
- const appClientId = Cypress.env('OKTA_ANDROID_CLIENT_ID');
- const fromURI = 'fromURI1';
-
- cy.visit(
- `/register?returnUrl=${encodedReturnUrl}&ref=${encodedRef}&refViewId=${refViewId}&clientId=${clientId}&appClientId=${appClientId}&fromURI=${fromURI}`,
- );
-
- const timeRequestWasMade = new Date();
- cy.get('input[name=email]').type(unregisteredEmail);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(unregisteredEmail);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- unregisteredEmail,
- timeRequestWasMade,
- /welcome\/([^"]*)/,
- ).then(({ body, token }) => {
- expect(body).to.have.string('Complete registration');
- expect(token).to.have.string('al_');
- cy.visit(`/welcome/${token}`);
- cy.contains('Save and continue');
-
- cy.get('form')
- .should('have.attr', 'action')
- .and('match', new RegExp(encodedReturnUrl))
- .and('match', new RegExp(refViewId))
- .and('match', new RegExp(encodedRef))
- .and('match', new RegExp(clientId))
- .and('not.match', new RegExp(appClientId))
- .and('not.match', new RegExp(fromURI));
-
- //we are reloading here to make sure the params are persisted even on page refresh
- cy.reload();
-
- cy.get('input[name="firstName"]').type('First Name');
- cy.get('input[name="secondName"]').type('Last Name');
- cy.get('input[name="password"]').type(randomPassword());
- cy.get('button[type="submit"]').click();
- cy.url().should('contain', encodedReturnUrl);
- cy.url().should('contain', refViewId);
- cy.url().should('contain', encodedRef);
- cy.url().should('contain', clientId);
- cy.url().should('not.contain', appClientId);
- cy.url().should('not.contain', fromURI);
- });
- });
-
- it('does not register registrationLocation for email with no existing account if cmp is not consented', () => {
- const unregisteredEmail = randomMailosaurEmail();
- cy.enableCMP();
- cy.visit(`/register`);
- cy.setCookie('GU_geo_country', 'FR');
- cy.declineCMP();
-
- cy.get('input[name=email]').type(unregisteredEmail);
- cy.get('input[name=_cmpConsentedState]').should('have.value', 'false');
-
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.intercept('POST', '/register**', (req) => {
- expect(req.body).to.include('_cmpConsentedState=false');
- expect(req.headers.cookie).to.include('GU_geo_country=FR');
- });
- });
-
- it('successfully registers registrationLocation for email with no existing account if cmp consented', () => {
- const unregisteredEmail = randomMailosaurEmail();
- cy.enableCMP();
- cy.visit(`/register`);
- cy.setCookie('GU_geo_country', 'FR');
- cy.acceptCMP();
-
- cy.get('input[name=email]').type(unregisteredEmail);
- cy.get('input[name=_cmpConsentedState]').should('have.value', 'true');
-
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.intercept('POST', '/register**', (req) => {
- expect(req.body).to.include('_cmpConsentedState=true');
- expect(req.headers.cookie).to.include('GU_geo_country=FR');
- });
- });
-
- it('successfully blocks the password set page /welcome if a password has already been set', () => {
- const unregisteredEmail = randomMailosaurEmail();
- cy.visit(`/register`);
-
- const timeRequestWasMade = new Date();
- cy.get('input[name=email]').type(unregisteredEmail);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(unregisteredEmail);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- unregisteredEmail,
- timeRequestWasMade,
- /welcome\/([^"]*)/,
- ).then(({ body, token }) => {
- expect(body).to.have.string('Complete registration');
- cy.visit(`/welcome/${token}`);
- cy.contains('Save and continue');
-
- cy.get('input[name="password"]').type(randomPassword());
- cy.get('button[type="submit"]').click();
- cy.url().should('contain', '/consents/');
- cy.go('back');
- cy.url().should('contain', '/welcome/');
- cy.contains('Password already set for');
- });
- });
-
- it('completes registration and overrides returnUrl from encryptedStateCookie if one set on welcome page url', () => {
- const encodedReturnUrl =
- 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
- const unregisteredEmail = randomMailosaurEmail();
-
- cy.visit(`/register?returnUrl=${encodedReturnUrl}`);
-
- const timeRequestWasMade = new Date();
- cy.get('input[name=email]').type(unregisteredEmail);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(unregisteredEmail);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- unregisteredEmail,
- timeRequestWasMade,
- /welcome\/([^"]*)/,
- ).then(({ body, token }) => {
- expect(body).to.have.string('Complete registration');
- const newReturnUrl = encodeURIComponent(
- 'https://www.theguardian.com/technology/2017/may/04/nier-automata-sci-fi-game-sleeper-hit-designer-yoko-taro',
- );
- cy.visit(`/welcome/${token}?returnUrl=${newReturnUrl}`);
- cy.contains('Save and continue');
- cy.url()
- .should('contain', newReturnUrl)
- .and('not.contain', encodedReturnUrl);
-
- cy.get('form')
- .should('have.attr', 'action')
- .and('match', new RegExp(newReturnUrl))
- .and('not.match', new RegExp(encodedReturnUrl));
-
- //we are reloading here to make sure the params are persisted even on page refresh
- cy.reload();
-
- cy.get('input[name="password"]').type(randomPassword());
- cy.get('button[type="submit"]').click();
- cy.url()
- .should('contain', newReturnUrl)
- .and('not.contain', encodedReturnUrl);
- });
- });
-
- it('overrides appClientId and fromURI if set on activation link', () => {
- const encodedReturnUrl =
- 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
- const unregisteredEmail = randomMailosaurEmail();
-
- // these params should *not* persist between initial registration and welcome page
- // despite the fact that they PersistableQueryParams, as these are set by the Okta SDK sign in method
- // and subsequent interception, and not by gateway
- const appClientId1 = 'appClientId1';
- const fromURI1 = 'fromURI1';
-
- cy.visit(
- `/register?returnUrl=${encodedReturnUrl}&appClientId=${appClientId1}&fromURI=${fromURI1}`,
- );
-
- const timeRequestWasMade = new Date();
- cy.get('input[name=email]').type(unregisteredEmail);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(unregisteredEmail);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- unregisteredEmail,
- timeRequestWasMade,
- /welcome\/([^"]*)/,
- ).then(({ body, token }) => {
- expect(body).to.have.string('Complete registration');
- // should contain these params instead
- const appClientId2 = 'appClientId2';
- const fromURI2 = 'fromURI2';
- cy.visit(
- `/welcome/${token}?appClientId=${appClientId2}&fromURI=${fromURI2}`,
- );
- cy.contains('Save and continue');
- cy.url()
- .should('contain', appClientId2)
- .and('contain', fromURI2)
- .and('not.contain', appClientId1)
- .and('not.contain', fromURI1);
-
- cy.get('form')
- .should('have.attr', 'action')
- .and('match', new RegExp(appClientId2))
- .and('match', new RegExp(fromURI2))
- .and('not.match', new RegExp(appClientId1))
- .and('not.match', new RegExp(fromURI1));
- });
- });
- });
- context('Existing users attempting to register with Okta', () => {
- it('should send a STAGED user a set password email with an Okta activation token', () => {
- // Test users created via IDAPI-with-Okta do not have the activation
- // lifecycle run at creation, so they don't transition immediately from
- // STAGED to PROVISIONED (c.f.
- // https://developer.okta.com/docs/reference/api/users/#create-user) .
- // This is useful for us as we can test STAGED users first, then test
- // PROVISIONED users in the next test by activating a STAGED user. Users
- // created through Gateway-with-Okta do have this lifecycle run, so if we
- // rebuild these tests to not use IDAPI at all, we need to figure out a
- // way to test STAGED and PROVISIONED users (probably by just passing an
- // optional `activate` prop to a createUser function).
- cy
- .createTestUser({
- isGuestUser: true,
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.STAGED);
-
- cy.visit('/register');
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /\/set-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('This account already exists');
-
- expect(body).to.have.string('Create password');
- expect(links.length).to.eq(2);
- const setPasswordLink = links.find(
- (s) => s.text?.includes('Create password'),
- );
- expect(setPasswordLink?.href).not.to.have.string('useOkta=true');
- cy.visit(setPasswordLink?.href as string);
- cy.contains('Create password');
- cy.contains(emailAddress);
- });
- });
- });
- });
-
- it('should send a STAGED user a set password email with an Okta activation token, and has a prefixed activation token when using a native app', () => {
- // Test users created via IDAPI-with-Okta do not have the activation
- // lifecycle run at creation, so they don't transition immediately from
- // STAGED to PROVISIONED (c.f.
- // https://developer.okta.com/docs/reference/api/users/#create-user) .
- // This is useful for us as we can test STAGED users first, then test
- // PROVISIONED users in the next test by activating a STAGED user. Users
- // created through Gateway-with-Okta do have this lifecycle run, so if we
- // rebuild these tests to not use IDAPI at all, we need to figure out a
- // way to test STAGED and PROVISIONED users (probably by just passing an
- // optional `activate` prop to a createUser function).
- cy
- .createTestUser({
- isGuestUser: true,
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.STAGED);
-
- const appClientId = Cypress.env('OKTA_ANDROID_CLIENT_ID');
- const fromURI = 'fromURI1';
-
- cy.visit(`/register?appClientId=${appClientId}&fromURI=${fromURI}`);
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /\/set-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('This account already exists');
-
- expect(body).to.have.string('Create password');
- expect(links.length).to.eq(2);
- const setPasswordLink = links.find(
- (s) => s.text?.includes('Create password'),
- );
- expect(setPasswordLink?.href ?? '')
- .to.have.string('al_')
- .and.not.to.have.string('useOkta=true');
- cy.visit(setPasswordLink?.href as string);
- cy.contains('Create password');
- cy.contains(emailAddress);
- });
- });
- });
- });
-
- it('should send a PROVISIONED user a set password email with an Okta activation token', () => {
- cy
- .createTestUser({
- isGuestUser: true,
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.activateTestOktaUser(emailAddress).then(() => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.PROVISIONED);
-
- cy.visit('/register');
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /\/set-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('This account already exists');
- expect(body).to.have.string('Create password');
- expect(links.length).to.eq(2);
- const setPasswordLink = links.find(
- (s) => s.text?.includes('Create password'),
- );
- expect(setPasswordLink?.href).not.to.have.string(
- 'useOkta=true',
- );
- cy.visit(setPasswordLink?.href as string);
- cy.contains('Create password');
- cy.contains(emailAddress);
- });
- });
- });
- });
- });
- it('should send an ACTIVE UNvalidated user with a password a security email with activation token', () => {
- cy
- .createTestUser({
- isGuestUser: false,
- isUserEmailValidated: false,
- })
- ?.then(({ emailAddress }) => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.ACTIVE);
-
- cy.visit('/register');
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- // Make sure that we don't get sent to the 'security reasons' page
- cy.url().should('include', '/register/email-sent');
- cy.contains(
- 'For security reasons we need you to change your password.',
- ).should('not.exist');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string(
- 'Because your security is extremely important to us, we have changed our password policy.',
- );
- expect(body).to.have.string('Reset password');
- expect(links.length).to.eq(2);
- const resetPasswordLink = links.find(
- (s) => s.text?.includes('Reset password'),
- );
- cy.visit(resetPasswordLink?.href as string);
- cy.contains(emailAddress);
- cy.contains('Reset password');
- });
- });
- });
- });
- it('should send an ACTIVE validated user WITH a password a reset password email with an activation token', () => {
- cy
- .createTestUser({
- isGuestUser: false,
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.ACTIVE);
-
- cy.visit('/register');
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('This account already exists');
- expect(body).to.have.string('Sign in');
- expect(body).to.have.string('Reset password');
- expect(links.length).to.eq(3);
- const resetPasswordLink = links.find(
- (s) => s.text?.includes('Reset password'),
- );
- expect(resetPasswordLink?.href ?? '').not.to.have.string(
- 'useOkta=true',
- );
- cy.visit(resetPasswordLink?.href as string);
- cy.contains(emailAddress);
- cy.contains('Reset password');
- });
- });
- });
- });
- it('should send an ACTIVE validated user WITH a password a reset password email with an activation token, and prefixed activation token if using native app', () => {
- cy
- .createTestUser({
- isGuestUser: false,
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.ACTIVE);
-
- const appClientId = Cypress.env('OKTA_ANDROID_CLIENT_ID');
- const fromURI = 'fromURI1';
-
- cy.visit(`/register?appClientId=${appClientId}&fromURI=${fromURI}`);
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('This account already exists');
- expect(body).to.have.string('Sign in');
- expect(body).to.have.string('Reset password');
- expect(links.length).to.eq(3);
- const resetPasswordLink = links.find(
- (s) => s.text?.includes('Reset password'),
- );
- expect(resetPasswordLink?.href ?? '')
- .to.have.string('al_')
- .and.not.to.have.string('useOkta=true');
- cy.visit(resetPasswordLink?.href as string);
- cy.contains(emailAddress);
- cy.contains('Reset password');
- });
- });
- });
- });
- it('should send a RECOVERY user a reset password email with an Okta activation token', () => {
- cy
- .createTestUser({
- isGuestUser: false,
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.resetOktaUserPassword(emailAddress).then(() => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.RECOVERY);
-
- cy.visit('/register');
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('Password reset');
- expect(body).to.have.string('Reset password');
- expect(links.length).to.eq(2);
- const resetPasswordLink = links.find(
- (s) => s.text?.includes('Reset password'),
- );
- expect(resetPasswordLink?.href ?? '').not.to.have.string(
- 'useOkta=true',
- );
- cy.visit(resetPasswordLink?.href as string);
- cy.contains('Reset password');
- cy.contains(emailAddress);
- });
- });
- });
- });
- });
- it('should send a PASSWORD_EXPIRED user a reset password email with an Okta activation token', () => {
- cy
- .createTestUser({
- isGuestUser: false,
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.expireOktaUserPassword(emailAddress).then(() => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.PASSWORD_EXPIRED);
-
- cy.visit('/register');
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('Password reset');
- expect(body).to.have.string('Reset password');
- expect(links.length).to.eq(2);
- const resetPasswordLink = links.find(
- (s) => s.text?.includes('Reset password'),
- );
- expect(resetPasswordLink?.href ?? '').not.to.have.string(
- 'useOkta=true',
- );
- cy.visit(resetPasswordLink?.href as string);
- cy.contains('Reset password');
- cy.contains(emailAddress);
- });
- });
- });
- });
- });
- it('should display an error if a SUSPENDED user attempts to register', () => {
- cy
- .createTestUser({
- isGuestUser: false,
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.suspendOktaUser(emailAddress).then(() => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.SUSPENDED);
-
- cy.visit('/register');
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('There was a problem registering, please try again.');
- });
- });
- });
- });
- });
-
- context(
- 'Existing users asking for an email to be resent after attempting to register with Okta',
- () => {
- it('should resend a STAGED user a set password email with an Okta activation token', () => {
- cy
- .createTestUser({
- isGuestUser: true,
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.STAGED);
-
- cy.visit('/register');
-
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- // Wait for the first email to arrive...
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /\/set-password\/([^"]*)/,
- ).then(() => {
- const timeRequestWasMade = new Date();
-
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- // ...before waiting for the second email to arrive
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /\/set-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('This account already exists');
- expect(body).to.have.string('Create password');
- expect(links.length).to.eq(2);
- const setPasswordLink = links.find(
- (s) => s.text?.includes('Create password'),
- );
- expect(setPasswordLink?.href ?? '').not.to.have.string(
- 'useOkta=true',
- );
- cy.visit(setPasswordLink?.href as string);
- cy.contains('Create password');
- cy.contains(emailAddress);
- });
- });
- });
- });
- });
-
- it('should resend a PROVISIONED user a set password email with an Okta activation token', () => {
- cy
- .createTestUser({
- isGuestUser: true,
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.activateTestOktaUser(emailAddress).then(() => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.PROVISIONED);
-
- cy.visit('/register');
-
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /\/set-password\/([^"]*)/,
- ).then(() => {
- const timeRequestWasMade = new Date();
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /\/set-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('This account already exists');
- expect(body).to.have.string('Create password');
- expect(links.length).to.eq(2);
- const setPasswordLink = links.find(
- (s) => s.text?.includes('Create password'),
- );
- expect(setPasswordLink?.href ?? '').not.to.have.string(
- 'useOkta=true',
- );
- cy.visit(setPasswordLink?.href as string);
- cy.contains('Create password');
- cy.contains(emailAddress);
- });
- });
- });
- });
- });
- });
- it('should send an ACTIVE user a reset password email with an Okta activation token', () => {
- cy
- .createTestUser({
- isGuestUser: false,
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.ACTIVE);
-
- cy.visit('/register');
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- ).then(() => {
- const timeRequestWasMade = new Date();
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('This account already exists');
- expect(body).to.have.string('Sign in');
- expect(body).to.have.string('Reset password');
- expect(links.length).to.eq(3);
- const resetPasswordLink = links.find(
- (s) => s.text?.includes('Reset password'),
- );
- expect(resetPasswordLink?.href ?? '').not.to.have.string(
- 'useOkta=true',
- );
- cy.visit(resetPasswordLink?.href as string);
- cy.contains('Reset password');
- cy.contains(emailAddress);
- });
- });
- });
- });
- });
- it('should send a RECOVERY user a reset password email with an Okta activation token', () => {
- cy
- .createTestUser({
- isGuestUser: false,
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.resetOktaUserPassword(emailAddress).then(() => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.RECOVERY);
-
- cy.visit('/register');
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(() => {
- const timeRequestWasMade = new Date();
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('Password reset');
- expect(body).to.have.string('Reset password');
- expect(links.length).to.eq(2);
- const resetPasswordLink = links.find(
- (s) => s.text?.includes('Reset password'),
- );
- expect(resetPasswordLink?.href ?? '').not.to.have.string(
- 'useOkta=true',
- );
- cy.visit(resetPasswordLink?.href as string);
- cy.contains('Reset password');
- cy.contains(emailAddress);
- });
- });
- });
- });
- });
- });
- it('should send a PASSWORD_EXPIRED user a reset password email with an Okta activation token', () => {
- cy
- .createTestUser({
- isGuestUser: false,
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.expireOktaUserPassword(emailAddress).then(() => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.PASSWORD_EXPIRED);
-
- cy.visit('/register');
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(() => {
- const timeRequestWasMade = new Date();
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('Password reset');
- expect(body).to.have.string('Reset password');
- expect(links.length).to.eq(2);
- const resetPasswordLink = links.find(
- (s) => s.text?.includes('Reset password'),
- );
- expect(resetPasswordLink?.href ?? '').not.to.have.string(
- 'useOkta=true',
- );
- cy.visit(resetPasswordLink?.href as string);
- cy.contains('Reset password');
- cy.contains(emailAddress);
- });
- });
- });
- });
- });
- });
- },
- );
-
- context('Welcome Page - Resend (Link expired)', () => {
- it('send an email for user with no existing account', () => {
- const encodedReturnUrl =
- 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
- const unregisteredEmail = randomMailosaurEmail();
-
- cy.visit(`/welcome/resend?returnUrl=${encodedReturnUrl}`);
-
- const timeRequestWasMade = new Date();
- cy.get('input[name=email]').type(unregisteredEmail);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(unregisteredEmail);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- unregisteredEmail,
- timeRequestWasMade,
- /welcome\/([^"]*)/,
- ).then(({ body, token }) => {
- expect(body).to.have.string('Complete registration');
- cy.visit(`/welcome/${token}`);
- cy.contains('Save and continue');
-
- cy.get('form')
- .should('have.attr', 'action')
- .and('match', new RegExp(encodedReturnUrl));
-
- //we are reloading here to make sure the params are persisted even on page refresh
- cy.reload();
-
- cy.get('input[name="password"]').type(randomPassword());
- cy.get('button[type="submit"]').click();
- cy.url().should('contain', encodedReturnUrl);
- });
- });
-
- it('should resend a STAGED user a set password email with an Okta activation token', () => {
- cy
- .createTestUser({
- isGuestUser: true,
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.STAGED);
-
- cy.visit('/welcome/resend');
-
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- // Wait for the first email to arrive...
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /\/set-password\/([^"]*)/,
- ).then(() => {
- const timeRequestWasMade = new Date();
-
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- // ...before waiting for the second email to arrive
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /\/set-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('This account already exists');
- expect(body).to.have.string('Create password');
- expect(links.length).to.eq(2);
- const setPasswordLink = links.find(
- (s) => s.text?.includes('Create password'),
- );
- expect(setPasswordLink?.href ?? '').not.to.have.string(
- 'useOkta=true',
- );
- cy.visit(setPasswordLink?.href as string);
- cy.contains('Create password');
- cy.contains(emailAddress);
- });
- });
- });
- });
- });
- it('should resend a PROVISIONED user a set password email with an Okta activation token', () => {
- cy
- .createTestUser({
- isGuestUser: true,
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.activateTestOktaUser(emailAddress).then(() => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.PROVISIONED);
-
- cy.visit('/welcome/resend');
-
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /\/set-password\/([^"]*)/,
- ).then(() => {
- const timeRequestWasMade = new Date();
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /\/set-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('This account already exists');
- expect(body).to.have.string('Create password');
- expect(links.length).to.eq(2);
- const setPasswordLink = links.find(
- (s) => s.text?.includes('Create password'),
- );
- expect(setPasswordLink?.href ?? '').not.to.have.string(
- 'useOkta=true',
- );
- cy.visit(setPasswordLink?.href as string);
- cy.contains('Create password');
- cy.contains(emailAddress);
- });
- });
- });
- });
- });
- });
- it('should send an ACTIVE user a reset password email with an activation token', () => {
- cy
- .createTestUser({
- isGuestUser: false,
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.ACTIVE);
-
- cy.visit('/welcome/resend');
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- ).then(() => {
- const timeRequestWasMade = new Date();
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('This account already exists');
- expect(body).to.have.string('Sign in');
- expect(body).to.have.string('Reset password');
- expect(links.length).to.eq(3);
- const resetPasswordLink = links.find(
- (s) => s.text?.includes('Reset password'),
- );
- expect(resetPasswordLink?.href ?? '').not.to.have.string(
- 'useOkta=true',
- );
- cy.visit(resetPasswordLink?.href as string);
- cy.contains('Reset password');
- cy.contains(emailAddress);
- });
- });
- });
- });
- });
- it('should send a RECOVERY user a reset password email with an Okta activation token', () => {
- cy
- .createTestUser({
- isGuestUser: false,
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.resetOktaUserPassword(emailAddress).then(() => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.RECOVERY);
-
- cy.visit('/welcome/resend');
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(() => {
- const timeRequestWasMade = new Date();
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('Password reset');
- expect(body).to.have.string('Reset password');
- expect(links.length).to.eq(2);
- const resetPasswordLink = links.find(
- (s) => s.text?.includes('Reset password'),
- );
- expect(resetPasswordLink?.href ?? '').not.to.have.string(
- 'useOkta=true',
- );
- cy.visit(resetPasswordLink?.href as string);
- cy.contains('Reset password');
- cy.contains(emailAddress);
- });
- });
- });
- });
- });
- });
- it('should send a PASSWORD_EXPIRED user a reset password email with an Okta activation token', () => {
- cy
- .createTestUser({
- isGuestUser: false,
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.expireOktaUserPassword(emailAddress).then(() => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.PASSWORD_EXPIRED);
-
- cy.visit('/welcome/resend');
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(() => {
- const timeRequestWasMade = new Date();
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('Password reset');
- expect(body).to.have.string('Reset password');
- expect(links.length).to.eq(2);
- const resetPasswordLink = links.find(
- (s) => s.text?.includes('Reset password'),
- );
- expect(resetPasswordLink?.href ?? '').not.to.have.string(
- 'useOkta=true',
- );
- cy.visit(resetPasswordLink?.href as string);
- cy.contains('Reset password');
- cy.contains(emailAddress);
- });
- });
- });
- });
- });
- });
- });
-
- context('Okta session exists on /signin', () => {
- beforeEach(() => {
- // Disable redirect to /signin/success by default
- cy.setCookie(
- 'GU_ran_experiments',
- new URLSearchParams({
- OptInPromptPostSignIn: Date.now().toString(),
- }).toString(),
- );
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', 'https://m.code.dev-theguardian.com/', (req) => {
- req.reply(200);
- });
- });
-
- it('shows the signed in as page', () => {
- // Create a validated test user
- cy.createTestUser({ isUserEmailValidated: true }).then(
- ({ emailAddress, finalPassword }) => {
- // Sign our new user in
- cy.visit(
- `/signin?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/consents`,
- )}`,
- );
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', '/consents');
-
- // Get the current session data
- cy.getCookie('sid').then((originalSidCookie) => {
- expect(originalSidCookie).to.exist;
-
- // Visit register again
- cy.visit(
- `/register?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/consents`,
- )}`,
- );
- cy.url().should('include', '/register');
-
- cy.contains('Sign in to the Guardian');
- cy.contains('You are signed in with');
- cy.contains(emailAddress);
- cy.contains('Continue')
- .should('have.attr', 'href')
- .and(
- 'include',
- `https://${Cypress.env(
- 'BASE_URI',
- )}/signin/refresh?returnUrl=https%3A%2F%2Fprofile.thegulocal.com%2Fconsents`,
- );
- cy.contains('a', 'Sign in')
- .should('have.attr', 'href')
- .and('include', '/signout?returnUrl=');
- cy.contains('Sign in with a different email');
- });
- },
- );
- });
- });
+ context('Registering with Okta', () => {
+ it('successfully registers using an email with no existing account', () => {
+ const encodedReturnUrl =
+ 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
+ const unregisteredEmail = randomMailosaurEmail();
+ const encodedRef = 'https%3A%2F%2Fm.theguardian.com';
+ const refViewId = 'testRefViewId';
+ const clientId = 'jobs';
+
+ // these params should *not* persist between initial registration and welcome page
+ // despite the fact that they PersistableQueryParams, as these are set by the Okta SDK sign in method
+ // and subsequent interception, and not by gateway
+ const appClientId = 'appClientId1';
+ const fromURI = 'fromURI1';
+
+ cy.visit(
+ `/register?returnUrl=${encodedReturnUrl}&ref=${encodedRef}&refViewId=${refViewId}&clientId=${clientId}&appClientId=${appClientId}&fromURI=${fromURI}`,
+ );
+
+ const timeRequestWasMade = new Date();
+ cy.get('input[name=email]').type(unregisteredEmail);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(unregisteredEmail);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ unregisteredEmail,
+ timeRequestWasMade,
+ /welcome\/([^"]*)/,
+ ).then(({ body, token }) => {
+ expect(body).to.have.string('Complete registration');
+ cy.visit(`/welcome/${token}`);
+ cy.contains('Save and continue');
+
+ cy.get('form')
+ .should('have.attr', 'action')
+ .and('match', new RegExp(encodedReturnUrl))
+ .and('match', new RegExp(refViewId))
+ .and('match', new RegExp(encodedRef))
+ .and('match', new RegExp(clientId))
+ .and('not.match', new RegExp(appClientId))
+ .and('not.match', new RegExp(fromURI));
+
+ //we are reloading here to make sure the params are persisted even on page refresh
+ cy.reload();
+
+ cy.get('input[name="firstName"]').type('First Name');
+ cy.get('input[name="secondName"]').type('Last Name');
+ cy.get('input[name="password"]').type(randomPassword());
+ cy.get('button[type="submit"]').click();
+ cy.url().should('contain', encodedReturnUrl);
+ cy.url().should('contain', refViewId);
+ cy.url().should('contain', encodedRef);
+ cy.url().should('contain', clientId);
+ cy.url().should('not.contain', appClientId);
+ cy.url().should('not.contain', fromURI);
+ });
+ });
+
+ it('successfully registers using an email with no existing account, and has a prefixed activation token when using a native app', () => {
+ const encodedReturnUrl =
+ 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
+ const unregisteredEmail = randomMailosaurEmail();
+ const encodedRef = 'https%3A%2F%2Fm.theguardian.com';
+ const refViewId = 'testRefViewId';
+ const clientId = 'jobs';
+
+ // these params should *not* persist between initial registration and welcome page
+ // despite the fact that they PersistableQueryParams, as these are set by the Okta SDK sign in method
+ // and subsequent interception, and not by gateway
+ const appClientId = Cypress.env('OKTA_ANDROID_CLIENT_ID');
+ const fromURI = 'fromURI1';
+
+ cy.visit(
+ `/register?returnUrl=${encodedReturnUrl}&ref=${encodedRef}&refViewId=${refViewId}&clientId=${clientId}&appClientId=${appClientId}&fromURI=${fromURI}`,
+ );
+
+ const timeRequestWasMade = new Date();
+ cy.get('input[name=email]').type(unregisteredEmail);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(unregisteredEmail);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ unregisteredEmail,
+ timeRequestWasMade,
+ /welcome\/([^"]*)/,
+ ).then(({ body, token }) => {
+ expect(body).to.have.string('Complete registration');
+ expect(token).to.have.string('al_');
+ cy.visit(`/welcome/${token}`);
+ cy.contains('Save and continue');
+
+ cy.get('form')
+ .should('have.attr', 'action')
+ .and('match', new RegExp(encodedReturnUrl))
+ .and('match', new RegExp(refViewId))
+ .and('match', new RegExp(encodedRef))
+ .and('match', new RegExp(clientId))
+ .and('not.match', new RegExp(appClientId))
+ .and('not.match', new RegExp(fromURI));
+
+ //we are reloading here to make sure the params are persisted even on page refresh
+ cy.reload();
+
+ cy.get('input[name="firstName"]').type('First Name');
+ cy.get('input[name="secondName"]').type('Last Name');
+ cy.get('input[name="password"]').type(randomPassword());
+ cy.get('button[type="submit"]').click();
+ cy.url().should('contain', encodedReturnUrl);
+ cy.url().should('contain', refViewId);
+ cy.url().should('contain', encodedRef);
+ cy.url().should('contain', clientId);
+ cy.url().should('not.contain', appClientId);
+ cy.url().should('not.contain', fromURI);
+ });
+ });
+
+ it('does not register registrationLocation for email with no existing account if cmp is not consented', () => {
+ const unregisteredEmail = randomMailosaurEmail();
+ cy.enableCMP();
+ cy.visit(`/register`);
+ cy.setCookie('GU_geo_country', 'FR');
+ cy.declineCMP();
+
+ cy.get('input[name=email]').type(unregisteredEmail);
+ cy.get('input[name=_cmpConsentedState]').should('have.value', 'false');
+
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.intercept('POST', '/register**', (req) => {
+ expect(req.body).to.include('_cmpConsentedState=false');
+ expect(req.headers.cookie).to.include('GU_geo_country=FR');
+ });
+ });
+
+ it('successfully registers registrationLocation for email with no existing account if cmp consented', () => {
+ const unregisteredEmail = randomMailosaurEmail();
+ cy.enableCMP();
+ cy.visit(`/register`);
+ cy.setCookie('GU_geo_country', 'FR');
+ cy.acceptCMP();
+
+ cy.get('input[name=email]').type(unregisteredEmail);
+ cy.get('input[name=_cmpConsentedState]').should('have.value', 'true');
+
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.intercept('POST', '/register**', (req) => {
+ expect(req.body).to.include('_cmpConsentedState=true');
+ expect(req.headers.cookie).to.include('GU_geo_country=FR');
+ });
+ });
+
+ it('successfully blocks the password set page /welcome if a password has already been set', () => {
+ const unregisteredEmail = randomMailosaurEmail();
+ cy.visit(`/register`);
+
+ const timeRequestWasMade = new Date();
+ cy.get('input[name=email]').type(unregisteredEmail);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(unregisteredEmail);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ unregisteredEmail,
+ timeRequestWasMade,
+ /welcome\/([^"]*)/,
+ ).then(({ body, token }) => {
+ expect(body).to.have.string('Complete registration');
+ cy.visit(`/welcome/${token}`);
+ cy.contains('Save and continue');
+
+ cy.get('input[name="password"]').type(randomPassword());
+ cy.get('button[type="submit"]').click();
+ cy.url().should('contain', '/consents/');
+ cy.go('back');
+ cy.url().should('contain', '/welcome/');
+ cy.contains('Password already set for');
+ });
+ });
+
+ it('completes registration and overrides returnUrl from encryptedStateCookie if one set on welcome page url', () => {
+ const encodedReturnUrl =
+ 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
+ const unregisteredEmail = randomMailosaurEmail();
+
+ cy.visit(`/register?returnUrl=${encodedReturnUrl}`);
+
+ const timeRequestWasMade = new Date();
+ cy.get('input[name=email]').type(unregisteredEmail);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(unregisteredEmail);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ unregisteredEmail,
+ timeRequestWasMade,
+ /welcome\/([^"]*)/,
+ ).then(({ body, token }) => {
+ expect(body).to.have.string('Complete registration');
+ const newReturnUrl = encodeURIComponent(
+ 'https://www.theguardian.com/technology/2017/may/04/nier-automata-sci-fi-game-sleeper-hit-designer-yoko-taro',
+ );
+ cy.visit(`/welcome/${token}?returnUrl=${newReturnUrl}`);
+ cy.contains('Save and continue');
+ cy.url()
+ .should('contain', newReturnUrl)
+ .and('not.contain', encodedReturnUrl);
+
+ cy.get('form')
+ .should('have.attr', 'action')
+ .and('match', new RegExp(newReturnUrl))
+ .and('not.match', new RegExp(encodedReturnUrl));
+
+ //we are reloading here to make sure the params are persisted even on page refresh
+ cy.reload();
+
+ cy.get('input[name="password"]').type(randomPassword());
+ cy.get('button[type="submit"]').click();
+ cy.url()
+ .should('contain', newReturnUrl)
+ .and('not.contain', encodedReturnUrl);
+ });
+ });
+
+ it('overrides appClientId and fromURI if set on activation link', () => {
+ const encodedReturnUrl =
+ 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
+ const unregisteredEmail = randomMailosaurEmail();
+
+ // these params should *not* persist between initial registration and welcome page
+ // despite the fact that they PersistableQueryParams, as these are set by the Okta SDK sign in method
+ // and subsequent interception, and not by gateway
+ const appClientId1 = 'appClientId1';
+ const fromURI1 = 'fromURI1';
+
+ cy.visit(
+ `/register?returnUrl=${encodedReturnUrl}&appClientId=${appClientId1}&fromURI=${fromURI1}`,
+ );
+
+ const timeRequestWasMade = new Date();
+ cy.get('input[name=email]').type(unregisteredEmail);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(unregisteredEmail);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ unregisteredEmail,
+ timeRequestWasMade,
+ /welcome\/([^"]*)/,
+ ).then(({ body, token }) => {
+ expect(body).to.have.string('Complete registration');
+ // should contain these params instead
+ const appClientId2 = 'appClientId2';
+ const fromURI2 = 'fromURI2';
+ cy.visit(
+ `/welcome/${token}?appClientId=${appClientId2}&fromURI=${fromURI2}`,
+ );
+ cy.contains('Save and continue');
+ cy.url()
+ .should('contain', appClientId2)
+ .and('contain', fromURI2)
+ .and('not.contain', appClientId1)
+ .and('not.contain', fromURI1);
+
+ cy.get('form')
+ .should('have.attr', 'action')
+ .and('match', new RegExp(appClientId2))
+ .and('match', new RegExp(fromURI2))
+ .and('not.match', new RegExp(appClientId1))
+ .and('not.match', new RegExp(fromURI1));
+ });
+ });
+ });
+ context('Existing users attempting to register with Okta', () => {
+ it('should send a STAGED user a set password email with an Okta activation token', () => {
+ // Test users created via IDAPI-with-Okta do not have the activation
+ // lifecycle run at creation, so they don't transition immediately from
+ // STAGED to PROVISIONED (c.f.
+ // https://developer.okta.com/docs/reference/api/users/#create-user) .
+ // This is useful for us as we can test STAGED users first, then test
+ // PROVISIONED users in the next test by activating a STAGED user. Users
+ // created through Gateway-with-Okta do have this lifecycle run, so if we
+ // rebuild these tests to not use IDAPI at all, we need to figure out a
+ // way to test STAGED and PROVISIONED users (probably by just passing an
+ // optional `activate` prop to a createUser function).
+ cy
+ .createTestUser({
+ isGuestUser: true,
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.STAGED);
+
+ cy.visit('/register');
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /\/set-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('This account already exists');
+
+ expect(body).to.have.string('Create password');
+ expect(links.length).to.eq(2);
+ const setPasswordLink = links.find(
+ (s) => s.text?.includes('Create password'),
+ );
+ expect(setPasswordLink?.href).not.to.have.string('useOkta=true');
+ cy.visit(setPasswordLink?.href as string);
+ cy.contains('Create password');
+ cy.contains(emailAddress);
+ });
+ });
+ });
+ });
+
+ it('should send a STAGED user a set password email with an Okta activation token, and has a prefixed activation token when using a native app', () => {
+ // Test users created via IDAPI-with-Okta do not have the activation
+ // lifecycle run at creation, so they don't transition immediately from
+ // STAGED to PROVISIONED (c.f.
+ // https://developer.okta.com/docs/reference/api/users/#create-user) .
+ // This is useful for us as we can test STAGED users first, then test
+ // PROVISIONED users in the next test by activating a STAGED user. Users
+ // created through Gateway-with-Okta do have this lifecycle run, so if we
+ // rebuild these tests to not use IDAPI at all, we need to figure out a
+ // way to test STAGED and PROVISIONED users (probably by just passing an
+ // optional `activate` prop to a createUser function).
+ cy
+ .createTestUser({
+ isGuestUser: true,
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.STAGED);
+
+ const appClientId = Cypress.env('OKTA_ANDROID_CLIENT_ID');
+ const fromURI = 'fromURI1';
+
+ cy.visit(`/register?appClientId=${appClientId}&fromURI=${fromURI}`);
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /\/set-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('This account already exists');
+
+ expect(body).to.have.string('Create password');
+ expect(links.length).to.eq(2);
+ const setPasswordLink = links.find(
+ (s) => s.text?.includes('Create password'),
+ );
+ expect(setPasswordLink?.href ?? '')
+ .to.have.string('al_')
+ .and.not.to.have.string('useOkta=true');
+ cy.visit(setPasswordLink?.href as string);
+ cy.contains('Create password');
+ cy.contains(emailAddress);
+ });
+ });
+ });
+ });
+
+ it('should send a PROVISIONED user a set password email with an Okta activation token', () => {
+ cy
+ .createTestUser({
+ isGuestUser: true,
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.activateTestOktaUser(emailAddress).then(() => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.PROVISIONED);
+
+ cy.visit('/register');
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /\/set-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('This account already exists');
+ expect(body).to.have.string('Create password');
+ expect(links.length).to.eq(2);
+ const setPasswordLink = links.find(
+ (s) => s.text?.includes('Create password'),
+ );
+ expect(setPasswordLink?.href).not.to.have.string(
+ 'useOkta=true',
+ );
+ cy.visit(setPasswordLink?.href as string);
+ cy.contains('Create password');
+ cy.contains(emailAddress);
+ });
+ });
+ });
+ });
+ });
+ it('should send an ACTIVE UNvalidated user with a password a security email with activation token', () => {
+ cy
+ .createTestUser({
+ isGuestUser: false,
+ isUserEmailValidated: false,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.ACTIVE);
+
+ cy.visit('/register');
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ // Make sure that we don't get sent to the 'security reasons' page
+ cy.url().should('include', '/register/email-sent');
+ cy.contains(
+ 'For security reasons we need you to change your password.',
+ ).should('not.exist');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string(
+ 'Because your security is extremely important to us, we have changed our password policy.',
+ );
+ expect(body).to.have.string('Reset password');
+ expect(links.length).to.eq(2);
+ const resetPasswordLink = links.find(
+ (s) => s.text?.includes('Reset password'),
+ );
+ cy.visit(resetPasswordLink?.href as string);
+ cy.contains(emailAddress);
+ cy.contains('Reset password');
+ });
+ });
+ });
+ });
+ it('should send an ACTIVE validated user WITH a password a reset password email with an activation token', () => {
+ cy
+ .createTestUser({
+ isGuestUser: false,
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.ACTIVE);
+
+ cy.visit('/register');
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('This account already exists');
+ expect(body).to.have.string('Sign in');
+ expect(body).to.have.string('Reset password');
+ expect(links.length).to.eq(3);
+ const resetPasswordLink = links.find(
+ (s) => s.text?.includes('Reset password'),
+ );
+ expect(resetPasswordLink?.href ?? '').not.to.have.string(
+ 'useOkta=true',
+ );
+ cy.visit(resetPasswordLink?.href as string);
+ cy.contains(emailAddress);
+ cy.contains('Reset password');
+ });
+ });
+ });
+ });
+ it('should send an ACTIVE validated user WITH a password a reset password email with an activation token, and prefixed activation token if using native app', () => {
+ cy
+ .createTestUser({
+ isGuestUser: false,
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.ACTIVE);
+
+ const appClientId = Cypress.env('OKTA_ANDROID_CLIENT_ID');
+ const fromURI = 'fromURI1';
+
+ cy.visit(`/register?appClientId=${appClientId}&fromURI=${fromURI}`);
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('This account already exists');
+ expect(body).to.have.string('Sign in');
+ expect(body).to.have.string('Reset password');
+ expect(links.length).to.eq(3);
+ const resetPasswordLink = links.find(
+ (s) => s.text?.includes('Reset password'),
+ );
+ expect(resetPasswordLink?.href ?? '')
+ .to.have.string('al_')
+ .and.not.to.have.string('useOkta=true');
+ cy.visit(resetPasswordLink?.href as string);
+ cy.contains(emailAddress);
+ cy.contains('Reset password');
+ });
+ });
+ });
+ });
+ it('should send a RECOVERY user a reset password email with an Okta activation token', () => {
+ cy
+ .createTestUser({
+ isGuestUser: false,
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.resetOktaUserPassword(emailAddress).then(() => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.RECOVERY);
+
+ cy.visit('/register');
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('Password reset');
+ expect(body).to.have.string('Reset password');
+ expect(links.length).to.eq(2);
+ const resetPasswordLink = links.find(
+ (s) => s.text?.includes('Reset password'),
+ );
+ expect(resetPasswordLink?.href ?? '').not.to.have.string(
+ 'useOkta=true',
+ );
+ cy.visit(resetPasswordLink?.href as string);
+ cy.contains('Reset password');
+ cy.contains(emailAddress);
+ });
+ });
+ });
+ });
+ });
+ it('should send a PASSWORD_EXPIRED user a reset password email with an Okta activation token', () => {
+ cy
+ .createTestUser({
+ isGuestUser: false,
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.expireOktaUserPassword(emailAddress).then(() => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.PASSWORD_EXPIRED);
+
+ cy.visit('/register');
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('Password reset');
+ expect(body).to.have.string('Reset password');
+ expect(links.length).to.eq(2);
+ const resetPasswordLink = links.find(
+ (s) => s.text?.includes('Reset password'),
+ );
+ expect(resetPasswordLink?.href ?? '').not.to.have.string(
+ 'useOkta=true',
+ );
+ cy.visit(resetPasswordLink?.href as string);
+ cy.contains('Reset password');
+ cy.contains(emailAddress);
+ });
+ });
+ });
+ });
+ });
+ it('should display an error if a SUSPENDED user attempts to register', () => {
+ cy
+ .createTestUser({
+ isGuestUser: false,
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.suspendOktaUser(emailAddress).then(() => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.SUSPENDED);
+
+ cy.visit('/register');
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('There was a problem registering, please try again.');
+ });
+ });
+ });
+ });
+ });
+
+ context(
+ 'Existing users asking for an email to be resent after attempting to register with Okta',
+ () => {
+ it('should resend a STAGED user a set password email with an Okta activation token', () => {
+ cy
+ .createTestUser({
+ isGuestUser: true,
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.STAGED);
+
+ cy.visit('/register');
+
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ // Wait for the first email to arrive...
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /\/set-password\/([^"]*)/,
+ ).then(() => {
+ const timeRequestWasMade = new Date();
+
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ // ...before waiting for the second email to arrive
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /\/set-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('This account already exists');
+ expect(body).to.have.string('Create password');
+ expect(links.length).to.eq(2);
+ const setPasswordLink = links.find(
+ (s) => s.text?.includes('Create password'),
+ );
+ expect(setPasswordLink?.href ?? '').not.to.have.string(
+ 'useOkta=true',
+ );
+ cy.visit(setPasswordLink?.href as string);
+ cy.contains('Create password');
+ cy.contains(emailAddress);
+ });
+ });
+ });
+ });
+ });
+
+ it('should resend a PROVISIONED user a set password email with an Okta activation token', () => {
+ cy
+ .createTestUser({
+ isGuestUser: true,
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.activateTestOktaUser(emailAddress).then(() => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.PROVISIONED);
+
+ cy.visit('/register');
+
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /\/set-password\/([^"]*)/,
+ ).then(() => {
+ const timeRequestWasMade = new Date();
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /\/set-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('This account already exists');
+ expect(body).to.have.string('Create password');
+ expect(links.length).to.eq(2);
+ const setPasswordLink = links.find(
+ (s) => s.text?.includes('Create password'),
+ );
+ expect(setPasswordLink?.href ?? '').not.to.have.string(
+ 'useOkta=true',
+ );
+ cy.visit(setPasswordLink?.href as string);
+ cy.contains('Create password');
+ cy.contains(emailAddress);
+ });
+ });
+ });
+ });
+ });
+ });
+ it('should send an ACTIVE user a reset password email with an Okta activation token', () => {
+ cy
+ .createTestUser({
+ isGuestUser: false,
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.ACTIVE);
+
+ cy.visit('/register');
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ ).then(() => {
+ const timeRequestWasMade = new Date();
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('This account already exists');
+ expect(body).to.have.string('Sign in');
+ expect(body).to.have.string('Reset password');
+ expect(links.length).to.eq(3);
+ const resetPasswordLink = links.find(
+ (s) => s.text?.includes('Reset password'),
+ );
+ expect(resetPasswordLink?.href ?? '').not.to.have.string(
+ 'useOkta=true',
+ );
+ cy.visit(resetPasswordLink?.href as string);
+ cy.contains('Reset password');
+ cy.contains(emailAddress);
+ });
+ });
+ });
+ });
+ });
+ it('should send a RECOVERY user a reset password email with an Okta activation token', () => {
+ cy
+ .createTestUser({
+ isGuestUser: false,
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.resetOktaUserPassword(emailAddress).then(() => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.RECOVERY);
+
+ cy.visit('/register');
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(() => {
+ const timeRequestWasMade = new Date();
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('Password reset');
+ expect(body).to.have.string('Reset password');
+ expect(links.length).to.eq(2);
+ const resetPasswordLink = links.find(
+ (s) => s.text?.includes('Reset password'),
+ );
+ expect(resetPasswordLink?.href ?? '').not.to.have.string(
+ 'useOkta=true',
+ );
+ cy.visit(resetPasswordLink?.href as string);
+ cy.contains('Reset password');
+ cy.contains(emailAddress);
+ });
+ });
+ });
+ });
+ });
+ });
+ it('should send a PASSWORD_EXPIRED user a reset password email with an Okta activation token', () => {
+ cy
+ .createTestUser({
+ isGuestUser: false,
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.expireOktaUserPassword(emailAddress).then(() => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.PASSWORD_EXPIRED);
+
+ cy.visit('/register');
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(() => {
+ const timeRequestWasMade = new Date();
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('Password reset');
+ expect(body).to.have.string('Reset password');
+ expect(links.length).to.eq(2);
+ const resetPasswordLink = links.find(
+ (s) => s.text?.includes('Reset password'),
+ );
+ expect(resetPasswordLink?.href ?? '').not.to.have.string(
+ 'useOkta=true',
+ );
+ cy.visit(resetPasswordLink?.href as string);
+ cy.contains('Reset password');
+ cy.contains(emailAddress);
+ });
+ });
+ });
+ });
+ });
+ });
+ },
+ );
+
+ context('Welcome Page - Resend (Link expired)', () => {
+ it('send an email for user with no existing account', () => {
+ const encodedReturnUrl =
+ 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
+ const unregisteredEmail = randomMailosaurEmail();
+
+ cy.visit(`/welcome/resend?returnUrl=${encodedReturnUrl}`);
+
+ const timeRequestWasMade = new Date();
+ cy.get('input[name=email]').type(unregisteredEmail);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(unregisteredEmail);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ unregisteredEmail,
+ timeRequestWasMade,
+ /welcome\/([^"]*)/,
+ ).then(({ body, token }) => {
+ expect(body).to.have.string('Complete registration');
+ cy.visit(`/welcome/${token}`);
+ cy.contains('Save and continue');
+
+ cy.get('form')
+ .should('have.attr', 'action')
+ .and('match', new RegExp(encodedReturnUrl));
+
+ //we are reloading here to make sure the params are persisted even on page refresh
+ cy.reload();
+
+ cy.get('input[name="password"]').type(randomPassword());
+ cy.get('button[type="submit"]').click();
+ cy.url().should('contain', encodedReturnUrl);
+ });
+ });
+
+ it('should resend a STAGED user a set password email with an Okta activation token', () => {
+ cy
+ .createTestUser({
+ isGuestUser: true,
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.STAGED);
+
+ cy.visit('/welcome/resend');
+
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ // Wait for the first email to arrive...
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /\/set-password\/([^"]*)/,
+ ).then(() => {
+ const timeRequestWasMade = new Date();
+
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ // ...before waiting for the second email to arrive
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /\/set-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('This account already exists');
+ expect(body).to.have.string('Create password');
+ expect(links.length).to.eq(2);
+ const setPasswordLink = links.find(
+ (s) => s.text?.includes('Create password'),
+ );
+ expect(setPasswordLink?.href ?? '').not.to.have.string(
+ 'useOkta=true',
+ );
+ cy.visit(setPasswordLink?.href as string);
+ cy.contains('Create password');
+ cy.contains(emailAddress);
+ });
+ });
+ });
+ });
+ });
+ it('should resend a PROVISIONED user a set password email with an Okta activation token', () => {
+ cy
+ .createTestUser({
+ isGuestUser: true,
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.activateTestOktaUser(emailAddress).then(() => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.PROVISIONED);
+
+ cy.visit('/welcome/resend');
+
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /\/set-password\/([^"]*)/,
+ ).then(() => {
+ const timeRequestWasMade = new Date();
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /\/set-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('This account already exists');
+ expect(body).to.have.string('Create password');
+ expect(links.length).to.eq(2);
+ const setPasswordLink = links.find(
+ (s) => s.text?.includes('Create password'),
+ );
+ expect(setPasswordLink?.href ?? '').not.to.have.string(
+ 'useOkta=true',
+ );
+ cy.visit(setPasswordLink?.href as string);
+ cy.contains('Create password');
+ cy.contains(emailAddress);
+ });
+ });
+ });
+ });
+ });
+ });
+ it('should send an ACTIVE user a reset password email with an activation token', () => {
+ cy
+ .createTestUser({
+ isGuestUser: false,
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.ACTIVE);
+
+ cy.visit('/welcome/resend');
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ ).then(() => {
+ const timeRequestWasMade = new Date();
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('This account already exists');
+ expect(body).to.have.string('Sign in');
+ expect(body).to.have.string('Reset password');
+ expect(links.length).to.eq(3);
+ const resetPasswordLink = links.find(
+ (s) => s.text?.includes('Reset password'),
+ );
+ expect(resetPasswordLink?.href ?? '').not.to.have.string(
+ 'useOkta=true',
+ );
+ cy.visit(resetPasswordLink?.href as string);
+ cy.contains('Reset password');
+ cy.contains(emailAddress);
+ });
+ });
+ });
+ });
+ });
+ it('should send a RECOVERY user a reset password email with an Okta activation token', () => {
+ cy
+ .createTestUser({
+ isGuestUser: false,
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.resetOktaUserPassword(emailAddress).then(() => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.RECOVERY);
+
+ cy.visit('/welcome/resend');
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(() => {
+ const timeRequestWasMade = new Date();
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('Password reset');
+ expect(body).to.have.string('Reset password');
+ expect(links.length).to.eq(2);
+ const resetPasswordLink = links.find(
+ (s) => s.text?.includes('Reset password'),
+ );
+ expect(resetPasswordLink?.href ?? '').not.to.have.string(
+ 'useOkta=true',
+ );
+ cy.visit(resetPasswordLink?.href as string);
+ cy.contains('Reset password');
+ cy.contains(emailAddress);
+ });
+ });
+ });
+ });
+ });
+ });
+ it('should send a PASSWORD_EXPIRED user a reset password email with an Okta activation token', () => {
+ cy
+ .createTestUser({
+ isGuestUser: false,
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.expireOktaUserPassword(emailAddress).then(() => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.PASSWORD_EXPIRED);
+
+ cy.visit('/welcome/resend');
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(() => {
+ const timeRequestWasMade = new Date();
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('Password reset');
+ expect(body).to.have.string('Reset password');
+ expect(links.length).to.eq(2);
+ const resetPasswordLink = links.find(
+ (s) => s.text?.includes('Reset password'),
+ );
+ expect(resetPasswordLink?.href ?? '').not.to.have.string(
+ 'useOkta=true',
+ );
+ cy.visit(resetPasswordLink?.href as string);
+ cy.contains('Reset password');
+ cy.contains(emailAddress);
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+
+ context('Okta session exists on /signin', () => {
+ beforeEach(() => {
+ // Disable redirect to /signin/success by default
+ cy.setCookie(
+ 'GU_ran_experiments',
+ new URLSearchParams({
+ OptInPromptPostSignIn: Date.now().toString(),
+ }).toString(),
+ );
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', 'https://m.code.dev-theguardian.com/', (req) => {
+ req.reply(200);
+ });
+ });
+
+ it('shows the signed in as page', () => {
+ // Create a validated test user
+ cy.createTestUser({ isUserEmailValidated: true }).then(
+ ({ emailAddress, finalPassword }) => {
+ // Sign our new user in
+ cy.visit(
+ `/signin?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/consents`,
+ )}`,
+ );
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', '/consents');
+
+ // Get the current session data
+ cy.getCookie('sid').then((originalSidCookie) => {
+ expect(originalSidCookie).to.exist;
+
+ // Visit register again
+ cy.visit(
+ `/register?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/consents`,
+ )}`,
+ );
+ cy.url().should('include', '/register');
+
+ cy.contains('Sign in to the Guardian');
+ cy.contains('You are signed in with');
+ cy.contains(emailAddress);
+ cy.contains('Continue')
+ .should('have.attr', 'href')
+ .and(
+ 'include',
+ `https://${Cypress.env(
+ 'BASE_URI',
+ )}/signin/refresh?returnUrl=https%3A%2F%2Fprofile.thegulocal.com%2Fconsents`,
+ );
+ cy.contains('a', 'Sign in')
+ .should('have.attr', 'href')
+ .and('include', '/signout?returnUrl=');
+ cy.contains('Sign in with a different email');
+ });
+ },
+ );
+ });
+ });
});
diff --git a/cypress/integration/ete-okta/reset_password.3.cy.ts b/cypress/integration/ete-okta/reset_password.3.cy.ts
index 242858b784..6dacd3d16f 100644
--- a/cypress/integration/ete-okta/reset_password.3.cy.ts
+++ b/cypress/integration/ete-okta/reset_password.3.cy.ts
@@ -2,526 +2,526 @@ import { Status } from '../../../src/server/models/okta/User';
import { randomPassword } from '../../support/commands/testUser';
const breachCheck = () => {
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
};
describe('Password reset flow in Okta', () => {
- context('Account exists', () => {
- it("changes the reader's password", () => {
- const encodedReturnUrl =
- 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
- const encodedRef = 'https%3A%2F%2Fm.theguardian.com';
- const refViewId = 'testRefViewId';
- const clientId = 'jobs';
-
- // these params should *not* persist between initial registration and welcome page
- // despite the fact that they PersistableQueryParams, as these are set by the Okta SDK sign in method
- // and subsequent interception, and not by gateway
- const appClientId = 'appClientId1';
- const fromURI = 'fromURI1';
-
- breachCheck();
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.visit(
- `/reset-password?returnUrl=${encodedReturnUrl}&ref=${encodedRef}&refViewId=${refViewId}&clientId=${clientId}&appClientId=${appClientId}&fromURI=${fromURI}`,
- );
- const timeRequestWasMade = new Date();
-
- cy.contains('Forgot password');
- cy.get('input[name=email]').type(emailAddress);
-
- // Continue checking the password reset flow after reCAPTCHA assertions above.
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.contains('Check your email inbox');
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(({ token }) => {
- cy.visit(`/reset-password/${token}`);
-
- cy.get('form')
- .should('have.attr', 'action')
- .and('match', new RegExp(encodedReturnUrl))
- .and('match', new RegExp(refViewId))
- .and('match', new RegExp(encodedRef))
- .and('match', new RegExp(clientId))
- .and('not.match', new RegExp(appClientId))
- .and('not.match', new RegExp(fromURI));
-
- //we are reloading here to make sure the params are persisted even on page refresh
- cy.reload();
-
- cy.get('input[name=password]').type(randomPassword());
-
- cy.wait('@breachCheck');
- cy.get('[data-cy="main-form-submit-button"]')
- .click()
- .should('be.disabled');
- cy.contains('Password updated');
- cy.contains(emailAddress.toLowerCase());
-
- cy.url().should('contain', encodedReturnUrl);
- cy.url().should('contain', refViewId);
- cy.url().should('contain', encodedRef);
- cy.url().should('contain', clientId);
- cy.url().should('not.contain', 'useOkta=true');
- cy.url().should('not.contain', appClientId);
- cy.url().should('not.contain', fromURI);
- });
- });
- });
-
- it("changes the reader's password, and has a prefixed recovery token when using a native app", () => {
- const encodedReturnUrl =
- 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
- const encodedRef = 'https%3A%2F%2Fm.theguardian.com';
- const refViewId = 'testRefViewId';
- const clientId = 'jobs';
-
- // these params should *not* persist between initial registration and welcome page
- // despite the fact that they PersistableQueryParams, as these are set by the Okta SDK sign in method
- // and subsequent interception, and not by gateway
- const appClientId = Cypress.env('OKTA_ANDROID_CLIENT_ID');
- const fromURI = 'fromURI1';
-
- breachCheck();
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.visit(
- `/reset-password?returnUrl=${encodedReturnUrl}&ref=${encodedRef}&refViewId=${refViewId}&clientId=${clientId}&appClientId=${appClientId}&fromURI=${fromURI}`,
- );
- const timeRequestWasMade = new Date();
-
- cy.contains('Forgot password');
- cy.get('input[name=email]').type(emailAddress);
-
- // Continue checking the password reset flow after reCAPTCHA assertions above.
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.contains('Check your email inbox');
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(({ token }) => {
- expect(token).to.have.string('al_');
- cy.visit(`/reset-password/${token}`);
-
- cy.get('form')
- .should('have.attr', 'action')
- .and('match', new RegExp(encodedReturnUrl))
- .and('match', new RegExp(refViewId))
- .and('match', new RegExp(encodedRef))
- .and('match', new RegExp(clientId))
- .and('not.match', new RegExp(appClientId))
- .and('not.match', new RegExp(fromURI));
-
- //we are reloading here to make sure the params are persisted even on page refresh
- cy.reload();
-
- cy.get('input[name=password]').type(randomPassword());
-
- cy.wait('@breachCheck');
- cy.get('[data-cy="main-form-submit-button"]')
- .click()
- .should('be.disabled');
- cy.contains('Password updated');
- cy.contains(emailAddress.toLowerCase());
-
- cy.url().should('contain', encodedReturnUrl);
- cy.url().should('contain', refViewId);
- cy.url().should('contain', encodedRef);
- cy.url().should('contain', clientId);
- cy.url().should('not.contain', 'useOkta=true');
- cy.url().should('not.contain', appClientId);
- cy.url().should('not.contain', fromURI);
- });
- });
- });
-
- it("changes the reader's password and overrides returnUrl from encryptedStateCookie if one set on reset password page url", () => {
- const encodedReturnUrl =
- 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
-
- breachCheck();
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.visit(`/reset-password?returnUrl=${encodedReturnUrl}`);
- const timeRequestWasMade = new Date();
-
- cy.contains('Forgot password');
- cy.get('input[name=email]').type(emailAddress);
-
- // Continue checking the password reset flow after reCAPTCHA assertions above.
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.contains('Check your email inbox');
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(({ token }) => {
- const newReturnUrl = encodeURIComponent(
- 'https://www.theguardian.com/technology/2017/may/04/nier-automata-sci-fi-game-sleeper-hit-designer-yoko-taro',
- );
- cy.visit(`/reset-password/${token}?returnUrl=${newReturnUrl}`);
-
- cy.url()
- .should('contain', newReturnUrl)
- .and('not.contain', encodedReturnUrl);
-
- cy.get('form')
- .should('have.attr', 'action')
- .and('match', new RegExp(newReturnUrl))
- .and('not.match', new RegExp(encodedReturnUrl));
-
- //we are reloading here to make sure the params are persisted even on page refresh
- cy.reload();
-
- cy.get('input[name=password]').type(randomPassword());
-
- cy.wait('@breachCheck');
- cy.get('[data-cy="main-form-submit-button"]')
- .click()
- .should('be.disabled');
- cy.contains('Password updated');
- cy.contains(emailAddress.toLowerCase());
-
- cy.url()
- .should('contain', newReturnUrl)
- .and('not.contain', encodedReturnUrl)
- .and('not.contain', 'useOkta=true');
- });
- });
- });
-
- it('overrides appClientId and fromURI if set on reset password page url', () => {
- const encodedReturnUrl =
- 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
-
- // these params should *not* persist between initial registration and welcome page
- // despite the fact that they PersistableQueryParams, as these are set by the Okta SDK sign in method
- // and subsequent interception, and not by gateway
- const appClientId1 = 'appClientId1';
- const fromURI1 = 'fromURI1';
-
- breachCheck();
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.visit(
- `/reset-password?returnUrl=${encodedReturnUrl}&appClientId=${appClientId1}&fromURI=${fromURI1}`,
- );
- const timeRequestWasMade = new Date();
-
- cy.contains('Forgot password');
- cy.get('input[name=email]').type(emailAddress);
-
- // Continue checking the password reset flow after reCAPTCHA assertions above.
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.contains('Check your email inbox');
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(({ token }) => {
- // should contain these params instead
- const appClientId2 = 'appClientId2';
- const fromURI2 = 'fromURI2';
- cy.visit(
- `/reset-password/${token}?appClientId=${appClientId2}&fromURI=${fromURI2}`,
- );
-
- cy.url()
- .should('contain', appClientId2)
- .and('contain', fromURI2)
- .and('not.contain', appClientId1)
- .and('not.contain', fromURI1);
-
- cy.get('form')
- .should('have.attr', 'action')
- .and('match', new RegExp(appClientId2))
- .and('match', new RegExp(fromURI2))
- .and('not.match', new RegExp(appClientId1))
- .and('not.match', new RegExp(fromURI1));
- });
- });
- });
- });
-
- context('STAGED user', () => {
- it("changes the reader's password", () => {
- breachCheck();
- cy.createTestUser({ isGuestUser: true })?.then(({ emailAddress }) => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.STAGED);
-
- cy.visit('/reset-password');
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('button[type="submit"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /\/set-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('Welcome back');
-
- expect(body).to.have.string('Create password');
- expect(links.length).to.eq(2);
- const setPasswordLink = links.find(
- (s) => s.text?.includes('Create password'),
- );
- expect(setPasswordLink?.href ?? '').not.to.have.string(
- 'useOkta=true',
- );
- cy.visit(setPasswordLink?.href as string);
- cy.contains('Create password');
- cy.contains(emailAddress);
-
- cy.get('input[name=password]').type(randomPassword());
-
- cy.wait('@breachCheck');
- cy.get('[data-cy="main-form-submit-button"]')
- .click()
- .should('be.disabled');
- cy.contains('Password created');
- cy.contains(emailAddress.toLowerCase());
- });
- });
- });
- });
-
- it("changes the reader's password, and has a prefixed recovery token when using a native app", () => {
- breachCheck();
- cy.createTestUser({ isGuestUser: true })?.then(({ emailAddress }) => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.STAGED);
-
- const appClientId = Cypress.env('OKTA_ANDROID_CLIENT_ID');
- const fromURI = 'fromURI1';
-
- cy.visit(
- `/reset-password?appClientId=${appClientId}&fromURI=${fromURI}`,
- );
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('button[type="submit"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /\/set-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('Welcome back');
-
- expect(body).to.have.string('Create password');
- expect(links.length).to.eq(2);
- const setPasswordLink = links.find(
- (s) => s.text?.includes('Create password'),
- );
- expect(setPasswordLink?.href ?? '')
- .to.have.string('al_')
- .and.not.to.have.string('useOkta=true');
- cy.visit(setPasswordLink?.href as string);
- cy.contains('Create password');
- cy.contains(emailAddress);
-
- cy.get('input[name=password]').type(randomPassword());
-
- cy.wait('@breachCheck');
- cy.get('[data-cy="main-form-submit-button"]')
- .click()
- .should('be.disabled');
- cy.contains('Password created');
- cy.contains(emailAddress.toLowerCase());
- });
- });
- });
- });
- });
-
- context('PROVISIONED user', () => {
- it("changes the reader's password", () => {
- breachCheck();
- cy.createTestUser({ isGuestUser: true })?.then(({ emailAddress }) => {
- cy.activateTestOktaUser(emailAddress).then(() => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.PROVISIONED);
-
- cy.visit('/reset-password');
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('button[type="submit"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /\/set-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('Welcome back');
-
- expect(body).to.have.string('Create password');
- expect(links.length).to.eq(2);
- const setPasswordLink = links.find(
- (s) => s.text?.includes('Create password'),
- );
- expect(setPasswordLink?.href ?? '').not.to.have.string(
- 'useOkta=true',
- );
- cy.visit(setPasswordLink?.href as string);
- cy.contains('Create password');
- cy.contains(emailAddress);
-
- cy.get('input[name=password]').type(randomPassword());
-
- cy.wait('@breachCheck');
- cy.get('[data-cy="main-form-submit-button"]')
- .click()
- .should('be.disabled');
- cy.contains('Password created');
- cy.contains(emailAddress.toLowerCase());
- });
- });
- });
- });
- });
- });
-
- context('RECOVERY user', () => {
- it("changes the reader's password", () => {
- breachCheck();
- cy.createTestUser({ isGuestUser: false })?.then(({ emailAddress }) => {
- cy.resetOktaUserPassword(emailAddress).then(() => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.RECOVERY);
-
- cy.visit('/reset-password');
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('button[type="submit"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('Password reset');
- expect(body).to.have.string('Reset password');
- expect(links.length).to.eq(2);
- const resetPasswordLink = links.find(
- (s) => s.text?.includes('Reset password'),
- );
- expect(resetPasswordLink?.href ?? '').not.to.have.string(
- 'useOkta=true',
- );
- cy.visit(resetPasswordLink?.href as string);
- cy.contains('Reset password');
- cy.contains(emailAddress);
-
- cy.get('input[name=password]').type(randomPassword());
-
- cy.wait('@breachCheck');
- cy.get('[data-cy="main-form-submit-button"]')
- .click()
- .should('be.disabled');
- cy.contains('Password updated');
- cy.contains(emailAddress.toLowerCase());
- });
- });
- });
- });
- });
- });
-
- context('PASSWORD_EXPIRED user', () => {
- it("changes the reader's password", () => {
- breachCheck();
- cy.createTestUser({ isGuestUser: false })?.then(({ emailAddress }) => {
- cy.expireOktaUserPassword(emailAddress).then(() => {
- cy.getTestOktaUser(emailAddress).then((oktaUser) => {
- expect(oktaUser.status).to.eq(Status.PASSWORD_EXPIRED);
-
- cy.visit('/reset-password');
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('button[type="submit"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(({ links, body }) => {
- expect(body).to.have.string('Password reset');
- expect(body).to.have.string('Reset password');
- expect(links.length).to.eq(2);
- const resetPasswordLink = links.find(
- (s) => s.text?.includes('Reset password'),
- );
- expect(resetPasswordLink?.href ?? '').not.to.have.string(
- 'useOkta=true',
- );
- cy.visit(resetPasswordLink?.href as string);
- cy.contains('Reset password');
- cy.contains(emailAddress);
-
- cy.get('input[name=password]').type(randomPassword());
-
- cy.wait('@breachCheck');
- cy.get('[data-cy="main-form-submit-button"]')
- .click()
- .should('be.disabled');
- cy.contains('Password updated');
- cy.contains(emailAddress.toLowerCase());
- });
- });
- });
- });
- });
- });
+ context('Account exists', () => {
+ it("changes the reader's password", () => {
+ const encodedReturnUrl =
+ 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
+ const encodedRef = 'https%3A%2F%2Fm.theguardian.com';
+ const refViewId = 'testRefViewId';
+ const clientId = 'jobs';
+
+ // these params should *not* persist between initial registration and welcome page
+ // despite the fact that they PersistableQueryParams, as these are set by the Okta SDK sign in method
+ // and subsequent interception, and not by gateway
+ const appClientId = 'appClientId1';
+ const fromURI = 'fromURI1';
+
+ breachCheck();
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.visit(
+ `/reset-password?returnUrl=${encodedReturnUrl}&ref=${encodedRef}&refViewId=${refViewId}&clientId=${clientId}&appClientId=${appClientId}&fromURI=${fromURI}`,
+ );
+ const timeRequestWasMade = new Date();
+
+ cy.contains('Forgot password');
+ cy.get('input[name=email]').type(emailAddress);
+
+ // Continue checking the password reset flow after reCAPTCHA assertions above.
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.contains('Check your email inbox');
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(({ token }) => {
+ cy.visit(`/reset-password/${token}`);
+
+ cy.get('form')
+ .should('have.attr', 'action')
+ .and('match', new RegExp(encodedReturnUrl))
+ .and('match', new RegExp(refViewId))
+ .and('match', new RegExp(encodedRef))
+ .and('match', new RegExp(clientId))
+ .and('not.match', new RegExp(appClientId))
+ .and('not.match', new RegExp(fromURI));
+
+ //we are reloading here to make sure the params are persisted even on page refresh
+ cy.reload();
+
+ cy.get('input[name=password]').type(randomPassword());
+
+ cy.wait('@breachCheck');
+ cy.get('[data-cy="main-form-submit-button"]')
+ .click()
+ .should('be.disabled');
+ cy.contains('Password updated');
+ cy.contains(emailAddress.toLowerCase());
+
+ cy.url().should('contain', encodedReturnUrl);
+ cy.url().should('contain', refViewId);
+ cy.url().should('contain', encodedRef);
+ cy.url().should('contain', clientId);
+ cy.url().should('not.contain', 'useOkta=true');
+ cy.url().should('not.contain', appClientId);
+ cy.url().should('not.contain', fromURI);
+ });
+ });
+ });
+
+ it("changes the reader's password, and has a prefixed recovery token when using a native app", () => {
+ const encodedReturnUrl =
+ 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
+ const encodedRef = 'https%3A%2F%2Fm.theguardian.com';
+ const refViewId = 'testRefViewId';
+ const clientId = 'jobs';
+
+ // these params should *not* persist between initial registration and welcome page
+ // despite the fact that they PersistableQueryParams, as these are set by the Okta SDK sign in method
+ // and subsequent interception, and not by gateway
+ const appClientId = Cypress.env('OKTA_ANDROID_CLIENT_ID');
+ const fromURI = 'fromURI1';
+
+ breachCheck();
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.visit(
+ `/reset-password?returnUrl=${encodedReturnUrl}&ref=${encodedRef}&refViewId=${refViewId}&clientId=${clientId}&appClientId=${appClientId}&fromURI=${fromURI}`,
+ );
+ const timeRequestWasMade = new Date();
+
+ cy.contains('Forgot password');
+ cy.get('input[name=email]').type(emailAddress);
+
+ // Continue checking the password reset flow after reCAPTCHA assertions above.
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.contains('Check your email inbox');
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(({ token }) => {
+ expect(token).to.have.string('al_');
+ cy.visit(`/reset-password/${token}`);
+
+ cy.get('form')
+ .should('have.attr', 'action')
+ .and('match', new RegExp(encodedReturnUrl))
+ .and('match', new RegExp(refViewId))
+ .and('match', new RegExp(encodedRef))
+ .and('match', new RegExp(clientId))
+ .and('not.match', new RegExp(appClientId))
+ .and('not.match', new RegExp(fromURI));
+
+ //we are reloading here to make sure the params are persisted even on page refresh
+ cy.reload();
+
+ cy.get('input[name=password]').type(randomPassword());
+
+ cy.wait('@breachCheck');
+ cy.get('[data-cy="main-form-submit-button"]')
+ .click()
+ .should('be.disabled');
+ cy.contains('Password updated');
+ cy.contains(emailAddress.toLowerCase());
+
+ cy.url().should('contain', encodedReturnUrl);
+ cy.url().should('contain', refViewId);
+ cy.url().should('contain', encodedRef);
+ cy.url().should('contain', clientId);
+ cy.url().should('not.contain', 'useOkta=true');
+ cy.url().should('not.contain', appClientId);
+ cy.url().should('not.contain', fromURI);
+ });
+ });
+ });
+
+ it("changes the reader's password and overrides returnUrl from encryptedStateCookie if one set on reset password page url", () => {
+ const encodedReturnUrl =
+ 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
+
+ breachCheck();
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.visit(`/reset-password?returnUrl=${encodedReturnUrl}`);
+ const timeRequestWasMade = new Date();
+
+ cy.contains('Forgot password');
+ cy.get('input[name=email]').type(emailAddress);
+
+ // Continue checking the password reset flow after reCAPTCHA assertions above.
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.contains('Check your email inbox');
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(({ token }) => {
+ const newReturnUrl = encodeURIComponent(
+ 'https://www.theguardian.com/technology/2017/may/04/nier-automata-sci-fi-game-sleeper-hit-designer-yoko-taro',
+ );
+ cy.visit(`/reset-password/${token}?returnUrl=${newReturnUrl}`);
+
+ cy.url()
+ .should('contain', newReturnUrl)
+ .and('not.contain', encodedReturnUrl);
+
+ cy.get('form')
+ .should('have.attr', 'action')
+ .and('match', new RegExp(newReturnUrl))
+ .and('not.match', new RegExp(encodedReturnUrl));
+
+ //we are reloading here to make sure the params are persisted even on page refresh
+ cy.reload();
+
+ cy.get('input[name=password]').type(randomPassword());
+
+ cy.wait('@breachCheck');
+ cy.get('[data-cy="main-form-submit-button"]')
+ .click()
+ .should('be.disabled');
+ cy.contains('Password updated');
+ cy.contains(emailAddress.toLowerCase());
+
+ cy.url()
+ .should('contain', newReturnUrl)
+ .and('not.contain', encodedReturnUrl)
+ .and('not.contain', 'useOkta=true');
+ });
+ });
+ });
+
+ it('overrides appClientId and fromURI if set on reset password page url', () => {
+ const encodedReturnUrl =
+ 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
+
+ // these params should *not* persist between initial registration and welcome page
+ // despite the fact that they PersistableQueryParams, as these are set by the Okta SDK sign in method
+ // and subsequent interception, and not by gateway
+ const appClientId1 = 'appClientId1';
+ const fromURI1 = 'fromURI1';
+
+ breachCheck();
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.visit(
+ `/reset-password?returnUrl=${encodedReturnUrl}&appClientId=${appClientId1}&fromURI=${fromURI1}`,
+ );
+ const timeRequestWasMade = new Date();
+
+ cy.contains('Forgot password');
+ cy.get('input[name=email]').type(emailAddress);
+
+ // Continue checking the password reset flow after reCAPTCHA assertions above.
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.contains('Check your email inbox');
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(({ token }) => {
+ // should contain these params instead
+ const appClientId2 = 'appClientId2';
+ const fromURI2 = 'fromURI2';
+ cy.visit(
+ `/reset-password/${token}?appClientId=${appClientId2}&fromURI=${fromURI2}`,
+ );
+
+ cy.url()
+ .should('contain', appClientId2)
+ .and('contain', fromURI2)
+ .and('not.contain', appClientId1)
+ .and('not.contain', fromURI1);
+
+ cy.get('form')
+ .should('have.attr', 'action')
+ .and('match', new RegExp(appClientId2))
+ .and('match', new RegExp(fromURI2))
+ .and('not.match', new RegExp(appClientId1))
+ .and('not.match', new RegExp(fromURI1));
+ });
+ });
+ });
+ });
+
+ context('STAGED user', () => {
+ it("changes the reader's password", () => {
+ breachCheck();
+ cy.createTestUser({ isGuestUser: true })?.then(({ emailAddress }) => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.STAGED);
+
+ cy.visit('/reset-password');
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('button[type="submit"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /\/set-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('Welcome back');
+
+ expect(body).to.have.string('Create password');
+ expect(links.length).to.eq(2);
+ const setPasswordLink = links.find(
+ (s) => s.text?.includes('Create password'),
+ );
+ expect(setPasswordLink?.href ?? '').not.to.have.string(
+ 'useOkta=true',
+ );
+ cy.visit(setPasswordLink?.href as string);
+ cy.contains('Create password');
+ cy.contains(emailAddress);
+
+ cy.get('input[name=password]').type(randomPassword());
+
+ cy.wait('@breachCheck');
+ cy.get('[data-cy="main-form-submit-button"]')
+ .click()
+ .should('be.disabled');
+ cy.contains('Password created');
+ cy.contains(emailAddress.toLowerCase());
+ });
+ });
+ });
+ });
+
+ it("changes the reader's password, and has a prefixed recovery token when using a native app", () => {
+ breachCheck();
+ cy.createTestUser({ isGuestUser: true })?.then(({ emailAddress }) => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.STAGED);
+
+ const appClientId = Cypress.env('OKTA_ANDROID_CLIENT_ID');
+ const fromURI = 'fromURI1';
+
+ cy.visit(
+ `/reset-password?appClientId=${appClientId}&fromURI=${fromURI}`,
+ );
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('button[type="submit"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /\/set-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('Welcome back');
+
+ expect(body).to.have.string('Create password');
+ expect(links.length).to.eq(2);
+ const setPasswordLink = links.find(
+ (s) => s.text?.includes('Create password'),
+ );
+ expect(setPasswordLink?.href ?? '')
+ .to.have.string('al_')
+ .and.not.to.have.string('useOkta=true');
+ cy.visit(setPasswordLink?.href as string);
+ cy.contains('Create password');
+ cy.contains(emailAddress);
+
+ cy.get('input[name=password]').type(randomPassword());
+
+ cy.wait('@breachCheck');
+ cy.get('[data-cy="main-form-submit-button"]')
+ .click()
+ .should('be.disabled');
+ cy.contains('Password created');
+ cy.contains(emailAddress.toLowerCase());
+ });
+ });
+ });
+ });
+ });
+
+ context('PROVISIONED user', () => {
+ it("changes the reader's password", () => {
+ breachCheck();
+ cy.createTestUser({ isGuestUser: true })?.then(({ emailAddress }) => {
+ cy.activateTestOktaUser(emailAddress).then(() => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.PROVISIONED);
+
+ cy.visit('/reset-password');
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('button[type="submit"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /\/set-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('Welcome back');
+
+ expect(body).to.have.string('Create password');
+ expect(links.length).to.eq(2);
+ const setPasswordLink = links.find(
+ (s) => s.text?.includes('Create password'),
+ );
+ expect(setPasswordLink?.href ?? '').not.to.have.string(
+ 'useOkta=true',
+ );
+ cy.visit(setPasswordLink?.href as string);
+ cy.contains('Create password');
+ cy.contains(emailAddress);
+
+ cy.get('input[name=password]').type(randomPassword());
+
+ cy.wait('@breachCheck');
+ cy.get('[data-cy="main-form-submit-button"]')
+ .click()
+ .should('be.disabled');
+ cy.contains('Password created');
+ cy.contains(emailAddress.toLowerCase());
+ });
+ });
+ });
+ });
+ });
+ });
+
+ context('RECOVERY user', () => {
+ it("changes the reader's password", () => {
+ breachCheck();
+ cy.createTestUser({ isGuestUser: false })?.then(({ emailAddress }) => {
+ cy.resetOktaUserPassword(emailAddress).then(() => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.RECOVERY);
+
+ cy.visit('/reset-password');
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('button[type="submit"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('Password reset');
+ expect(body).to.have.string('Reset password');
+ expect(links.length).to.eq(2);
+ const resetPasswordLink = links.find(
+ (s) => s.text?.includes('Reset password'),
+ );
+ expect(resetPasswordLink?.href ?? '').not.to.have.string(
+ 'useOkta=true',
+ );
+ cy.visit(resetPasswordLink?.href as string);
+ cy.contains('Reset password');
+ cy.contains(emailAddress);
+
+ cy.get('input[name=password]').type(randomPassword());
+
+ cy.wait('@breachCheck');
+ cy.get('[data-cy="main-form-submit-button"]')
+ .click()
+ .should('be.disabled');
+ cy.contains('Password updated');
+ cy.contains(emailAddress.toLowerCase());
+ });
+ });
+ });
+ });
+ });
+ });
+
+ context('PASSWORD_EXPIRED user', () => {
+ it("changes the reader's password", () => {
+ breachCheck();
+ cy.createTestUser({ isGuestUser: false })?.then(({ emailAddress }) => {
+ cy.expireOktaUserPassword(emailAddress).then(() => {
+ cy.getTestOktaUser(emailAddress).then((oktaUser) => {
+ expect(oktaUser.status).to.eq(Status.PASSWORD_EXPIRED);
+
+ cy.visit('/reset-password');
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('button[type="submit"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(({ links, body }) => {
+ expect(body).to.have.string('Password reset');
+ expect(body).to.have.string('Reset password');
+ expect(links.length).to.eq(2);
+ const resetPasswordLink = links.find(
+ (s) => s.text?.includes('Reset password'),
+ );
+ expect(resetPasswordLink?.href ?? '').not.to.have.string(
+ 'useOkta=true',
+ );
+ cy.visit(resetPasswordLink?.href as string);
+ cy.contains('Reset password');
+ cy.contains(emailAddress);
+
+ cy.get('input[name=password]').type(randomPassword());
+
+ cy.wait('@breachCheck');
+ cy.get('[data-cy="main-form-submit-button"]')
+ .click()
+ .should('be.disabled');
+ cy.contains('Password updated');
+ cy.contains(emailAddress.toLowerCase());
+ });
+ });
+ });
+ });
+ });
+ });
});
diff --git a/cypress/integration/ete-okta/sign_in.1.cy.ts b/cypress/integration/ete-okta/sign_in.1.cy.ts
index 2349335c79..b6a8e9a922 100644
--- a/cypress/integration/ete-okta/sign_in.1.cy.ts
+++ b/cypress/integration/ete-okta/sign_in.1.cy.ts
@@ -1,414 +1,414 @@
import * as SignIn from '../shared/sign_in.shared';
describe('Sign in flow, Okta enabled', () => {
- beforeEach(() => {
- SignIn.beforeEach();
- });
-
- context('Terms and Conditions links', () => {
- it(...SignIn.linksToTheGoogleTermsOfServicePage());
- it(...SignIn.linksToTheGooglePrivacyPolicyPage());
- it(...SignIn.linksToTheGuardianTermsAndConditionsPage());
- it(...SignIn.linksToTheGuardianPrivacyPolicyPage());
- it(
- ...SignIn.linksToTheGuardianJobsTermsAndConditionsPageWhenJobsClientIdSet(),
- );
- it(...SignIn.linksToTheGuardianJobsPrivacyPolicyPageWhenJobsClientIdSet());
- });
-
- it(...SignIn.persistsTheClientIdWhenNavigatingAway());
- it(...SignIn.appliesFormValidationToEmailAndPasswordInputFields());
- it(...SignIn.showsAMessageWhenCredentialsAreInvalid());
- it(...SignIn.correctlySignsInAnExistingUser());
- it(...SignIn.navigatesToResetPassword());
- it(...SignIn.navigatesToRegistration());
- it(...SignIn.respectsTheReturnUrlQueryParam());
- it(...SignIn.removesEncryptedEmailParameterFromQueryString());
- it(
- ...SignIn.removesEncryptedEmailParameterAndPreservesAllOtherValidParameters(),
- );
- it(
- ...SignIn.showsRecaptchaErrorsWhenTheUserTriesToSignInOfflineAndAllowsSignInWhenBackOnline(),
- );
- it(...SignIn.redirectsToOptInPrompt());
- it(...SignIn.hitsAccessTokenRateLimitAndRecoversTokenAfterTimeout());
-
- it(...SignIn.redirectsCorrectlyForSocialSignIn());
- it(
- ...SignIn.showsAnErrorMessageAndInformationParagraphWhenAccountLinkingRequiredErrorParameterIsPresent(),
- );
- it(
- ...SignIn.doesNotDisplaySocialButtonsWhenAccountLinkingRequiredErrorParameterIsPresent(),
- );
-
- it('sets emailValidated flag on oauth callback', () => {
- // this is a specific test case for new user registrations in Okta
- // In Okta new social registered users are added to the GuardianUser-EmailValidated group
- // by default, but the custom emailValidated field is not defined/set to false
- // this causes problems in legacy code, where the emailValidated flag is not set but the group is
- // so we need to set the flag to true when the user is added to the group
- // we do this on the oauth callback route /oauth/authorization-code/callback
- // where we update the user profile with the emailValidated flag if the user is in the GuardianUser-EmailValidated group but the emailValidated is falsy
-
- // This test checks this behaviour by first getting a user into this state
- // i.e user.profile.emailValidated = false, and user groups has GuardianUser-EmailValidated
-
- // first we have to get the id of the GuardianUser-EmailValidated group
- cy.findEmailValidatedOktaGroupId().then((groupId) => {
- // next we create a test user
- cy.createTestUser({}).then(({ emailAddress, finalPassword }) => {
- // we get the user profile object from Okta
- cy.getTestOktaUser(emailAddress).then((user) => {
- const { id, profile } = user;
- // check the user profile has the emailValidated flag set to false
- expect(profile.emailValidated).to.be.false;
- // next check the user groups
- cy.getOktaUserGroups(id).then((groups) => {
- // make sure the user is not in the GuardianUser-EmailValidated group
- const group = groups.find((g) => g.id === groupId);
- expect(group).not.to.exist;
-
- // and add them to the group if this is the case
- cy.addOktaUserToGroup(id, groupId);
-
- // at this point the user is in the correct state
- // so we attempt to sign them in
- cy.visit(
- `/signin?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/consents`,
- )}`,
- );
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', '/consents');
-
- // at this point the oauth callback route will have run, so we can recheck the user profile to see if the emailValidated flag has been set
- cy.getTestOktaUser(id).then((user) => {
- const { profile } = user;
- expect(profile.emailValidated).to.be.true;
- });
-
- // and the user should also be in the group
- cy.getOktaUserGroups(id).then((groups) => {
- const group = groups.find((g) => g.id === groupId);
- expect(group).to.exist;
- });
- });
- });
- });
- });
- });
- context('Okta session refresh', () => {
- it('refreshes a valid Okta session', () => {
- // Create a validated test user
- cy.createTestUser({ isUserEmailValidated: true }).then(
- ({ emailAddress, finalPassword }) => {
- // Sign our new user in
- cy.visit(
- `/signin?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/consents`,
- )}`,
- );
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', '/consents');
-
- // Get the current session data
- cy.getCookie('sid').then((originalSidCookie) => {
- expect(originalSidCookie).to.exist;
-
- // Refresh our user session
- cy.visit(
- `/signin/refresh?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/consents`,
- )}`,
- );
- cy.url().should('include', '/consents');
-
- // Get the refreshed session data
- cy.getCookie('sid').then((newSidCookie) => {
- expect(newSidCookie).to.exist;
- expect(newSidCookie?.value).to.equal(originalSidCookie?.value);
- if (newSidCookie?.expiry && originalSidCookie?.expiry) {
- expect(newSidCookie?.expiry).to.be.greaterThan(
- originalSidCookie?.expiry,
- );
- }
- });
- });
- },
- );
- });
- it('sends a client with the Okta cookie and an invalid Okta session to the redirectUrl', () => {
- // Create a validated test user
- cy.createTestUser({ isUserEmailValidated: true }).then(
- ({ emailAddress, finalPassword }) => {
- // Sign our new user in
- cy.visit(
- `/signin?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/consents`,
- )}`,
- );
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', '/consents');
-
- // Get the current session data
- cy.getCookie('sid').then((sidCookie) => {
- // Close the user's current session in Okta
- cy.closeCurrentOktaSession(sidCookie?.value).then(() => {
- // Refresh our user session
- cy.visit(
- `/signin/refresh?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/consents`,
- )}`,
- );
- cy.url().should('include', '/consents');
- });
- });
- },
- );
- });
- it('sends a client without the Okta cookie to the redirectUrl', () => {
- // Create a validated test user
- cy.createTestUser({ isUserEmailValidated: true }).then(
- ({ emailAddress, finalPassword }) => {
- // Sign our new user in
- cy.visit(
- `/signin?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/consents`,
- )}`,
- );
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', '/consents');
-
- // Delete the Okta sid cookie
- // strange behaviour form Cypress 12
- // where we need to delete cookie from both domains
- // to get the test to pass
- // cypress 12 seems to have issues with hostOnly cookies not being removed or persisting after clear
- // https://github.com/cypress-io/cypress/issues/25174
- cy.clearCookie('sid', {
- domain: Cypress.env('BASE_URI'),
- });
- cy.clearCookie('sid', {
- domain: `.${Cypress.env('BASE_URI')}`,
- });
-
- // Visit the refresh endpoint
- cy.visit(
- `/signin/refresh?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/consents`,
- )}`,
- );
- cy.url().should('include', '/consents');
-
- cy.getCookie('sid').should('not.exist');
- },
- );
- });
- it('sends a client with neither Okta nor Identity cookies to /signin', () => {
- // Create a validated test user
- cy.createTestUser({ isUserEmailValidated: true }).then(
- ({ emailAddress, finalPassword }) => {
- // Sign our new user in
- cy.visit(
- `/signin?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/consents`,
- )}`,
- );
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', '/consents');
-
- // Delete all cookies (Okta and IDAPI)
- cy.clearCookies();
-
- // Visit the refresh endpoint
- cy.visit(
- `/signin/refresh?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/consents`,
- )}`,
- );
- cy.url().should('include', '/signin');
-
- cy.getCookie('sid').should('not.exist');
- cy.getCookie('sc_gu_u').should('not.exist');
- cy.getCookie('sc_gu_la').should('not.exist');
- },
- );
- });
- it('leaves the last access cookie unchanged when refreshing a valid Okta session', () => {
- // Create a validated test user
- cy.createTestUser({ isUserEmailValidated: true }).then(
- ({ emailAddress, finalPassword }) => {
- // Sign our new user in
- cy.visit(
- `/signin?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/consents`,
- )}`,
- );
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', '/consents');
-
- // Get the current session data
- cy.getCookie('SC_GU_LA').then((originalLastAccessCookie) => {
- cy.getCookie('SC_GU_U').then((originalSecureIdapiCookie) => {
- expect(originalLastAccessCookie).to.exist;
- expect(originalSecureIdapiCookie).to.exist;
-
- // Refresh our user session
- cy.visit(
- `/signin/refresh?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/consents`,
- )}`,
- );
- cy.url().should('include', '/consents');
-
- // Expect the last access cookie to be unchanged
- cy.getCookie('SC_GU_LA').then((lastAccessCookie) => {
- expect(lastAccessCookie).to.exist;
- expect(lastAccessCookie?.value).to.equal(
- originalLastAccessCookie?.value,
- );
- expect(lastAccessCookie?.expiry).to.equal(
- originalLastAccessCookie?.expiry,
- );
- });
-
- // Expect other Idapi cookies to have changed
- cy.getCookie('SC_GU_U').then((secureIdapiCookie) => {
- expect(secureIdapiCookie).to.exist;
- expect(secureIdapiCookie?.value).not.to.equal(
- originalSecureIdapiCookie?.value,
- );
- if (
- secureIdapiCookie?.expiry &&
- originalSecureIdapiCookie?.expiry
- ) {
- expect(secureIdapiCookie?.expiry).to.be.greaterThan(
- originalSecureIdapiCookie?.expiry,
- );
- }
- });
- });
- });
- },
- );
- });
- });
-
- context('Okta unvalidated email flow', () => {
- it('Sends a user with an unvalidated email a reset password email on sign in', () => {
- cy
- .createTestUser({
- isUserEmailValidated: false,
- })
- ?.then(({ emailAddress, finalPassword }) => {
- const timeRequestWasMade = new Date();
- cy.visit('/signin');
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', '/signin/email-sent');
- cy.contains(
- 'For security reasons we need you to change your password.',
- );
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- // Ensure the user's authentication cookies are not set
- cy.getCookie('sid').then((sidCookie) => {
- expect(sidCookie).to.not.exist;
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(({ links, body, token }) => {
- expect(body).to.have.string(
- 'Because your security is extremely important to us, we have changed our password policy.',
- );
- expect(body).to.have.string('Reset password');
- expect(links.length).to.eq(2);
- const resetPasswordLink = links.find(
- (s) => s.text?.includes('Reset password'),
- );
- expect(resetPasswordLink?.href ?? '').to.have.string(
- 'reset-password',
- );
- cy.visit(`/reset-password/${token}`);
- cy.contains(emailAddress);
- cy.contains('Reset password');
- });
- });
- });
- });
- });
-
- context('Okta session exists on /signin', () => {
- beforeEach(() => {
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', 'https://m.code.dev-theguardian.com/', (req) => {
- req.reply(200);
- });
- });
-
- it('shows the signed in as page', () => {
- // Create a validated test user
- cy.createTestUser({ isUserEmailValidated: true }).then(
- ({ emailAddress, finalPassword }) => {
- // Sign our new user in
- cy.visit(
- `/signin?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/consents`,
- )}`,
- );
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', '/consents');
-
- // Get the current session data
- cy.getCookie('sid').then((originalSidCookie) => {
- expect(originalSidCookie).to.exist;
-
- // Visit sign in again
- cy.visit(
- `/signin?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/consents`,
- )}`,
- );
- cy.url().should('include', '/signin');
-
- cy.contains('Sign in to the Guardian');
- cy.contains('You are signed in with');
- cy.contains(emailAddress);
- cy.contains('Continue')
- .should('have.attr', 'href')
- .and(
- 'include',
- `https://${Cypress.env(
- 'BASE_URI',
- )}/signin/refresh?returnUrl=https%3A%2F%2Fprofile.thegulocal.com%2Fconsents`,
- );
- cy.contains('a', 'Sign in')
- .should('have.attr', 'href')
- .and('include', '/signout?returnUrl=');
- cy.contains('Sign in with a different email');
- });
- },
- );
- });
- });
+ beforeEach(() => {
+ SignIn.beforeEach();
+ });
+
+ context('Terms and Conditions links', () => {
+ it(...SignIn.linksToTheGoogleTermsOfServicePage());
+ it(...SignIn.linksToTheGooglePrivacyPolicyPage());
+ it(...SignIn.linksToTheGuardianTermsAndConditionsPage());
+ it(...SignIn.linksToTheGuardianPrivacyPolicyPage());
+ it(
+ ...SignIn.linksToTheGuardianJobsTermsAndConditionsPageWhenJobsClientIdSet(),
+ );
+ it(...SignIn.linksToTheGuardianJobsPrivacyPolicyPageWhenJobsClientIdSet());
+ });
+
+ it(...SignIn.persistsTheClientIdWhenNavigatingAway());
+ it(...SignIn.appliesFormValidationToEmailAndPasswordInputFields());
+ it(...SignIn.showsAMessageWhenCredentialsAreInvalid());
+ it(...SignIn.correctlySignsInAnExistingUser());
+ it(...SignIn.navigatesToResetPassword());
+ it(...SignIn.navigatesToRegistration());
+ it(...SignIn.respectsTheReturnUrlQueryParam());
+ it(...SignIn.removesEncryptedEmailParameterFromQueryString());
+ it(
+ ...SignIn.removesEncryptedEmailParameterAndPreservesAllOtherValidParameters(),
+ );
+ it(
+ ...SignIn.showsRecaptchaErrorsWhenTheUserTriesToSignInOfflineAndAllowsSignInWhenBackOnline(),
+ );
+ it(...SignIn.redirectsToOptInPrompt());
+ it(...SignIn.hitsAccessTokenRateLimitAndRecoversTokenAfterTimeout());
+
+ it(...SignIn.redirectsCorrectlyForSocialSignIn());
+ it(
+ ...SignIn.showsAnErrorMessageAndInformationParagraphWhenAccountLinkingRequiredErrorParameterIsPresent(),
+ );
+ it(
+ ...SignIn.doesNotDisplaySocialButtonsWhenAccountLinkingRequiredErrorParameterIsPresent(),
+ );
+
+ it('sets emailValidated flag on oauth callback', () => {
+ // this is a specific test case for new user registrations in Okta
+ // In Okta new social registered users are added to the GuardianUser-EmailValidated group
+ // by default, but the custom emailValidated field is not defined/set to false
+ // this causes problems in legacy code, where the emailValidated flag is not set but the group is
+ // so we need to set the flag to true when the user is added to the group
+ // we do this on the oauth callback route /oauth/authorization-code/callback
+ // where we update the user profile with the emailValidated flag if the user is in the GuardianUser-EmailValidated group but the emailValidated is falsy
+
+ // This test checks this behaviour by first getting a user into this state
+ // i.e user.profile.emailValidated = false, and user groups has GuardianUser-EmailValidated
+
+ // first we have to get the id of the GuardianUser-EmailValidated group
+ cy.findEmailValidatedOktaGroupId().then((groupId) => {
+ // next we create a test user
+ cy.createTestUser({}).then(({ emailAddress, finalPassword }) => {
+ // we get the user profile object from Okta
+ cy.getTestOktaUser(emailAddress).then((user) => {
+ const { id, profile } = user;
+ // check the user profile has the emailValidated flag set to false
+ expect(profile.emailValidated).to.be.false;
+ // next check the user groups
+ cy.getOktaUserGroups(id).then((groups) => {
+ // make sure the user is not in the GuardianUser-EmailValidated group
+ const group = groups.find((g) => g.id === groupId);
+ expect(group).not.to.exist;
+
+ // and add them to the group if this is the case
+ cy.addOktaUserToGroup(id, groupId);
+
+ // at this point the user is in the correct state
+ // so we attempt to sign them in
+ cy.visit(
+ `/signin?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/consents`,
+ )}`,
+ );
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', '/consents');
+
+ // at this point the oauth callback route will have run, so we can recheck the user profile to see if the emailValidated flag has been set
+ cy.getTestOktaUser(id).then((user) => {
+ const { profile } = user;
+ expect(profile.emailValidated).to.be.true;
+ });
+
+ // and the user should also be in the group
+ cy.getOktaUserGroups(id).then((groups) => {
+ const group = groups.find((g) => g.id === groupId);
+ expect(group).to.exist;
+ });
+ });
+ });
+ });
+ });
+ });
+ context('Okta session refresh', () => {
+ it('refreshes a valid Okta session', () => {
+ // Create a validated test user
+ cy.createTestUser({ isUserEmailValidated: true }).then(
+ ({ emailAddress, finalPassword }) => {
+ // Sign our new user in
+ cy.visit(
+ `/signin?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/consents`,
+ )}`,
+ );
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', '/consents');
+
+ // Get the current session data
+ cy.getCookie('sid').then((originalSidCookie) => {
+ expect(originalSidCookie).to.exist;
+
+ // Refresh our user session
+ cy.visit(
+ `/signin/refresh?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/consents`,
+ )}`,
+ );
+ cy.url().should('include', '/consents');
+
+ // Get the refreshed session data
+ cy.getCookie('sid').then((newSidCookie) => {
+ expect(newSidCookie).to.exist;
+ expect(newSidCookie?.value).to.equal(originalSidCookie?.value);
+ if (newSidCookie?.expiry && originalSidCookie?.expiry) {
+ expect(newSidCookie?.expiry).to.be.greaterThan(
+ originalSidCookie?.expiry,
+ );
+ }
+ });
+ });
+ },
+ );
+ });
+ it('sends a client with the Okta cookie and an invalid Okta session to the redirectUrl', () => {
+ // Create a validated test user
+ cy.createTestUser({ isUserEmailValidated: true }).then(
+ ({ emailAddress, finalPassword }) => {
+ // Sign our new user in
+ cy.visit(
+ `/signin?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/consents`,
+ )}`,
+ );
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', '/consents');
+
+ // Get the current session data
+ cy.getCookie('sid').then((sidCookie) => {
+ // Close the user's current session in Okta
+ cy.closeCurrentOktaSession(sidCookie?.value).then(() => {
+ // Refresh our user session
+ cy.visit(
+ `/signin/refresh?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/consents`,
+ )}`,
+ );
+ cy.url().should('include', '/consents');
+ });
+ });
+ },
+ );
+ });
+ it('sends a client without the Okta cookie to the redirectUrl', () => {
+ // Create a validated test user
+ cy.createTestUser({ isUserEmailValidated: true }).then(
+ ({ emailAddress, finalPassword }) => {
+ // Sign our new user in
+ cy.visit(
+ `/signin?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/consents`,
+ )}`,
+ );
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', '/consents');
+
+ // Delete the Okta sid cookie
+ // strange behaviour form Cypress 12
+ // where we need to delete cookie from both domains
+ // to get the test to pass
+ // cypress 12 seems to have issues with hostOnly cookies not being removed or persisting after clear
+ // https://github.com/cypress-io/cypress/issues/25174
+ cy.clearCookie('sid', {
+ domain: Cypress.env('BASE_URI'),
+ });
+ cy.clearCookie('sid', {
+ domain: `.${Cypress.env('BASE_URI')}`,
+ });
+
+ // Visit the refresh endpoint
+ cy.visit(
+ `/signin/refresh?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/consents`,
+ )}`,
+ );
+ cy.url().should('include', '/consents');
+
+ cy.getCookie('sid').should('not.exist');
+ },
+ );
+ });
+ it('sends a client with neither Okta nor Identity cookies to /signin', () => {
+ // Create a validated test user
+ cy.createTestUser({ isUserEmailValidated: true }).then(
+ ({ emailAddress, finalPassword }) => {
+ // Sign our new user in
+ cy.visit(
+ `/signin?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/consents`,
+ )}`,
+ );
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', '/consents');
+
+ // Delete all cookies (Okta and IDAPI)
+ cy.clearCookies();
+
+ // Visit the refresh endpoint
+ cy.visit(
+ `/signin/refresh?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/consents`,
+ )}`,
+ );
+ cy.url().should('include', '/signin');
+
+ cy.getCookie('sid').should('not.exist');
+ cy.getCookie('sc_gu_u').should('not.exist');
+ cy.getCookie('sc_gu_la').should('not.exist');
+ },
+ );
+ });
+ it('leaves the last access cookie unchanged when refreshing a valid Okta session', () => {
+ // Create a validated test user
+ cy.createTestUser({ isUserEmailValidated: true }).then(
+ ({ emailAddress, finalPassword }) => {
+ // Sign our new user in
+ cy.visit(
+ `/signin?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/consents`,
+ )}`,
+ );
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', '/consents');
+
+ // Get the current session data
+ cy.getCookie('SC_GU_LA').then((originalLastAccessCookie) => {
+ cy.getCookie('SC_GU_U').then((originalSecureIdapiCookie) => {
+ expect(originalLastAccessCookie).to.exist;
+ expect(originalSecureIdapiCookie).to.exist;
+
+ // Refresh our user session
+ cy.visit(
+ `/signin/refresh?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/consents`,
+ )}`,
+ );
+ cy.url().should('include', '/consents');
+
+ // Expect the last access cookie to be unchanged
+ cy.getCookie('SC_GU_LA').then((lastAccessCookie) => {
+ expect(lastAccessCookie).to.exist;
+ expect(lastAccessCookie?.value).to.equal(
+ originalLastAccessCookie?.value,
+ );
+ expect(lastAccessCookie?.expiry).to.equal(
+ originalLastAccessCookie?.expiry,
+ );
+ });
+
+ // Expect other Idapi cookies to have changed
+ cy.getCookie('SC_GU_U').then((secureIdapiCookie) => {
+ expect(secureIdapiCookie).to.exist;
+ expect(secureIdapiCookie?.value).not.to.equal(
+ originalSecureIdapiCookie?.value,
+ );
+ if (
+ secureIdapiCookie?.expiry &&
+ originalSecureIdapiCookie?.expiry
+ ) {
+ expect(secureIdapiCookie?.expiry).to.be.greaterThan(
+ originalSecureIdapiCookie?.expiry,
+ );
+ }
+ });
+ });
+ });
+ },
+ );
+ });
+ });
+
+ context('Okta unvalidated email flow', () => {
+ it('Sends a user with an unvalidated email a reset password email on sign in', () => {
+ cy
+ .createTestUser({
+ isUserEmailValidated: false,
+ })
+ ?.then(({ emailAddress, finalPassword }) => {
+ const timeRequestWasMade = new Date();
+ cy.visit('/signin');
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', '/signin/email-sent');
+ cy.contains(
+ 'For security reasons we need you to change your password.',
+ );
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ // Ensure the user's authentication cookies are not set
+ cy.getCookie('sid').then((sidCookie) => {
+ expect(sidCookie).to.not.exist;
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(({ links, body, token }) => {
+ expect(body).to.have.string(
+ 'Because your security is extremely important to us, we have changed our password policy.',
+ );
+ expect(body).to.have.string('Reset password');
+ expect(links.length).to.eq(2);
+ const resetPasswordLink = links.find(
+ (s) => s.text?.includes('Reset password'),
+ );
+ expect(resetPasswordLink?.href ?? '').to.have.string(
+ 'reset-password',
+ );
+ cy.visit(`/reset-password/${token}`);
+ cy.contains(emailAddress);
+ cy.contains('Reset password');
+ });
+ });
+ });
+ });
+ });
+
+ context('Okta session exists on /signin', () => {
+ beforeEach(() => {
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', 'https://m.code.dev-theguardian.com/', (req) => {
+ req.reply(200);
+ });
+ });
+
+ it('shows the signed in as page', () => {
+ // Create a validated test user
+ cy.createTestUser({ isUserEmailValidated: true }).then(
+ ({ emailAddress, finalPassword }) => {
+ // Sign our new user in
+ cy.visit(
+ `/signin?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/consents`,
+ )}`,
+ );
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', '/consents');
+
+ // Get the current session data
+ cy.getCookie('sid').then((originalSidCookie) => {
+ expect(originalSidCookie).to.exist;
+
+ // Visit sign in again
+ cy.visit(
+ `/signin?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/consents`,
+ )}`,
+ );
+ cy.url().should('include', '/signin');
+
+ cy.contains('Sign in to the Guardian');
+ cy.contains('You are signed in with');
+ cy.contains(emailAddress);
+ cy.contains('Continue')
+ .should('have.attr', 'href')
+ .and(
+ 'include',
+ `https://${Cypress.env(
+ 'BASE_URI',
+ )}/signin/refresh?returnUrl=https%3A%2F%2Fprofile.thegulocal.com%2Fconsents`,
+ );
+ cy.contains('a', 'Sign in')
+ .should('have.attr', 'href')
+ .and('include', '/signout?returnUrl=');
+ cy.contains('Sign in with a different email');
+ });
+ },
+ );
+ });
+ });
});
diff --git a/cypress/integration/ete-okta/sign_out.5.cy.ts b/cypress/integration/ete-okta/sign_out.5.cy.ts
index ec23d6dbac..601884ec9a 100644
--- a/cypress/integration/ete-okta/sign_out.5.cy.ts
+++ b/cypress/integration/ete-okta/sign_out.5.cy.ts
@@ -1,57 +1,57 @@
describe('Sign out flow', () => {
- context('Signs a user out', () => {
- it('Removes Okta cookies and dotcom cookies when signing out', () => {
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress, finalPassword }) => {
- // Disable redirect to /signin/success by default
- cy.setCookie(
- 'GU_ran_experiments',
- new URLSearchParams({
- OptInPromptPostSignIn: Date.now().toString(),
- }).toString(),
- );
+ context('Signs a user out', () => {
+ it('Removes Okta cookies and dotcom cookies when signing out', () => {
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress, finalPassword }) => {
+ // Disable redirect to /signin/success by default
+ cy.setCookie(
+ 'GU_ran_experiments',
+ new URLSearchParams({
+ OptInPromptPostSignIn: Date.now().toString(),
+ }).toString(),
+ );
- // load the consents page as its on the same domain
- const postSignInReturnUrl = `https://${Cypress.env(
- 'BASE_URI',
- )}/consents/data`;
- const visitUrl = `/signin?returnUrl=${encodeURIComponent(
- postSignInReturnUrl,
- )}`;
- cy.visit(visitUrl);
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- // check sign in has worked first
- cy.url().should('include', `/consents/data`);
- // check session cookie is set
- cy.getCookie('sid').should('exist');
- // check idapi cookies are set
- cy.getCookie('SC_GU_U').should('exist');
- cy.getCookie('SC_GU_LA').should('exist');
- cy.getCookie('GU_U').should('exist');
+ // load the consents page as its on the same domain
+ const postSignInReturnUrl = `https://${Cypress.env(
+ 'BASE_URI',
+ )}/consents/data`;
+ const visitUrl = `/signin?returnUrl=${encodeURIComponent(
+ postSignInReturnUrl,
+ )}`;
+ cy.visit(visitUrl);
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ // check sign in has worked first
+ cy.url().should('include', `/consents/data`);
+ // check session cookie is set
+ cy.getCookie('sid').should('exist');
+ // check idapi cookies are set
+ cy.getCookie('SC_GU_U').should('exist');
+ cy.getCookie('SC_GU_LA').should('exist');
+ cy.getCookie('GU_U').should('exist');
- // attempt to sign out and redirect to sign in to make sure the cookies are removed
- // and the signed in as page isn't visible
- const postSignOutReturnUrl = `https://${Cypress.env(
- 'BASE_URI',
- )}/signin`;
- cy.visit(
- `/signout?returnUrl=${encodeURIComponent(postSignOutReturnUrl)}`,
- );
- // cypress 12 seems to have issues with hostOnly cookies not being removed or persisting after clear
- // https://github.com/cypress-io/cypress/issues/25174
- // so for now I've changed this check to make sure the "Signed in as" page isn't visible
- // cy.getCookie('sid').should('not.exist');
- cy.contains('You are signed in with').should('not.exist');
- // check cookies are removed
- cy.getCookie('SC_GU_U').should('not.exist');
- cy.getCookie('SC_GU_LA').should('not.exist');
- cy.getCookie('GU_U').should('not.exist');
- });
- });
- });
+ // attempt to sign out and redirect to sign in to make sure the cookies are removed
+ // and the signed in as page isn't visible
+ const postSignOutReturnUrl = `https://${Cypress.env(
+ 'BASE_URI',
+ )}/signin`;
+ cy.visit(
+ `/signout?returnUrl=${encodeURIComponent(postSignOutReturnUrl)}`,
+ );
+ // cypress 12 seems to have issues with hostOnly cookies not being removed or persisting after clear
+ // https://github.com/cypress-io/cypress/issues/25174
+ // so for now I've changed this check to make sure the "Signed in as" page isn't visible
+ // cy.getCookie('sid').should('not.exist');
+ cy.contains('You are signed in with').should('not.exist');
+ // check cookies are removed
+ cy.getCookie('SC_GU_U').should('not.exist');
+ cy.getCookie('SC_GU_LA').should('not.exist');
+ cy.getCookie('GU_U').should('not.exist');
+ });
+ });
+ });
});
diff --git a/cypress/integration/ete/change_email/change_email.2.cy.ts b/cypress/integration/ete/change_email/change_email.2.cy.ts
index eaf6e51e61..0f297d4a64 100644
--- a/cypress/integration/ete/change_email/change_email.2.cy.ts
+++ b/cypress/integration/ete/change_email/change_email.2.cy.ts
@@ -1,38 +1,38 @@
import { randomMailosaurEmail } from '../../../support/commands/testUser';
describe('Change email', () => {
- it('change email flow successful', () => {
- cy.createTestUser({
- isUserEmailValidated: true,
- }).then(({ cookies }) => {
- // SC_GU_U is required for the cy.updateTestUser
- const scGuU = cookies.find((cookie) => cookie.key === 'SC_GU_U');
- if (!scGuU) throw new Error('SC_GU_U cookie not found');
- cy.setCookie('SC_GU_U', scGuU?.value);
+ it('change email flow successful', () => {
+ cy.createTestUser({
+ isUserEmailValidated: true,
+ }).then(({ cookies }) => {
+ // SC_GU_U is required for the cy.updateTestUser
+ const scGuU = cookies.find((cookie) => cookie.key === 'SC_GU_U');
+ if (!scGuU) throw new Error('SC_GU_U cookie not found');
+ cy.setCookie('SC_GU_U', scGuU?.value);
- const timeRequestWasMade = new Date();
+ const timeRequestWasMade = new Date();
- const newEmail = randomMailosaurEmail();
+ const newEmail = randomMailosaurEmail();
- cy.updateTestUser({
- primaryEmailAddress: newEmail,
- });
+ cy.updateTestUser({
+ primaryEmailAddress: newEmail,
+ });
- cy.checkForEmailAndGetDetails(
- newEmail,
- timeRequestWasMade,
- /change-email\/([^"]*)/,
- ).then(({ token }) => {
- cy.visit(`/change-email/${token}`);
- cy.contains('Success! Your email address has been updated.');
- });
- });
- });
+ cy.checkForEmailAndGetDetails(
+ newEmail,
+ timeRequestWasMade,
+ /change-email\/([^"]*)/,
+ ).then(({ token }) => {
+ cy.visit(`/change-email/${token}`);
+ cy.contains('Success! Your email address has been updated.');
+ });
+ });
+ });
- it('change email flow unsuccessful', () => {
- cy.visit(`/change-email/bad_token`);
- cy.contains(
- 'The email change link you followed has expired or was invalid.',
- );
- });
+ it('change email flow unsuccessful', () => {
+ cy.visit(`/change-email/bad_token`);
+ cy.contains(
+ 'The email change link you followed has expired or was invalid.',
+ );
+ });
});
diff --git a/cypress/integration/ete/consent_token/consent_token.2.cy.ts b/cypress/integration/ete/consent_token/consent_token.2.cy.ts
index fe9903a90c..54eece99a3 100644
--- a/cypress/integration/ete/consent_token/consent_token.2.cy.ts
+++ b/cypress/integration/ete/consent_token/consent_token.2.cy.ts
@@ -1,46 +1,46 @@
describe('Consent token flow', () => {
- it('redirects to the success route when supplied a valid token by a logged in user', () => {
- cy.createTestUser({
- isUserEmailValidated: true,
- }).then(({ emailAddress, cookies }) => {
- // SC_GU_U is required for the cy.getTestUserDetails
- const scGuU = cookies.find((cookie) => cookie.key === 'SC_GU_U');
- if (!scGuU) throw new Error('SC_GU_U cookie not found');
- cy.setCookie('SC_GU_U', scGuU?.value);
- // SC_GU_LA is required for the cy.getTestUserDetails
- const scGuLa = cookies.find((cookie) => cookie.key === 'SC_GU_LA');
- if (!scGuLa) throw new Error('SC_GU_LA cookie not found');
- cy.setCookie('SC_GU_LA', scGuLa?.value);
- cy.sendConsentEmail({
- emailAddress,
- consents: ['jobs'],
- }).then(() => {
- const timeRequestWasMade = new Date();
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /consent-token\/([^"]*)/,
- ).then(({ token }) => {
- cy.visit(`/consent-token/${token}/accept`, {
- failOnStatusCode: false,
- });
- // /consents/thank-you isn't hosted by Gateway so all we need to check
- // is that the cy.visit() redirected successfully, so intercept the request
- // and return a 200
- cy.intercept('GET', '/consents/thank-you', (req) => {
- req.reply(200);
- });
- });
- });
- });
- });
+ it('redirects to the success route when supplied a valid token by a logged in user', () => {
+ cy.createTestUser({
+ isUserEmailValidated: true,
+ }).then(({ emailAddress, cookies }) => {
+ // SC_GU_U is required for the cy.getTestUserDetails
+ const scGuU = cookies.find((cookie) => cookie.key === 'SC_GU_U');
+ if (!scGuU) throw new Error('SC_GU_U cookie not found');
+ cy.setCookie('SC_GU_U', scGuU?.value);
+ // SC_GU_LA is required for the cy.getTestUserDetails
+ const scGuLa = cookies.find((cookie) => cookie.key === 'SC_GU_LA');
+ if (!scGuLa) throw new Error('SC_GU_LA cookie not found');
+ cy.setCookie('SC_GU_LA', scGuLa?.value);
+ cy.sendConsentEmail({
+ emailAddress,
+ consents: ['jobs'],
+ }).then(() => {
+ const timeRequestWasMade = new Date();
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /consent-token\/([^"]*)/,
+ ).then(({ token }) => {
+ cy.visit(`/consent-token/${token}/accept`, {
+ failOnStatusCode: false,
+ });
+ // /consents/thank-you isn't hosted by Gateway so all we need to check
+ // is that the cy.visit() redirected successfully, so intercept the request
+ // and return a 200
+ cy.intercept('GET', '/consents/thank-you', (req) => {
+ req.reply(200);
+ });
+ });
+ });
+ });
+ });
- it('shows the email sent page when supplied an invalid token', () => {
- const invalidToken = 'invalid-consent-token';
- cy.visit(`/consent-token/${invalidToken}/accept`);
- cy.contains('This link has expired.');
- cy.get('button[type=submit]').click();
- cy.url().should('include', '/consent-token/email-sent');
- cy.contains('Check your email inbox');
- });
+ it('shows the email sent page when supplied an invalid token', () => {
+ const invalidToken = 'invalid-consent-token';
+ cy.visit(`/consent-token/${invalidToken}/accept`);
+ cy.contains('This link has expired.');
+ cy.get('button[type=submit]').click();
+ cy.url().should('include', '/consent-token/email-sent');
+ cy.contains('Check your email inbox');
+ });
});
diff --git a/cypress/integration/ete/registration/register.2.cy.ts b/cypress/integration/ete/registration/register.2.cy.ts
index 28c8e10e18..40bd8b767b 100644
--- a/cypress/integration/ete/registration/register.2.cy.ts
+++ b/cypress/integration/ete/registration/register.2.cy.ts
@@ -1,311 +1,311 @@
import { randomMailosaurEmail } from '../../../support/commands/testUser';
describe('Registration flow', () => {
- context('Terms and Conditions links', () => {
- it('links to the Google terms of service page', () => {
- const googleTermsUrl = 'https://policies.google.com/terms';
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', googleTermsUrl, (req) => {
- req.reply(200);
- });
- cy.visit('/signin?useIdapi=true');
- cy.contains('terms of service').click();
- cy.url().should('eq', googleTermsUrl);
- });
-
- it('links to the Google privacy policy page', () => {
- const googlePrivacyPolicyUrl = 'https://policies.google.com/privacy';
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', googlePrivacyPolicyUrl, (req) => {
- req.reply(200);
- });
- cy.visit('/signin?useIdapi=true');
- cy.contains('This service is protected by reCAPTCHA and the Google')
- .contains('privacy policy')
- .click();
- cy.url().should('eq', googlePrivacyPolicyUrl);
- });
-
- it('links to the Guardian terms and conditions page', () => {
- const guardianTermsOfServiceUrl =
- 'https://www.theguardian.com/help/terms-of-service';
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', guardianTermsOfServiceUrl, (req) => {
- req.reply(200);
- });
- cy.visit('/signin?useIdapi=true');
- cy.contains('terms & conditions').click();
- cy.url().should('eq', guardianTermsOfServiceUrl);
- });
-
- it('links to the Guardian privacy policy page', () => {
- const guardianPrivacyPolicyUrl =
- 'https://www.theguardian.com/help/privacy-policy';
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', guardianPrivacyPolicyUrl, (req) => {
- req.reply(200);
- });
- cy.visit('/signin?useIdapi=true');
- cy.contains('For information about how we use your data')
- .contains('privacy policy')
- .click();
- cy.url().should('eq', guardianPrivacyPolicyUrl);
- });
-
- it('links to the Guardian jobs terms and conditions page when jobs clientId set', () => {
- const guardianJobsTermsOfServiceUrl =
- 'https://jobs.theguardian.com/terms-and-conditions/';
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', guardianJobsTermsOfServiceUrl, (req) => {
- req.reply(200);
- });
- cy.visit('/signin?clientId=jobs&useIdapi=true');
- cy.contains('Guardian Jobs terms & conditions').click();
- cy.url().should('eq', guardianJobsTermsOfServiceUrl);
- });
-
- it('links to the Guardian jobs privacy policy page when jobs clientId set', () => {
- const guardianJobsPrivacyPolicyUrl =
- 'https://jobs.theguardian.com/privacy-policy/';
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', guardianJobsPrivacyPolicyUrl, (req) => {
- req.reply(200);
- });
- cy.visit('/signin?clientId=jobs&useIdapi=true');
- cy.contains('For information about how we use your data')
- .contains('Guardian Jobs privacy policy')
- .click();
- cy.url().should('eq', guardianJobsPrivacyPolicyUrl);
- });
- });
- it('persists the clientId when navigating away', () => {
- cy.visit('/register?clientId=jobs&useIdapi=true');
- cy.contains('Sign in').click();
- cy.url().should('contain', 'clientId=jobs');
- });
- it('does not proceed when no email provided', () => {
- cy.visit('/register');
- cy.get('[data-cy="main-form-submit-button"]').click();
- // check that form isn't submitted
- cy.url().should('not.contain', 'returnUrl');
- cy.contains('Please enter your email.');
- });
-
- it('does not proceed when invalid email provided', () => {
- cy.visit('/register?useIdapi=true');
- const invalidEmail = 'invalid.email.com';
- cy.get('input[name=email]').type(invalidEmail);
- cy.get('[data-cy="main-form-submit-button"]').click();
- // check that form isn't submitted
- cy.url().should('not.contain', 'returnUrl');
- cy.contains('Please enter a valid email format.');
- });
-
- it('successfully registers using an email with no existing account', () => {
- const encodedReturnUrl =
- 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
- const encodedRef = 'https%3A%2F%2Fm.theguardian.com';
- const refViewId = 'testRefViewId';
- const clientId = 'jobs';
- const unregisteredEmail = randomMailosaurEmail();
-
- cy.visit(
- `/register?returnUrl=${encodedReturnUrl}&ref=${encodedRef}&refViewId=${refViewId}&clientId=${clientId}&useIdapi=true`,
- );
- const timeRequestWasMade = new Date();
- cy.get('input[name=email]').type(unregisteredEmail);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(unregisteredEmail);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- unregisteredEmail,
- timeRequestWasMade,
- /welcome\/([^"]*)/,
- ).then(({ body, token }) => {
- expect(body).to.have.string('Complete registration');
- expect(body).to.have.string('returnUrl=' + encodedReturnUrl);
- expect(body).to.have.string('ref=' + encodedRef);
- expect(body).to.have.string('refViewId=' + refViewId);
- expect(body).to.have.string('clientId=' + clientId);
- cy.visit(`/welcome/${token}`);
- cy.contains('Save and continue');
- });
- });
-
- it('sends user an account exists email for user with existing account with password trying to register, clicks sign in, taken to /signin', () => {
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.visit('/register?useIdapi=true');
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(emailAddress, timeRequestWasMade).then(
- ({ links, body }) => {
- expect(body).to.have.string('This account already exists');
- expect(body).to.have.string('Sign in');
- expect(body).to.have.string('Reset password');
-
- expect(links.length).to.eq(3);
-
- const signInLink = links.find((link) => link.text === 'Sign in');
-
- expect(signInLink).not.to.be.undefined;
- expect(signInLink?.href ?? '').to.include('/signin');
-
- const signInUrl = new URL(signInLink?.href ?? '');
-
- cy.visit(signInUrl.pathname);
- cy.url().should('include', '/signin');
- },
- );
- });
- });
-
- it('sends user an account exists email for user with existing account with password trying to register, clicks reset password on email', () => {
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.visit('/register?useIdapi=true');
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /\/reset-password\/([^"]*)/,
- ).then(({ links, body, token }) => {
- expect(body).to.have.string('This account already exists');
- expect(body).to.have.string('Sign in');
- expect(body).to.have.string('Reset password');
- expect(body).to.have.string('This link is valid for 60 minutes.');
-
- expect(links.length).to.eq(3);
-
- const passwordResetLink = links.find(
- (link) => link.text === 'Reset password',
- );
-
- expect(passwordResetLink).not.to.be.undefined;
-
- cy.visit(`/reset-password/${token}`);
- cy.contains('Reset password');
- });
- });
- });
-
- it('sends user an account exists without password email for user with existing account without password trying to register, clicks create password on email', () => {
- cy
- .createTestUser({
- isUserEmailValidated: false,
- isGuestUser: true,
- })
- ?.then(({ emailAddress }) => {
- cy.visit('/register?useIdapi=true');
- const timeRequestWasMade = new Date();
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /\/set-password\/([^"]*)/,
- ).then(({ links, body, token }) => {
- expect(body).to.have.string('This account already exists');
- expect(body).to.have.string(
- 'To continue to your account please click below to create a password.',
- );
- expect(body).to.have.string('This link is valid for 60 minutes.');
- expect(body).to.have.string('Create password');
-
- expect(links.length).to.eq(2);
-
- const createPasswordLink = links.find(
- (link) => link.text === 'Create password',
- );
-
- expect(createPasswordLink).not.to.be.undefined;
-
- cy.visit(`/set-password/${token}`);
- cy.contains('Create password');
- });
- });
- });
-
- it('shows reCAPTCHA errors when the user tries to register offline and allows registration when back online', () => {
- const unregisteredEmail = randomMailosaurEmail();
-
- cy.visit('/register?useIdapi=true');
-
- // Simulate going offline by failing to reCAPTCHA POST request.
- cy.intercept({
- method: 'POST',
- url: 'https://www.google.com/recaptcha/api2/**',
- times: 1,
- });
-
- cy.get('input[name=email').type(unregisteredEmail);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.contains('Google reCAPTCHA verification failed. Please try again.');
-
- // On second click, an expanded error is shown.
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Google reCAPTCHA verification failed.');
- cy.contains('Report this error').should(
- 'have.attr',
- 'href',
- 'https://manage.theguardian.com/help-centre/contact-us',
- );
- cy.contains('If the problem persists please try the following:');
-
- const timeRequestWasMade = new Date();
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains(
- 'Google reCAPTCHA verification failed. Please try again.',
- ).should('not.exist');
-
- cy.contains('Check your email inbox');
- cy.contains(unregisteredEmail);
- cy.checkForEmailAndGetDetails(unregisteredEmail, timeRequestWasMade).then(
- ({ body }) => {
- expect(body).to.have.string('Complete registration');
- },
- );
- });
+ context('Terms and Conditions links', () => {
+ it('links to the Google terms of service page', () => {
+ const googleTermsUrl = 'https://policies.google.com/terms';
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', googleTermsUrl, (req) => {
+ req.reply(200);
+ });
+ cy.visit('/signin?useIdapi=true');
+ cy.contains('terms of service').click();
+ cy.url().should('eq', googleTermsUrl);
+ });
+
+ it('links to the Google privacy policy page', () => {
+ const googlePrivacyPolicyUrl = 'https://policies.google.com/privacy';
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', googlePrivacyPolicyUrl, (req) => {
+ req.reply(200);
+ });
+ cy.visit('/signin?useIdapi=true');
+ cy.contains('This service is protected by reCAPTCHA and the Google')
+ .contains('privacy policy')
+ .click();
+ cy.url().should('eq', googlePrivacyPolicyUrl);
+ });
+
+ it('links to the Guardian terms and conditions page', () => {
+ const guardianTermsOfServiceUrl =
+ 'https://www.theguardian.com/help/terms-of-service';
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', guardianTermsOfServiceUrl, (req) => {
+ req.reply(200);
+ });
+ cy.visit('/signin?useIdapi=true');
+ cy.contains('terms & conditions').click();
+ cy.url().should('eq', guardianTermsOfServiceUrl);
+ });
+
+ it('links to the Guardian privacy policy page', () => {
+ const guardianPrivacyPolicyUrl =
+ 'https://www.theguardian.com/help/privacy-policy';
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', guardianPrivacyPolicyUrl, (req) => {
+ req.reply(200);
+ });
+ cy.visit('/signin?useIdapi=true');
+ cy.contains('For information about how we use your data')
+ .contains('privacy policy')
+ .click();
+ cy.url().should('eq', guardianPrivacyPolicyUrl);
+ });
+
+ it('links to the Guardian jobs terms and conditions page when jobs clientId set', () => {
+ const guardianJobsTermsOfServiceUrl =
+ 'https://jobs.theguardian.com/terms-and-conditions/';
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', guardianJobsTermsOfServiceUrl, (req) => {
+ req.reply(200);
+ });
+ cy.visit('/signin?clientId=jobs&useIdapi=true');
+ cy.contains('Guardian Jobs terms & conditions').click();
+ cy.url().should('eq', guardianJobsTermsOfServiceUrl);
+ });
+
+ it('links to the Guardian jobs privacy policy page when jobs clientId set', () => {
+ const guardianJobsPrivacyPolicyUrl =
+ 'https://jobs.theguardian.com/privacy-policy/';
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', guardianJobsPrivacyPolicyUrl, (req) => {
+ req.reply(200);
+ });
+ cy.visit('/signin?clientId=jobs&useIdapi=true');
+ cy.contains('For information about how we use your data')
+ .contains('Guardian Jobs privacy policy')
+ .click();
+ cy.url().should('eq', guardianJobsPrivacyPolicyUrl);
+ });
+ });
+ it('persists the clientId when navigating away', () => {
+ cy.visit('/register?clientId=jobs&useIdapi=true');
+ cy.contains('Sign in').click();
+ cy.url().should('contain', 'clientId=jobs');
+ });
+ it('does not proceed when no email provided', () => {
+ cy.visit('/register');
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ // check that form isn't submitted
+ cy.url().should('not.contain', 'returnUrl');
+ cy.contains('Please enter your email.');
+ });
+
+ it('does not proceed when invalid email provided', () => {
+ cy.visit('/register?useIdapi=true');
+ const invalidEmail = 'invalid.email.com';
+ cy.get('input[name=email]').type(invalidEmail);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ // check that form isn't submitted
+ cy.url().should('not.contain', 'returnUrl');
+ cy.contains('Please enter a valid email format.');
+ });
+
+ it('successfully registers using an email with no existing account', () => {
+ const encodedReturnUrl =
+ 'https%3A%2F%2Fm.code.dev-theguardian.com%2Ftravel%2F2019%2Fdec%2F18%2Ffood-culture-tour-bethlehem-palestine-east-jerusalem-photo-essay';
+ const encodedRef = 'https%3A%2F%2Fm.theguardian.com';
+ const refViewId = 'testRefViewId';
+ const clientId = 'jobs';
+ const unregisteredEmail = randomMailosaurEmail();
+
+ cy.visit(
+ `/register?returnUrl=${encodedReturnUrl}&ref=${encodedRef}&refViewId=${refViewId}&clientId=${clientId}&useIdapi=true`,
+ );
+ const timeRequestWasMade = new Date();
+ cy.get('input[name=email]').type(unregisteredEmail);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(unregisteredEmail);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ unregisteredEmail,
+ timeRequestWasMade,
+ /welcome\/([^"]*)/,
+ ).then(({ body, token }) => {
+ expect(body).to.have.string('Complete registration');
+ expect(body).to.have.string('returnUrl=' + encodedReturnUrl);
+ expect(body).to.have.string('ref=' + encodedRef);
+ expect(body).to.have.string('refViewId=' + refViewId);
+ expect(body).to.have.string('clientId=' + clientId);
+ cy.visit(`/welcome/${token}`);
+ cy.contains('Save and continue');
+ });
+ });
+
+ it('sends user an account exists email for user with existing account with password trying to register, clicks sign in, taken to /signin', () => {
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.visit('/register?useIdapi=true');
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(emailAddress, timeRequestWasMade).then(
+ ({ links, body }) => {
+ expect(body).to.have.string('This account already exists');
+ expect(body).to.have.string('Sign in');
+ expect(body).to.have.string('Reset password');
+
+ expect(links.length).to.eq(3);
+
+ const signInLink = links.find((link) => link.text === 'Sign in');
+
+ expect(signInLink).not.to.be.undefined;
+ expect(signInLink?.href ?? '').to.include('/signin');
+
+ const signInUrl = new URL(signInLink?.href ?? '');
+
+ cy.visit(signInUrl.pathname);
+ cy.url().should('include', '/signin');
+ },
+ );
+ });
+ });
+
+ it('sends user an account exists email for user with existing account with password trying to register, clicks reset password on email', () => {
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.visit('/register?useIdapi=true');
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /\/reset-password\/([^"]*)/,
+ ).then(({ links, body, token }) => {
+ expect(body).to.have.string('This account already exists');
+ expect(body).to.have.string('Sign in');
+ expect(body).to.have.string('Reset password');
+ expect(body).to.have.string('This link is valid for 60 minutes.');
+
+ expect(links.length).to.eq(3);
+
+ const passwordResetLink = links.find(
+ (link) => link.text === 'Reset password',
+ );
+
+ expect(passwordResetLink).not.to.be.undefined;
+
+ cy.visit(`/reset-password/${token}`);
+ cy.contains('Reset password');
+ });
+ });
+ });
+
+ it('sends user an account exists without password email for user with existing account without password trying to register, clicks create password on email', () => {
+ cy
+ .createTestUser({
+ isUserEmailValidated: false,
+ isGuestUser: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.visit('/register?useIdapi=true');
+ const timeRequestWasMade = new Date();
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /\/set-password\/([^"]*)/,
+ ).then(({ links, body, token }) => {
+ expect(body).to.have.string('This account already exists');
+ expect(body).to.have.string(
+ 'To continue to your account please click below to create a password.',
+ );
+ expect(body).to.have.string('This link is valid for 60 minutes.');
+ expect(body).to.have.string('Create password');
+
+ expect(links.length).to.eq(2);
+
+ const createPasswordLink = links.find(
+ (link) => link.text === 'Create password',
+ );
+
+ expect(createPasswordLink).not.to.be.undefined;
+
+ cy.visit(`/set-password/${token}`);
+ cy.contains('Create password');
+ });
+ });
+ });
+
+ it('shows reCAPTCHA errors when the user tries to register offline and allows registration when back online', () => {
+ const unregisteredEmail = randomMailosaurEmail();
+
+ cy.visit('/register?useIdapi=true');
+
+ // Simulate going offline by failing to reCAPTCHA POST request.
+ cy.intercept({
+ method: 'POST',
+ url: 'https://www.google.com/recaptcha/api2/**',
+ times: 1,
+ });
+
+ cy.get('input[name=email').type(unregisteredEmail);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.contains('Google reCAPTCHA verification failed. Please try again.');
+
+ // On second click, an expanded error is shown.
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Google reCAPTCHA verification failed.');
+ cy.contains('Report this error').should(
+ 'have.attr',
+ 'href',
+ 'https://manage.theguardian.com/help-centre/contact-us',
+ );
+ cy.contains('If the problem persists please try the following:');
+
+ const timeRequestWasMade = new Date();
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains(
+ 'Google reCAPTCHA verification failed. Please try again.',
+ ).should('not.exist');
+
+ cy.contains('Check your email inbox');
+ cy.contains(unregisteredEmail);
+ cy.checkForEmailAndGetDetails(unregisteredEmail, timeRequestWasMade).then(
+ ({ body }) => {
+ expect(body).to.have.string('Complete registration');
+ },
+ );
+ });
});
diff --git a/cypress/integration/ete/registration/register_email_sent.3.cy.ts b/cypress/integration/ete/registration/register_email_sent.3.cy.ts
index 7eb639f00a..b53dafcd16 100644
--- a/cypress/integration/ete/registration/register_email_sent.3.cy.ts
+++ b/cypress/integration/ete/registration/register_email_sent.3.cy.ts
@@ -2,202 +2,202 @@ import { injectAndCheckAxe } from '../../../support/cypress-axe';
import { randomMailosaurEmail } from '../../../support/commands/testUser';
describe('Registration email sent page', () => {
- context('A11y checks', () => {
- it('has no detectable a11y violations on the registration email sent page', () => {
- cy.visit('/register/email-sent?useIdapi=true');
- injectAndCheckAxe();
- });
- });
-
- it('should resend "Complete Registration" email when a new user registers which is same as initial email sent', () => {
- const unregisteredEmail = randomMailosaurEmail();
-
- const clientId = 'jobs';
- cy.visit(`/register?clientId=${clientId}&useIdapi=true`);
- cy.get('input[name=email]').type(unregisteredEmail);
- const timeRequestWasMadeInitialEmail = new Date();
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(unregisteredEmail);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- // test and delete initial email
- cy.checkForEmailAndGetDetails(
- unregisteredEmail,
- timeRequestWasMadeInitialEmail,
- ).then(({ body }) => {
- expect(body).to.have.string('Complete registration');
- });
-
- const timeRequestWasMade = new Date();
- cy.contains('Resend email').click();
- cy.contains('Check your email inbox');
- cy.contains(unregisteredEmail);
-
- // test and delete resent email
- cy.checkForEmailAndGetDetails(unregisteredEmail, timeRequestWasMade).then(
- ({ body }) => {
- expect(body).to.have.string('Complete registration');
- expect(body).to.have.string('clientId=' + clientId);
- },
- );
- });
-
- it('should resend account exists without password email when an existing user without password registers which is same as initial email sent', () => {
- cy
- .createTestUser({
- isUserEmailValidated: false,
- isGuestUser: true,
- })
- ?.then(({ emailAddress }) => {
- cy.visit('/register?useIdapi=true');
- cy.get('input[name=email]').type(emailAddress);
- const timeRequestWasMadeInitialEmail = new Date();
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- // test and delete initial email
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMadeInitialEmail,
- ).then(({ body }) => {
- expect(body).to.have.string('This account already exists');
- expect(body).to.have.string(
- 'To continue to your account please click below to create a password.',
- );
- expect(body).to.have.string('This link is valid for 60 minutes.');
- expect(body).to.have.string('Create password');
- });
-
- const timeRequestWasMade = new Date();
- cy.contains('Resend email').click();
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
-
- // test and delete resent email
- cy.checkForEmailAndGetDetails(emailAddress, timeRequestWasMade).then(
- ({ body }) => {
- expect(body).to.have.string('This account already exists');
- expect(body).to.have.string(
- 'To continue to your account please click below to create a password.',
- );
- expect(body).to.have.string('This link is valid for 60 minutes.');
- expect(body).to.have.string('Create password');
- },
- );
- });
- });
-
- it('should resend "Account Exists" email when an existing user with password registers which is same as initial email sent', () => {
- cy
- .createTestUser({
- isUserEmailValidated: false,
- })
- ?.then(({ emailAddress }) => {
- cy.visit('/register?useIdapi=true');
- cy.get('input[name=email]').type(emailAddress);
- const timeRequestWasMadeInitialEmail = new Date();
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMadeInitialEmail,
- ).then(({ body }) => {
- expect(body).to.have.string(
- 'You are already registered with the Guardian.',
- );
- });
-
- const timeRequestWasMade = new Date();
- cy.contains('Resend email').click();
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
-
- // test and delete resent email
- cy.checkForEmailAndGetDetails(emailAddress, timeRequestWasMade).then(
- ({ body }) => {
- expect(body).to.have.string(
- 'You are already registered with the Guardian.',
- );
- },
- );
- });
- });
-
- it('should navigate back to the correct page when change email is clicked', () => {
- cy.visit('/register/email-sent?useIdapi=true');
- cy.contains('Change email address').click();
- cy.contains('Register');
- cy.title().should('eq', 'Register | The Guardian');
- });
-
- it('should render properly if the encrypted email cookie is not set', () => {
- cy.visit('/register/email-sent?useIdapi=true');
- cy.contains('Change email address');
- cy.contains('Check your email inbox');
- });
-
- it('shows reCAPTCHA errors when the request fails', () => {
- cy
- .createTestUser({
- isUserEmailValidated: false,
- })
- ?.then(({ emailAddress }) => {
- cy.visit('/register?useIdapi=true');
- cy.get('input[name=email]').type(emailAddress);
-
- const timeRequestWasMadeInitialEmail = new Date();
-
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
-
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMadeInitialEmail,
- );
-
- // Simulate going offline by failing the reCAPTCHA POST request.
- cy.intercept({
- method: 'POST',
- url: 'https://www.google.com/recaptcha/api2/**',
- times: 1,
- });
- cy.contains('Resend email').click();
- cy.contains('Google reCAPTCHA verification failed. Please try again.');
-
- // On second click, an expanded error is shown.
- cy.contains('Resend email').click();
-
- cy.contains('Google reCAPTCHA verification failed.');
- cy.contains('If the problem persists please try the following:');
- cy.contains('userhelp@');
-
- const timeRequestWasMade = new Date();
- cy.contains('Resend email').click();
-
- cy.contains(
- 'Google reCAPTCHA verification failed. Please try again.',
- ).should('not.exist');
-
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
-
- cy.checkForEmailAndGetDetails(emailAddress, timeRequestWasMade);
- });
- });
+ context('A11y checks', () => {
+ it('has no detectable a11y violations on the registration email sent page', () => {
+ cy.visit('/register/email-sent?useIdapi=true');
+ injectAndCheckAxe();
+ });
+ });
+
+ it('should resend "Complete Registration" email when a new user registers which is same as initial email sent', () => {
+ const unregisteredEmail = randomMailosaurEmail();
+
+ const clientId = 'jobs';
+ cy.visit(`/register?clientId=${clientId}&useIdapi=true`);
+ cy.get('input[name=email]').type(unregisteredEmail);
+ const timeRequestWasMadeInitialEmail = new Date();
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(unregisteredEmail);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ // test and delete initial email
+ cy.checkForEmailAndGetDetails(
+ unregisteredEmail,
+ timeRequestWasMadeInitialEmail,
+ ).then(({ body }) => {
+ expect(body).to.have.string('Complete registration');
+ });
+
+ const timeRequestWasMade = new Date();
+ cy.contains('Resend email').click();
+ cy.contains('Check your email inbox');
+ cy.contains(unregisteredEmail);
+
+ // test and delete resent email
+ cy.checkForEmailAndGetDetails(unregisteredEmail, timeRequestWasMade).then(
+ ({ body }) => {
+ expect(body).to.have.string('Complete registration');
+ expect(body).to.have.string('clientId=' + clientId);
+ },
+ );
+ });
+
+ it('should resend account exists without password email when an existing user without password registers which is same as initial email sent', () => {
+ cy
+ .createTestUser({
+ isUserEmailValidated: false,
+ isGuestUser: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.visit('/register?useIdapi=true');
+ cy.get('input[name=email]').type(emailAddress);
+ const timeRequestWasMadeInitialEmail = new Date();
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ // test and delete initial email
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMadeInitialEmail,
+ ).then(({ body }) => {
+ expect(body).to.have.string('This account already exists');
+ expect(body).to.have.string(
+ 'To continue to your account please click below to create a password.',
+ );
+ expect(body).to.have.string('This link is valid for 60 minutes.');
+ expect(body).to.have.string('Create password');
+ });
+
+ const timeRequestWasMade = new Date();
+ cy.contains('Resend email').click();
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+
+ // test and delete resent email
+ cy.checkForEmailAndGetDetails(emailAddress, timeRequestWasMade).then(
+ ({ body }) => {
+ expect(body).to.have.string('This account already exists');
+ expect(body).to.have.string(
+ 'To continue to your account please click below to create a password.',
+ );
+ expect(body).to.have.string('This link is valid for 60 minutes.');
+ expect(body).to.have.string('Create password');
+ },
+ );
+ });
+ });
+
+ it('should resend "Account Exists" email when an existing user with password registers which is same as initial email sent', () => {
+ cy
+ .createTestUser({
+ isUserEmailValidated: false,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.visit('/register?useIdapi=true');
+ cy.get('input[name=email]').type(emailAddress);
+ const timeRequestWasMadeInitialEmail = new Date();
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMadeInitialEmail,
+ ).then(({ body }) => {
+ expect(body).to.have.string(
+ 'You are already registered with the Guardian.',
+ );
+ });
+
+ const timeRequestWasMade = new Date();
+ cy.contains('Resend email').click();
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+
+ // test and delete resent email
+ cy.checkForEmailAndGetDetails(emailAddress, timeRequestWasMade).then(
+ ({ body }) => {
+ expect(body).to.have.string(
+ 'You are already registered with the Guardian.',
+ );
+ },
+ );
+ });
+ });
+
+ it('should navigate back to the correct page when change email is clicked', () => {
+ cy.visit('/register/email-sent?useIdapi=true');
+ cy.contains('Change email address').click();
+ cy.contains('Register');
+ cy.title().should('eq', 'Register | The Guardian');
+ });
+
+ it('should render properly if the encrypted email cookie is not set', () => {
+ cy.visit('/register/email-sent?useIdapi=true');
+ cy.contains('Change email address');
+ cy.contains('Check your email inbox');
+ });
+
+ it('shows reCAPTCHA errors when the request fails', () => {
+ cy
+ .createTestUser({
+ isUserEmailValidated: false,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.visit('/register?useIdapi=true');
+ cy.get('input[name=email]').type(emailAddress);
+
+ const timeRequestWasMadeInitialEmail = new Date();
+
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMadeInitialEmail,
+ );
+
+ // Simulate going offline by failing the reCAPTCHA POST request.
+ cy.intercept({
+ method: 'POST',
+ url: 'https://www.google.com/recaptcha/api2/**',
+ times: 1,
+ });
+ cy.contains('Resend email').click();
+ cy.contains('Google reCAPTCHA verification failed. Please try again.');
+
+ // On second click, an expanded error is shown.
+ cy.contains('Resend email').click();
+
+ cy.contains('Google reCAPTCHA verification failed.');
+ cy.contains('If the problem persists please try the following:');
+ cy.contains('userhelp@');
+
+ const timeRequestWasMade = new Date();
+ cy.contains('Resend email').click();
+
+ cy.contains(
+ 'Google reCAPTCHA verification failed. Please try again.',
+ ).should('not.exist');
+
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+
+ cy.checkForEmailAndGetDetails(emailAddress, timeRequestWasMade);
+ });
+ });
});
diff --git a/cypress/integration/ete/reset_password/reset_password.4.cy.ts b/cypress/integration/ete/reset_password/reset_password.4.cy.ts
index bc33ca7bb2..fc9045c65b 100644
--- a/cypress/integration/ete/reset_password/reset_password.4.cy.ts
+++ b/cypress/integration/ete/reset_password/reset_password.4.cy.ts
@@ -1,210 +1,210 @@
import { randomPassword } from '../../../support/commands/testUser';
describe('Password reset flow', () => {
- context('Account exists', () => {
- it("changes the reader's password", () => {
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
-
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.visit('/signin?useIdapi=true');
- const timeRequestWasMade = new Date();
- cy.contains('Reset password').click();
-
- // Simulate going offline by failing the reCAPTCHA POST request.
- cy.intercept({
- method: 'POST',
- url: 'https://www.google.com/recaptcha/api2/**',
- times: 1,
- });
-
- cy.contains('Forgot password');
- cy.get('input[name=email]').type(emailAddress);
-
- // Check that both reCAPTCHA errors are shown.
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.contains(
- 'Google reCAPTCHA verification failed. Please try again.',
- );
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.contains('Google reCAPTCHA verification failed.');
- cy.contains('If the problem persists please try the following:');
- cy.contains('userhelp@');
-
- // Continue checking the password reset flow after reCAPTCHA assertions above.
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.contains('Check your email inbox');
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(({ token }) => {
- cy.visit(`/reset-password/${token}`);
- cy.get('input[name=password]').type(randomPassword());
- cy.wait('@breachCheck');
- cy.get('[data-cy="main-form-submit-button"]')
- .click()
- .should('be.disabled');
- cy.contains('Password updated');
- cy.contains(emailAddress.toLowerCase());
- });
- });
- });
- });
-
- context('Account without password exists', () => {
- it('changes the users password', () => {
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
-
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress }) => {
- cy.visit('/signin?useIdapi=true');
- const timeRequestWasMade = new Date();
- cy.contains('Reset password').click();
-
- // Simulate going offline by failing the reCAPTCHA POST request.
- cy.intercept({
- method: 'POST',
- url: 'https://www.google.com/recaptcha/api2/**',
- times: 1,
- });
-
- cy.contains('Forgot password');
- cy.get('input[name=email]').type(emailAddress);
-
- // Check that both reCAPTCHA errors are shown.
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.contains(
- 'Google reCAPTCHA verification failed. Please try again.',
- );
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.contains('Google reCAPTCHA verification failed.');
- cy.contains('If the problem persists please try the following:');
- cy.contains('userhelp@');
-
- // Continue checking the password reset flow after reCAPTCHA assertions above.
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.contains('Check your email inbox');
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMade,
- /reset-password\/([^"]*)/,
- ).then(({ token }) => {
- cy.visit(`/reset-password/${token}`);
- cy.get('input[name=password]').type(randomPassword());
- cy.wait('@breachCheck');
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.contains('Password updated');
- cy.contains(emailAddress.toLowerCase());
- });
- });
- });
- });
-
- context('No Account', () => {
- it('shows the email sent page with link to register when attempting to reset password', () => {
- cy.visit('/reset-password?useIdapi=true');
- cy.contains('Forgot password');
- cy.get('input[name=email]').type('invalid@doesnotexist.com');
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.contains('Check your email inbox');
- cy.contains('Register for free');
- });
- });
+ context('Account exists', () => {
+ it("changes the reader's password", () => {
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.visit('/signin?useIdapi=true');
+ const timeRequestWasMade = new Date();
+ cy.contains('Reset password').click();
+
+ // Simulate going offline by failing the reCAPTCHA POST request.
+ cy.intercept({
+ method: 'POST',
+ url: 'https://www.google.com/recaptcha/api2/**',
+ times: 1,
+ });
+
+ cy.contains('Forgot password');
+ cy.get('input[name=email]').type(emailAddress);
+
+ // Check that both reCAPTCHA errors are shown.
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.contains(
+ 'Google reCAPTCHA verification failed. Please try again.',
+ );
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.contains('Google reCAPTCHA verification failed.');
+ cy.contains('If the problem persists please try the following:');
+ cy.contains('userhelp@');
+
+ // Continue checking the password reset flow after reCAPTCHA assertions above.
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.contains('Check your email inbox');
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(({ token }) => {
+ cy.visit(`/reset-password/${token}`);
+ cy.get('input[name=password]').type(randomPassword());
+ cy.wait('@breachCheck');
+ cy.get('[data-cy="main-form-submit-button"]')
+ .click()
+ .should('be.disabled');
+ cy.contains('Password updated');
+ cy.contains(emailAddress.toLowerCase());
+ });
+ });
+ });
+ });
+
+ context('Account without password exists', () => {
+ it('changes the users password', () => {
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.visit('/signin?useIdapi=true');
+ const timeRequestWasMade = new Date();
+ cy.contains('Reset password').click();
+
+ // Simulate going offline by failing the reCAPTCHA POST request.
+ cy.intercept({
+ method: 'POST',
+ url: 'https://www.google.com/recaptcha/api2/**',
+ times: 1,
+ });
+
+ cy.contains('Forgot password');
+ cy.get('input[name=email]').type(emailAddress);
+
+ // Check that both reCAPTCHA errors are shown.
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.contains(
+ 'Google reCAPTCHA verification failed. Please try again.',
+ );
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.contains('Google reCAPTCHA verification failed.');
+ cy.contains('If the problem persists please try the following:');
+ cy.contains('userhelp@');
+
+ // Continue checking the password reset flow after reCAPTCHA assertions above.
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.contains('Check your email inbox');
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMade,
+ /reset-password\/([^"]*)/,
+ ).then(({ token }) => {
+ cy.visit(`/reset-password/${token}`);
+ cy.get('input[name=password]').type(randomPassword());
+ cy.wait('@breachCheck');
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.contains('Password updated');
+ cy.contains(emailAddress.toLowerCase());
+ });
+ });
+ });
+ });
+
+ context('No Account', () => {
+ it('shows the email sent page with link to register when attempting to reset password', () => {
+ cy.visit('/reset-password?useIdapi=true');
+ cy.contains('Forgot password');
+ cy.get('input[name=email]').type('invalid@doesnotexist.com');
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.contains('Check your email inbox');
+ cy.contains('Register for free');
+ });
+ });
});
describe('Password set flow', () => {
- context('Account without password exists', () => {
- it('from the set passsword link expired page, successfully send and reset the create password email, and get taken to the set password page from the email', () => {
- cy
- .createTestUser({
- isUserEmailValidated: false,
- isGuestUser: true,
- })
- ?.then(({ emailAddress }) => {
- cy.visit('/set-password/expired?useIdapi=true');
-
- // Simulate going offline by failing the reCAPTCHA POST request.
- cy.intercept({
- method: 'POST',
- url: 'https://www.google.com/recaptcha/api2/**',
- times: 1,
- });
-
- // link expired
- const timeRequestWasMadeLinkExpired = new Date();
- cy.get('input[name=email]').type(emailAddress);
-
- // Check that both reCAPTCHA errors are shown.
- cy.contains('Send me a link').click();
- cy.contains(
- 'Google reCAPTCHA verification failed. Please try again.',
- );
-
- cy.contains('Send me a link').click();
- cy.contains('Google reCAPTCHA verification failed.');
- cy.contains('If the problem persists please try the following:');
- cy.contains('userhelp@');
-
- // Continue checking the password reset flow after reCAPTCHA assertions above.
- cy.contains('Send me a link').click();
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.contains('Resend email');
- cy.contains('Change email address');
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMadeLinkExpired,
- ).then(({ body }) => {
- expect(body).to.have.string('Welcome back');
- expect(body).to.have.string(
- 'Please click below to create a password for your account.',
- );
- expect(body).to.have.string('This link is valid for 60 minutes.');
- expect(body).to.have.string('Create password');
- });
-
- // resend email
- const timeRequestWasMadeResend = new Date();
- cy.contains('Resend email').click();
- cy.contains('Check your email inbox');
- cy.contains(emailAddress);
- cy.checkForEmailAndGetDetails(
- emailAddress,
- timeRequestWasMadeResend,
- /\/set-password\/([^"]*)/,
- ).then(({ body, links, token }) => {
- expect(body).to.have.string('Welcome back');
- expect(body).to.have.string(
- 'Please click below to create a password for your account.',
- );
- expect(body).to.have.string('This link is valid for 60 minutes.');
- expect(body).to.have.string('Create password');
-
- expect(links.length).to.eq(2);
-
- const createPasswordLink = links.find(
- (link) => link.text === 'Create password',
- );
-
- expect(createPasswordLink).not.to.be.undefined;
-
- cy.visit(`/set-password/${token}`);
- cy.contains('Create password');
- });
- });
- });
- });
+ context('Account without password exists', () => {
+ it('from the set passsword link expired page, successfully send and reset the create password email, and get taken to the set password page from the email', () => {
+ cy
+ .createTestUser({
+ isUserEmailValidated: false,
+ isGuestUser: true,
+ })
+ ?.then(({ emailAddress }) => {
+ cy.visit('/set-password/expired?useIdapi=true');
+
+ // Simulate going offline by failing the reCAPTCHA POST request.
+ cy.intercept({
+ method: 'POST',
+ url: 'https://www.google.com/recaptcha/api2/**',
+ times: 1,
+ });
+
+ // link expired
+ const timeRequestWasMadeLinkExpired = new Date();
+ cy.get('input[name=email]').type(emailAddress);
+
+ // Check that both reCAPTCHA errors are shown.
+ cy.contains('Send me a link').click();
+ cy.contains(
+ 'Google reCAPTCHA verification failed. Please try again.',
+ );
+
+ cy.contains('Send me a link').click();
+ cy.contains('Google reCAPTCHA verification failed.');
+ cy.contains('If the problem persists please try the following:');
+ cy.contains('userhelp@');
+
+ // Continue checking the password reset flow after reCAPTCHA assertions above.
+ cy.contains('Send me a link').click();
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.contains('Resend email');
+ cy.contains('Change email address');
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMadeLinkExpired,
+ ).then(({ body }) => {
+ expect(body).to.have.string('Welcome back');
+ expect(body).to.have.string(
+ 'Please click below to create a password for your account.',
+ );
+ expect(body).to.have.string('This link is valid for 60 minutes.');
+ expect(body).to.have.string('Create password');
+ });
+
+ // resend email
+ const timeRequestWasMadeResend = new Date();
+ cy.contains('Resend email').click();
+ cy.contains('Check your email inbox');
+ cy.contains(emailAddress);
+ cy.checkForEmailAndGetDetails(
+ emailAddress,
+ timeRequestWasMadeResend,
+ /\/set-password\/([^"]*)/,
+ ).then(({ body, links, token }) => {
+ expect(body).to.have.string('Welcome back');
+ expect(body).to.have.string(
+ 'Please click below to create a password for your account.',
+ );
+ expect(body).to.have.string('This link is valid for 60 minutes.');
+ expect(body).to.have.string('Create password');
+
+ expect(links.length).to.eq(2);
+
+ const createPasswordLink = links.find(
+ (link) => link.text === 'Create password',
+ );
+
+ expect(createPasswordLink).not.to.be.undefined;
+
+ cy.visit(`/set-password/${token}`);
+ cy.contains('Create password');
+ });
+ });
+ });
+ });
});
diff --git a/cypress/integration/ete/sign_in/sign_in.1.cy.ts b/cypress/integration/ete/sign_in/sign_in.1.cy.ts
index 6f049451fb..102e8176a9 100644
--- a/cypress/integration/ete/sign_in/sign_in.1.cy.ts
+++ b/cypress/integration/ete/sign_in/sign_in.1.cy.ts
@@ -1,55 +1,55 @@
import * as SignIn from '../../shared/sign_in.shared';
describe('Sign in flow, Okta disabled', () => {
- beforeEach(() => {
- SignIn.beforeEach();
- });
+ beforeEach(() => {
+ SignIn.beforeEach();
+ });
- context('Terms and Conditions links', () => {
- it(...SignIn.linksToTheGoogleTermsOfServicePage(true));
- it(...SignIn.linksToTheGooglePrivacyPolicyPage(true));
- it(...SignIn.linksToTheGuardianTermsAndConditionsPage(true));
- it(...SignIn.linksToTheGuardianPrivacyPolicyPage(true));
- it(
- ...SignIn.linksToTheGuardianJobsTermsAndConditionsPageWhenJobsClientIdSet(
- true,
- ),
- );
- it(
- ...SignIn.linksToTheGuardianJobsPrivacyPolicyPageWhenJobsClientIdSet(
- true,
- ),
- );
- });
- it(...SignIn.persistsTheClientIdWhenNavigatingAway(true));
- it(...SignIn.appliesFormValidationToEmailAndPasswordInputFields(true));
- it(...SignIn.showsAMessageWhenCredentialsAreInvalid(true));
- it(...SignIn.correctlySignsInAnExistingUser(true));
- it(...SignIn.navigatesToResetPassword(true));
- it(...SignIn.navigatesToRegistration(true));
- it(...SignIn.respectsTheReturnUrlQueryParam(true));
- it(...SignIn.redirectsCorrectlyForSocialSignIn(true));
- it(...SignIn.removesEncryptedEmailParameterFromQueryString(true));
- it(
- ...SignIn.removesEncryptedEmailParameterAndPreservesAllOtherValidParameters(
- true,
- ),
- );
- it(
- ...SignIn.showsAnErrorMessageAndInformationParagraphWhenAccountLinkingRequiredErrorParameterIsPresent(
- true,
- ),
- );
- it(
- ...SignIn.doesNotDisplaySocialButtonsWhenAccountLinkingRequiredErrorParameterIsPresent(
- true,
- ),
- );
- it(
- ...SignIn.showsRecaptchaErrorsWhenTheUserTriesToSignInOfflineAndAllowsSignInWhenBackOnline(
- true,
- ),
- );
- it(...SignIn.redirectsToOptInPrompt(true));
- it(...SignIn.hitsAccessTokenRateLimitAndRecoversTokenAfterTimeout(true));
+ context('Terms and Conditions links', () => {
+ it(...SignIn.linksToTheGoogleTermsOfServicePage(true));
+ it(...SignIn.linksToTheGooglePrivacyPolicyPage(true));
+ it(...SignIn.linksToTheGuardianTermsAndConditionsPage(true));
+ it(...SignIn.linksToTheGuardianPrivacyPolicyPage(true));
+ it(
+ ...SignIn.linksToTheGuardianJobsTermsAndConditionsPageWhenJobsClientIdSet(
+ true,
+ ),
+ );
+ it(
+ ...SignIn.linksToTheGuardianJobsPrivacyPolicyPageWhenJobsClientIdSet(
+ true,
+ ),
+ );
+ });
+ it(...SignIn.persistsTheClientIdWhenNavigatingAway(true));
+ it(...SignIn.appliesFormValidationToEmailAndPasswordInputFields(true));
+ it(...SignIn.showsAMessageWhenCredentialsAreInvalid(true));
+ it(...SignIn.correctlySignsInAnExistingUser(true));
+ it(...SignIn.navigatesToResetPassword(true));
+ it(...SignIn.navigatesToRegistration(true));
+ it(...SignIn.respectsTheReturnUrlQueryParam(true));
+ it(...SignIn.redirectsCorrectlyForSocialSignIn(true));
+ it(...SignIn.removesEncryptedEmailParameterFromQueryString(true));
+ it(
+ ...SignIn.removesEncryptedEmailParameterAndPreservesAllOtherValidParameters(
+ true,
+ ),
+ );
+ it(
+ ...SignIn.showsAnErrorMessageAndInformationParagraphWhenAccountLinkingRequiredErrorParameterIsPresent(
+ true,
+ ),
+ );
+ it(
+ ...SignIn.doesNotDisplaySocialButtonsWhenAccountLinkingRequiredErrorParameterIsPresent(
+ true,
+ ),
+ );
+ it(
+ ...SignIn.showsRecaptchaErrorsWhenTheUserTriesToSignInOfflineAndAllowsSignInWhenBackOnline(
+ true,
+ ),
+ );
+ it(...SignIn.redirectsToOptInPrompt(true));
+ it(...SignIn.hitsAccessTokenRateLimitAndRecoversTokenAfterTimeout(true));
});
diff --git a/cypress/integration/ete/sign_out/sign_out.3.cy.ts b/cypress/integration/ete/sign_out/sign_out.3.cy.ts
index 890b1dfd98..f6cee6e401 100644
--- a/cypress/integration/ete/sign_out/sign_out.3.cy.ts
+++ b/cypress/integration/ete/sign_out/sign_out.3.cy.ts
@@ -1,71 +1,71 @@
describe('Sign out flow', () => {
- const DotComCookies = [
- 'gu_user_features_expiry',
- 'gu_paying_member',
- 'gu_recurring_contributor',
- 'gu_digital_subscriber',
- ];
+ const DotComCookies = [
+ 'gu_user_features_expiry',
+ 'gu_paying_member',
+ 'gu_recurring_contributor',
+ 'gu_digital_subscriber',
+ ];
- context('Signs a user out', () => {
- it('Removes IDAPI log in cookies and dotcom cookies when signing out', () => {
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress, finalPassword }) => {
- // Disable redirect to /signin/success by default
- cy.setCookie(
- 'GU_ran_experiments',
- new URLSearchParams({
- OptInPromptPostSignIn: Date.now().toString(),
- }).toString(),
- );
- // load the consents page as its on the same domain
- const postSignInReturnUrl = `https://${Cypress.env(
- 'BASE_URI',
- )}/consents/data?useIdapi=true`;
- const visitUrl = `/signin?returnUrl=${encodeURIComponent(
- postSignInReturnUrl,
- )}&useIdapi=true`;
- cy.visit(visitUrl);
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
+ context('Signs a user out', () => {
+ it('Removes IDAPI log in cookies and dotcom cookies when signing out', () => {
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress, finalPassword }) => {
+ // Disable redirect to /signin/success by default
+ cy.setCookie(
+ 'GU_ran_experiments',
+ new URLSearchParams({
+ OptInPromptPostSignIn: Date.now().toString(),
+ }).toString(),
+ );
+ // load the consents page as its on the same domain
+ const postSignInReturnUrl = `https://${Cypress.env(
+ 'BASE_URI',
+ )}/consents/data?useIdapi=true`;
+ const visitUrl = `/signin?returnUrl=${encodeURIComponent(
+ postSignInReturnUrl,
+ )}&useIdapi=true`;
+ cy.visit(visitUrl);
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
- DotComCookies.forEach((cookie) => {
- cy.setCookie(cookie, `the_${cookie}_cookie`, {
- domain: Cypress.env('BASE_URI')?.replace('profile', ''),
- });
- });
+ DotComCookies.forEach((cookie) => {
+ cy.setCookie(cookie, `the_${cookie}_cookie`, {
+ domain: Cypress.env('BASE_URI')?.replace('profile', ''),
+ });
+ });
- cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.get('[data-cy="main-form-submit-button"]').click();
- // check sign in has worked first
- cy.url().should('include', `/consents/data`);
- // check cookies are set
- cy.getCookie('SC_GU_U').should('exist');
- cy.getCookie('SC_GU_LA').should('exist');
- cy.getCookie('GU_U').should('exist');
- DotComCookies.forEach((cookie) => {
- cy.getCookie(cookie).should('exist');
- });
+ // check sign in has worked first
+ cy.url().should('include', `/consents/data`);
+ // check cookies are set
+ cy.getCookie('SC_GU_U').should('exist');
+ cy.getCookie('SC_GU_LA').should('exist');
+ cy.getCookie('GU_U').should('exist');
+ DotComCookies.forEach((cookie) => {
+ cy.getCookie(cookie).should('exist');
+ });
- // attempt to sign out and redirect to reset password as it's on same domain
- const postSignOutReturnUrl = `https://${Cypress.env(
- 'BASE_URI',
- )}/reset-password`;
- cy.visit(
- `/signout?returnUrl=${encodeURIComponent(
- postSignOutReturnUrl,
- )}&useIdapi=true`,
- );
- // check cookies are removed
- cy.getCookie('SC_GU_U').should('not.exist');
- cy.getCookie('SC_GU_LA').should('not.exist');
- cy.getCookie('GU_U').should('not.exist');
- DotComCookies.forEach((cookie) => {
- cy.getCookie(cookie).should('not.exist');
- });
- });
- });
- });
+ // attempt to sign out and redirect to reset password as it's on same domain
+ const postSignOutReturnUrl = `https://${Cypress.env(
+ 'BASE_URI',
+ )}/reset-password`;
+ cy.visit(
+ `/signout?returnUrl=${encodeURIComponent(
+ postSignOutReturnUrl,
+ )}&useIdapi=true`,
+ );
+ // check cookies are removed
+ cy.getCookie('SC_GU_U').should('not.exist');
+ cy.getCookie('SC_GU_LA').should('not.exist');
+ cy.getCookie('GU_U').should('not.exist');
+ DotComCookies.forEach((cookie) => {
+ cy.getCookie(cookie).should('not.exist');
+ });
+ });
+ });
+ });
});
diff --git a/cypress/integration/ete/terms/jobs_terms.4.cy.ts b/cypress/integration/ete/terms/jobs_terms.4.cy.ts
index 8f70d0404a..d7bbd272b5 100644
--- a/cypress/integration/ete/terms/jobs_terms.4.cy.ts
+++ b/cypress/integration/ete/terms/jobs_terms.4.cy.ts
@@ -1,242 +1,242 @@
describe('Jobs terms and conditions flow', () => {
- context('Accepts Jobs terms and conditions and sets their name', () => {
- it('should redirect users with an invalid SC_GU_U cookie to the signin page', () => {
- // load the consents page as its on the same domain
- const termsAcceptPageUrl = `https://${Cypress.env(
- 'BASE_URI',
- )}/agree/GRS?returnUrl=https://profile.thegulocal.com/signin?returnUrl=https%3A%2F%2Fm.code.dev-theguardian.com%2F&useIdapi=true`;
-
- cy.setCookie('SC_GU_U', 'invalid-cookie');
-
- cy.visit(termsAcceptPageUrl);
- cy.url().should('include', 'https://profile.thegulocal.com/signin');
- });
-
- it('should redirect users with no SC_GU_U cookie to the signin page', () => {
- // load the consents page as its on the same domain
- const termsAcceptPageUrl = `https://${Cypress.env(
- 'BASE_URI',
- )}/agree/GRS?useIdapi=true`;
- cy.visit(termsAcceptPageUrl);
- cy.url().should(
- 'include',
- 'https://profile.thegulocal.com/signin?returnUrl=https%3A%2F%2Fprofile.thegulocal.com%2Fagree%2FGRS&useIdapi=true',
- );
- });
-
- it('should show the jobs terms page for users who do not have first/last name set, but are part of GRS', () => {
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress, finalPassword }) => {
- cy.visit('/signin?useIdapi=true');
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
-
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.url().should('include', '/signin/success');
-
- const termsAcceptPageUrl = `https://${Cypress.env(
- 'BASE_URI',
- )}/agree/GRS?returnUrl=https://profile.thegulocal.com/healthcheck&useIdapi=true`;
-
- // Create a test user without a first/last name who is in the GRS group.
- cy.updateTestUser({
- privateFields: {
- firstName: '',
- secondName: '',
- },
- })
- .then(cy.addToGRS)
- .then(() => {
- cy.visit(termsAcceptPageUrl);
- cy.contains('Please complete your details for');
- cy.contains(emailAddress);
- cy.contains('We will use these details on your job applications');
-
- cy.get('input[name=firstName]').should('be.empty');
- cy.get('input[name=secondName]').should('be.empty');
-
- cy.get('input[name=firstName]').type('First Name');
- cy.get('input[name=secondName]').type('Second Name');
-
- cy.findByText('Save and continue').click();
-
- // User should be in the GRS group and have First/Last name set to our custom values.
- cy.getTestUserDetails().then(({ user, status }) => {
- expect(status).to.eq('ok');
- expect(user.privateFields.firstName).to.eq('First Name');
- expect(user.privateFields.secondName).to.eq('Second Name');
- const joinedGroups = user.userGroups.map(
- (group) => group.packageCode,
- );
- expect(joinedGroups).to.include('GRS');
- });
- });
- });
- });
-
- it('should redirect users who have already accepted the terms away', () => {
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress, finalPassword }) => {
- // load the consents page as its on the same domain
- const termsAcceptPageUrl = `https://${Cypress.env(
- 'BASE_URI',
- )}/agree/GRS?returnUrl=https://profile.thegulocal.com/healthcheck&useIdapi=true`;
-
- cy.visit('/signin?useIdapi=true');
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
-
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.url().should('include', '/signin/success');
-
- cy.visit(termsAcceptPageUrl);
-
- // check sign in has worked first
- cy.url().should('include', `/agree/GRS`);
- // check cookies are set
- cy.getCookie('SC_GU_U').should('exist');
- cy.getCookie('SC_GU_LA').should('exist');
- cy.getCookie('GU_U').should('exist');
-
- cy.contains('Welcome to Guardian Jobs');
-
- // User should not be in GRS and have the original first/last name.
- cy.getTestUserDetails().then(({ user, status }) => {
- expect(status).to.eq('ok');
- cy.get('input[name=firstName]').should(
- 'contain.value',
- user.privateFields.firstName,
- );
- cy.get('input[name=secondName]').should(
- 'contain.value',
- user.privateFields.secondName,
- );
-
- const joinedGroups = user.userGroups.map(
- (group) => group.packageCode,
- );
- expect(joinedGroups).not.to.include('GRS');
- });
-
- cy.get('input[name=firstName]').clear().type('First Name');
- cy.get('input[name=secondName]').clear().type('Second Name');
-
- cy.findByText('Continue').click();
-
- // User should be in the GRS group and have First/Last name set to our custom values.
- cy.getTestUserDetails().then(({ user, status }) => {
- expect(status).to.eq('ok');
- expect(user.privateFields.firstName).to.eq('First Name');
- expect(user.privateFields.secondName).to.eq('Second Name');
- const joinedGroups = user.userGroups.map(
- (group) => group.packageCode,
- );
- expect(joinedGroups).to.include('GRS');
- });
-
- cy.url().should(
- 'include',
- 'https://profile.thegulocal.com/healthcheck',
- );
-
- const finalTermsAcceptPageUrl = `https://${Cypress.env(
- 'BASE_URI',
- )}/agree/GRS?returnUrl=https://profile.thegulocal.com/maintenance&useIdapi=true`;
-
- cy.visit(finalTermsAcceptPageUrl, { failOnStatusCode: false });
-
- // Make sure the returnURL is respected.
- cy.url().should(
- 'include',
- 'https://profile.thegulocal.com/maintenance',
- );
- });
- });
-
- // Skipping this test for now, because of some flakiness where
- // users' first and last name aren't updated by the time we make the request
- // to /user/me to check their info.
- it('should allow a non-jobs user to enter their first/last name and accept the terms', () => {
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress, finalPassword }) => {
- // load the consents page as its on the same domain
- const termsAcceptPageUrl = `https://${Cypress.env(
- 'BASE_URI',
- )}/agree/GRS?returnUrl=https://jobs.thegulocal.com/&useIdapi=true`;
-
- cy.visit('/signin?useIdapi=true');
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
-
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.url().should('include', '/signin/success');
-
- cy.visit(termsAcceptPageUrl);
-
- // check sign in has worked first
- cy.url().should('include', `/agree/GRS`);
- // check cookies are set
- cy.getCookie('SC_GU_U').should('exist');
- cy.getCookie('SC_GU_LA').should('exist');
- cy.getCookie('GU_U').should('exist');
-
- cy.contains('Welcome to Guardian Jobs');
-
- // User should not be in GRS and have the original first/last name.
- cy.getTestUserDetails().then(({ user, status }) => {
- expect(status).to.eq('ok');
- cy.get('input[name=firstName]').should(
- 'contain.value',
- user.privateFields.firstName,
- );
- cy.get('input[name=secondName]').should(
- 'contain.value',
- user.privateFields.secondName,
- );
-
- const joinedGroups = user.userGroups.map(
- (group) => group.packageCode,
- );
- expect(joinedGroups).not.to.include('GRS');
- });
-
- cy.get('input[name=firstName]').clear().type('First Name');
- cy.get('input[name=secondName]').clear().type('Second Name');
-
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', 'https://jobs.thegulocal.com/', (req) => {
- req.reply(200);
- });
-
- cy.findByText('Continue').click();
-
- // Make sure the returnURL is respected.
- cy.url().should('include', 'https://jobs.thegulocal.com/');
-
- // User should be in the GRS group and have First/Last name set.
- cy.getTestUserDetails().then(({ user, status }) => {
- expect(status).to.eq('ok');
- expect(user.privateFields.firstName).to.eq('First Name');
- expect(user.privateFields.secondName).to.eq('Second Name');
- const joinedGroups = user.userGroups.map(
- (group) => group.packageCode,
- );
- expect(joinedGroups).to.include('GRS');
- });
- });
- });
- });
+ context('Accepts Jobs terms and conditions and sets their name', () => {
+ it('should redirect users with an invalid SC_GU_U cookie to the signin page', () => {
+ // load the consents page as its on the same domain
+ const termsAcceptPageUrl = `https://${Cypress.env(
+ 'BASE_URI',
+ )}/agree/GRS?returnUrl=https://profile.thegulocal.com/signin?returnUrl=https%3A%2F%2Fm.code.dev-theguardian.com%2F&useIdapi=true`;
+
+ cy.setCookie('SC_GU_U', 'invalid-cookie');
+
+ cy.visit(termsAcceptPageUrl);
+ cy.url().should('include', 'https://profile.thegulocal.com/signin');
+ });
+
+ it('should redirect users with no SC_GU_U cookie to the signin page', () => {
+ // load the consents page as its on the same domain
+ const termsAcceptPageUrl = `https://${Cypress.env(
+ 'BASE_URI',
+ )}/agree/GRS?useIdapi=true`;
+ cy.visit(termsAcceptPageUrl);
+ cy.url().should(
+ 'include',
+ 'https://profile.thegulocal.com/signin?returnUrl=https%3A%2F%2Fprofile.thegulocal.com%2Fagree%2FGRS&useIdapi=true',
+ );
+ });
+
+ it('should show the jobs terms page for users who do not have first/last name set, but are part of GRS', () => {
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress, finalPassword }) => {
+ cy.visit('/signin?useIdapi=true');
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.url().should('include', '/signin/success');
+
+ const termsAcceptPageUrl = `https://${Cypress.env(
+ 'BASE_URI',
+ )}/agree/GRS?returnUrl=https://profile.thegulocal.com/healthcheck&useIdapi=true`;
+
+ // Create a test user without a first/last name who is in the GRS group.
+ cy.updateTestUser({
+ privateFields: {
+ firstName: '',
+ secondName: '',
+ },
+ })
+ .then(cy.addToGRS)
+ .then(() => {
+ cy.visit(termsAcceptPageUrl);
+ cy.contains('Please complete your details for');
+ cy.contains(emailAddress);
+ cy.contains('We will use these details on your job applications');
+
+ cy.get('input[name=firstName]').should('be.empty');
+ cy.get('input[name=secondName]').should('be.empty');
+
+ cy.get('input[name=firstName]').type('First Name');
+ cy.get('input[name=secondName]').type('Second Name');
+
+ cy.findByText('Save and continue').click();
+
+ // User should be in the GRS group and have First/Last name set to our custom values.
+ cy.getTestUserDetails().then(({ user, status }) => {
+ expect(status).to.eq('ok');
+ expect(user.privateFields.firstName).to.eq('First Name');
+ expect(user.privateFields.secondName).to.eq('Second Name');
+ const joinedGroups = user.userGroups.map(
+ (group) => group.packageCode,
+ );
+ expect(joinedGroups).to.include('GRS');
+ });
+ });
+ });
+ });
+
+ it('should redirect users who have already accepted the terms away', () => {
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress, finalPassword }) => {
+ // load the consents page as its on the same domain
+ const termsAcceptPageUrl = `https://${Cypress.env(
+ 'BASE_URI',
+ )}/agree/GRS?returnUrl=https://profile.thegulocal.com/healthcheck&useIdapi=true`;
+
+ cy.visit('/signin?useIdapi=true');
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.url().should('include', '/signin/success');
+
+ cy.visit(termsAcceptPageUrl);
+
+ // check sign in has worked first
+ cy.url().should('include', `/agree/GRS`);
+ // check cookies are set
+ cy.getCookie('SC_GU_U').should('exist');
+ cy.getCookie('SC_GU_LA').should('exist');
+ cy.getCookie('GU_U').should('exist');
+
+ cy.contains('Welcome to Guardian Jobs');
+
+ // User should not be in GRS and have the original first/last name.
+ cy.getTestUserDetails().then(({ user, status }) => {
+ expect(status).to.eq('ok');
+ cy.get('input[name=firstName]').should(
+ 'contain.value',
+ user.privateFields.firstName,
+ );
+ cy.get('input[name=secondName]').should(
+ 'contain.value',
+ user.privateFields.secondName,
+ );
+
+ const joinedGroups = user.userGroups.map(
+ (group) => group.packageCode,
+ );
+ expect(joinedGroups).not.to.include('GRS');
+ });
+
+ cy.get('input[name=firstName]').clear().type('First Name');
+ cy.get('input[name=secondName]').clear().type('Second Name');
+
+ cy.findByText('Continue').click();
+
+ // User should be in the GRS group and have First/Last name set to our custom values.
+ cy.getTestUserDetails().then(({ user, status }) => {
+ expect(status).to.eq('ok');
+ expect(user.privateFields.firstName).to.eq('First Name');
+ expect(user.privateFields.secondName).to.eq('Second Name');
+ const joinedGroups = user.userGroups.map(
+ (group) => group.packageCode,
+ );
+ expect(joinedGroups).to.include('GRS');
+ });
+
+ cy.url().should(
+ 'include',
+ 'https://profile.thegulocal.com/healthcheck',
+ );
+
+ const finalTermsAcceptPageUrl = `https://${Cypress.env(
+ 'BASE_URI',
+ )}/agree/GRS?returnUrl=https://profile.thegulocal.com/maintenance&useIdapi=true`;
+
+ cy.visit(finalTermsAcceptPageUrl, { failOnStatusCode: false });
+
+ // Make sure the returnURL is respected.
+ cy.url().should(
+ 'include',
+ 'https://profile.thegulocal.com/maintenance',
+ );
+ });
+ });
+
+ // Skipping this test for now, because of some flakiness where
+ // users' first and last name aren't updated by the time we make the request
+ // to /user/me to check their info.
+ it('should allow a non-jobs user to enter their first/last name and accept the terms', () => {
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress, finalPassword }) => {
+ // load the consents page as its on the same domain
+ const termsAcceptPageUrl = `https://${Cypress.env(
+ 'BASE_URI',
+ )}/agree/GRS?returnUrl=https://jobs.thegulocal.com/&useIdapi=true`;
+
+ cy.visit('/signin?useIdapi=true');
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.url().should('include', '/signin/success');
+
+ cy.visit(termsAcceptPageUrl);
+
+ // check sign in has worked first
+ cy.url().should('include', `/agree/GRS`);
+ // check cookies are set
+ cy.getCookie('SC_GU_U').should('exist');
+ cy.getCookie('SC_GU_LA').should('exist');
+ cy.getCookie('GU_U').should('exist');
+
+ cy.contains('Welcome to Guardian Jobs');
+
+ // User should not be in GRS and have the original first/last name.
+ cy.getTestUserDetails().then(({ user, status }) => {
+ expect(status).to.eq('ok');
+ cy.get('input[name=firstName]').should(
+ 'contain.value',
+ user.privateFields.firstName,
+ );
+ cy.get('input[name=secondName]').should(
+ 'contain.value',
+ user.privateFields.secondName,
+ );
+
+ const joinedGroups = user.userGroups.map(
+ (group) => group.packageCode,
+ );
+ expect(joinedGroups).not.to.include('GRS');
+ });
+
+ cy.get('input[name=firstName]').clear().type('First Name');
+ cy.get('input[name=secondName]').clear().type('Second Name');
+
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', 'https://jobs.thegulocal.com/', (req) => {
+ req.reply(200);
+ });
+
+ cy.findByText('Continue').click();
+
+ // Make sure the returnURL is respected.
+ cy.url().should('include', 'https://jobs.thegulocal.com/');
+
+ // User should be in the GRS group and have First/Last name set.
+ cy.getTestUserDetails().then(({ user, status }) => {
+ expect(status).to.eq('ok');
+ expect(user.privateFields.firstName).to.eq('First Name');
+ expect(user.privateFields.secondName).to.eq('Second Name');
+ const joinedGroups = user.userGroups.map(
+ (group) => group.packageCode,
+ );
+ expect(joinedGroups).to.include('GRS');
+ });
+ });
+ });
+ });
});
diff --git a/cypress/integration/ete/unsubscribe/unsubscribe.3.cy.ts b/cypress/integration/ete/unsubscribe/unsubscribe.3.cy.ts
index 86243a2906..eaf00732db 100644
--- a/cypress/integration/ete/unsubscribe/unsubscribe.3.cy.ts
+++ b/cypress/integration/ete/unsubscribe/unsubscribe.3.cy.ts
@@ -1,205 +1,205 @@
import crypto from 'crypto';
describe('Unsubscribe newsletter/marketing email', () => {
- const newsletterListId = '4151';
- const newsletterId = 'today-uk';
- const marketingId = 'supporter';
-
- const createData = (newsletterId: string, userId: string) =>
- `${newsletterId}:${userId}:${Math.floor(Date.now() / 1000)}`;
-
- const createToken = (data: string) =>
- crypto
- .createHmac('sha1', Cypress.env('BRAZE_HMAC_KEY'))
- .update(data)
- .digest('hex');
-
- it('should be able to unsubscribe from a newsletter', () => {
- cy.createTestUser({
- isUserEmailValidated: true,
- }).then(({ cookies }) => {
- // SC_GU_U is required for the cy.getTestUserDetails
- const scGuU = cookies.find((cookie) => cookie.key === 'SC_GU_U');
- if (!scGuU) throw new Error('SC_GU_U cookie not found');
- cy.setCookie('SC_GU_U', scGuU?.value);
-
- cy.getTestUserDetails().then(({ user }) => {
- const id = user.id;
- const data = createData(newsletterId, id);
- cy.subscribeToNewsletter(newsletterListId).then(() => {
- cy.visit(
- `/unsubscribe/newsletter/${encodeURIComponent(data)}/${createToken(
- data,
- )}`,
- );
- cy.contains('You have been unsubscribed.');
- });
- });
- });
- });
-
- it('should be able to unsubscribe from a marketing email', () => {
- cy.createTestUser({
- isUserEmailValidated: true,
- }).then(({ cookies }) => {
- // SC_GU_U is required for the cy.getTestUserDetails
- const scGuU = cookies.find((cookie) => cookie.key === 'SC_GU_U');
- if (!scGuU) throw new Error('SC_GU_U cookie not found');
- cy.setCookie('SC_GU_U', scGuU?.value);
-
- cy.getTestUserDetails().then(({ user }) => {
- const id = user.id;
- const data = createData(marketingId, id);
- cy.subscribeToMarketingConsent(marketingId).then(() => {
- cy.visit(
- `/unsubscribe/marketing/${encodeURIComponent(data)}/${createToken(
- data,
- )}`,
- );
- cy.contains('You have been unsubscribed.');
- });
- });
- });
- });
-
- it('should be able to handle a unsubscribe error if emailType is not newsletter/marketing', () => {
- cy.createTestUser({
- isUserEmailValidated: true,
- }).then(({ cookies }) => {
- // SC_GU_U is required for the cy.getTestUserDetails
- const scGuU = cookies.find((cookie) => cookie.key === 'SC_GU_U');
- if (!scGuU) throw new Error('SC_GU_U cookie not found');
- cy.setCookie('SC_GU_U', scGuU?.value);
-
- cy.getTestUserDetails().then(({ user }) => {
- const id = user.id;
- const data = createData(marketingId, id);
- cy.subscribeToMarketingConsent(marketingId).then(() => {
- cy.visit(
- `/unsubscribe/fake/${encodeURIComponent(data)}/${createToken(
- data,
- )}`,
- );
- cy.contains('Unable to unsubscribe.');
- });
- });
- });
- });
-
- it('should be able to handle a unsubscribe error if token is invalid', () => {
- cy.createTestUser({
- isUserEmailValidated: true,
- }).then(({ cookies }) => {
- // SC_GU_U is required for the cy.getTestUserDetails
- const scGuU = cookies.find((cookie) => cookie.key === 'SC_GU_U');
- if (!scGuU) throw new Error('SC_GU_U cookie not found');
- cy.setCookie('SC_GU_U', scGuU?.value);
-
- cy.getTestUserDetails().then(({ user }) => {
- const id = user.id;
- const data = createData(newsletterId, id);
- cy.subscribeToNewsletter(newsletterListId).then(() => {
- cy.visit(
- `/unsubscribe/newsletter/${encodeURIComponent(data)}/fake_token`,
- );
- cy.contains('Unable to unsubscribe.');
- });
- });
- });
- });
-
- it('should be able to handle a unsubscribe error if newsletterId is invalid', () => {
- cy.createTestUser({
- isUserEmailValidated: true,
- }).then(({ cookies }) => {
- // SC_GU_U is required for the cy.getTestUserDetails
- const scGuU = cookies.find((cookie) => cookie.key === 'SC_GU_U');
- if (!scGuU) throw new Error('SC_GU_U cookie not found');
- cy.setCookie('SC_GU_U', scGuU?.value);
-
- cy.getTestUserDetails().then(({ user }) => {
- const id = user.id;
- const data = createData(`${newsletterId}-fake`, id);
- cy.subscribeToNewsletter(newsletterListId).then(() => {
- cy.visit(
- `/unsubscribe/newsletter/${encodeURIComponent(data)}/${createToken(
- data,
- )}`,
- );
- cy.contains('Unable to unsubscribe.');
- });
- });
- });
- });
-
- it('should be able to handle a unsubscribe error if marketingId is invalid', () => {
- cy.createTestUser({
- isUserEmailValidated: true,
- }).then(({ cookies }) => {
- // SC_GU_U is required for the cy.getTestUserDetails
- const scGuU = cookies.find((cookie) => cookie.key === 'SC_GU_U');
- if (!scGuU) throw new Error('SC_GU_U cookie not found');
- cy.setCookie('SC_GU_U', scGuU?.value);
-
- cy.getTestUserDetails().then(({ user }) => {
- const id = user.id;
- const data = createData(`${marketingId}-fake`, id);
- cy.subscribeToMarketingConsent(marketingId).then(() => {
- cy.visit(
- `/unsubscribe/marketing/${encodeURIComponent(data)}/${createToken(
- data,
- )}`,
- );
- cy.contains('Unable to unsubscribe.');
- });
- });
- });
- });
-
- it('should be able to handle a unsubscribe error if userId is invalid', () => {
- cy.createTestUser({
- isUserEmailValidated: true,
- }).then(({ cookies }) => {
- // SC_GU_U is required for the cy.getTestUserDetails
- const scGuU = cookies.find((cookie) => cookie.key === 'SC_GU_U');
- if (!scGuU) throw new Error('SC_GU_U cookie not found');
- cy.setCookie('SC_GU_U', scGuU?.value);
-
- cy.getTestUserDetails().then(({ user }) => {
- const id = user.id;
- const data = createData(marketingId, `${id}0`);
- cy.subscribeToMarketingConsent(marketingId).then(() => {
- cy.visit(
- `/unsubscribe/marketing/${encodeURIComponent(data)}/${createToken(
- data,
- )}`,
- );
- cy.contains('Unable to unsubscribe.');
- });
- });
- });
- });
-
- it('should be able to handle a unsubscribe error if data is invalid', () => {
- cy.createTestUser({
- isUserEmailValidated: true,
- }).then(({ cookies }) => {
- // SC_GU_U is required for the cy.getTestUserDetails
- const scGuU = cookies.find((cookie) => cookie.key === 'SC_GU_U');
- if (!scGuU) throw new Error('SC_GU_U cookie not found');
- cy.setCookie('SC_GU_U', scGuU?.value);
-
- cy.getTestUserDetails().then(() => {
- const data = 'data-is-invalid:yes-123';
- cy.subscribeToMarketingConsent(marketingId).then(() => {
- cy.visit(
- `/unsubscribe/marketing/${encodeURIComponent(data)}/${createToken(
- data,
- )}`,
- );
- cy.contains('Unable to unsubscribe.');
- });
- });
- });
- });
+ const newsletterListId = '4151';
+ const newsletterId = 'today-uk';
+ const marketingId = 'supporter';
+
+ const createData = (newsletterId: string, userId: string) =>
+ `${newsletterId}:${userId}:${Math.floor(Date.now() / 1000)}`;
+
+ const createToken = (data: string) =>
+ crypto
+ .createHmac('sha1', Cypress.env('BRAZE_HMAC_KEY'))
+ .update(data)
+ .digest('hex');
+
+ it('should be able to unsubscribe from a newsletter', () => {
+ cy.createTestUser({
+ isUserEmailValidated: true,
+ }).then(({ cookies }) => {
+ // SC_GU_U is required for the cy.getTestUserDetails
+ const scGuU = cookies.find((cookie) => cookie.key === 'SC_GU_U');
+ if (!scGuU) throw new Error('SC_GU_U cookie not found');
+ cy.setCookie('SC_GU_U', scGuU?.value);
+
+ cy.getTestUserDetails().then(({ user }) => {
+ const id = user.id;
+ const data = createData(newsletterId, id);
+ cy.subscribeToNewsletter(newsletterListId).then(() => {
+ cy.visit(
+ `/unsubscribe/newsletter/${encodeURIComponent(data)}/${createToken(
+ data,
+ )}`,
+ );
+ cy.contains('You have been unsubscribed.');
+ });
+ });
+ });
+ });
+
+ it('should be able to unsubscribe from a marketing email', () => {
+ cy.createTestUser({
+ isUserEmailValidated: true,
+ }).then(({ cookies }) => {
+ // SC_GU_U is required for the cy.getTestUserDetails
+ const scGuU = cookies.find((cookie) => cookie.key === 'SC_GU_U');
+ if (!scGuU) throw new Error('SC_GU_U cookie not found');
+ cy.setCookie('SC_GU_U', scGuU?.value);
+
+ cy.getTestUserDetails().then(({ user }) => {
+ const id = user.id;
+ const data = createData(marketingId, id);
+ cy.subscribeToMarketingConsent(marketingId).then(() => {
+ cy.visit(
+ `/unsubscribe/marketing/${encodeURIComponent(data)}/${createToken(
+ data,
+ )}`,
+ );
+ cy.contains('You have been unsubscribed.');
+ });
+ });
+ });
+ });
+
+ it('should be able to handle a unsubscribe error if emailType is not newsletter/marketing', () => {
+ cy.createTestUser({
+ isUserEmailValidated: true,
+ }).then(({ cookies }) => {
+ // SC_GU_U is required for the cy.getTestUserDetails
+ const scGuU = cookies.find((cookie) => cookie.key === 'SC_GU_U');
+ if (!scGuU) throw new Error('SC_GU_U cookie not found');
+ cy.setCookie('SC_GU_U', scGuU?.value);
+
+ cy.getTestUserDetails().then(({ user }) => {
+ const id = user.id;
+ const data = createData(marketingId, id);
+ cy.subscribeToMarketingConsent(marketingId).then(() => {
+ cy.visit(
+ `/unsubscribe/fake/${encodeURIComponent(data)}/${createToken(
+ data,
+ )}`,
+ );
+ cy.contains('Unable to unsubscribe.');
+ });
+ });
+ });
+ });
+
+ it('should be able to handle a unsubscribe error if token is invalid', () => {
+ cy.createTestUser({
+ isUserEmailValidated: true,
+ }).then(({ cookies }) => {
+ // SC_GU_U is required for the cy.getTestUserDetails
+ const scGuU = cookies.find((cookie) => cookie.key === 'SC_GU_U');
+ if (!scGuU) throw new Error('SC_GU_U cookie not found');
+ cy.setCookie('SC_GU_U', scGuU?.value);
+
+ cy.getTestUserDetails().then(({ user }) => {
+ const id = user.id;
+ const data = createData(newsletterId, id);
+ cy.subscribeToNewsletter(newsletterListId).then(() => {
+ cy.visit(
+ `/unsubscribe/newsletter/${encodeURIComponent(data)}/fake_token`,
+ );
+ cy.contains('Unable to unsubscribe.');
+ });
+ });
+ });
+ });
+
+ it('should be able to handle a unsubscribe error if newsletterId is invalid', () => {
+ cy.createTestUser({
+ isUserEmailValidated: true,
+ }).then(({ cookies }) => {
+ // SC_GU_U is required for the cy.getTestUserDetails
+ const scGuU = cookies.find((cookie) => cookie.key === 'SC_GU_U');
+ if (!scGuU) throw new Error('SC_GU_U cookie not found');
+ cy.setCookie('SC_GU_U', scGuU?.value);
+
+ cy.getTestUserDetails().then(({ user }) => {
+ const id = user.id;
+ const data = createData(`${newsletterId}-fake`, id);
+ cy.subscribeToNewsletter(newsletterListId).then(() => {
+ cy.visit(
+ `/unsubscribe/newsletter/${encodeURIComponent(data)}/${createToken(
+ data,
+ )}`,
+ );
+ cy.contains('Unable to unsubscribe.');
+ });
+ });
+ });
+ });
+
+ it('should be able to handle a unsubscribe error if marketingId is invalid', () => {
+ cy.createTestUser({
+ isUserEmailValidated: true,
+ }).then(({ cookies }) => {
+ // SC_GU_U is required for the cy.getTestUserDetails
+ const scGuU = cookies.find((cookie) => cookie.key === 'SC_GU_U');
+ if (!scGuU) throw new Error('SC_GU_U cookie not found');
+ cy.setCookie('SC_GU_U', scGuU?.value);
+
+ cy.getTestUserDetails().then(({ user }) => {
+ const id = user.id;
+ const data = createData(`${marketingId}-fake`, id);
+ cy.subscribeToMarketingConsent(marketingId).then(() => {
+ cy.visit(
+ `/unsubscribe/marketing/${encodeURIComponent(data)}/${createToken(
+ data,
+ )}`,
+ );
+ cy.contains('Unable to unsubscribe.');
+ });
+ });
+ });
+ });
+
+ it('should be able to handle a unsubscribe error if userId is invalid', () => {
+ cy.createTestUser({
+ isUserEmailValidated: true,
+ }).then(({ cookies }) => {
+ // SC_GU_U is required for the cy.getTestUserDetails
+ const scGuU = cookies.find((cookie) => cookie.key === 'SC_GU_U');
+ if (!scGuU) throw new Error('SC_GU_U cookie not found');
+ cy.setCookie('SC_GU_U', scGuU?.value);
+
+ cy.getTestUserDetails().then(({ user }) => {
+ const id = user.id;
+ const data = createData(marketingId, `${id}0`);
+ cy.subscribeToMarketingConsent(marketingId).then(() => {
+ cy.visit(
+ `/unsubscribe/marketing/${encodeURIComponent(data)}/${createToken(
+ data,
+ )}`,
+ );
+ cy.contains('Unable to unsubscribe.');
+ });
+ });
+ });
+ });
+
+ it('should be able to handle a unsubscribe error if data is invalid', () => {
+ cy.createTestUser({
+ isUserEmailValidated: true,
+ }).then(({ cookies }) => {
+ // SC_GU_U is required for the cy.getTestUserDetails
+ const scGuU = cookies.find((cookie) => cookie.key === 'SC_GU_U');
+ if (!scGuU) throw new Error('SC_GU_U cookie not found');
+ cy.setCookie('SC_GU_U', scGuU?.value);
+
+ cy.getTestUserDetails().then(() => {
+ const data = 'data-is-invalid:yes-123';
+ cy.subscribeToMarketingConsent(marketingId).then(() => {
+ cy.visit(
+ `/unsubscribe/marketing/${encodeURIComponent(data)}/${createToken(
+ data,
+ )}`,
+ );
+ cy.contains('Unable to unsubscribe.');
+ });
+ });
+ });
+ });
});
diff --git a/cypress/integration/mocked-okta/rateLimit.1.cy.ts b/cypress/integration/mocked-okta/rateLimit.1.cy.ts
index 7609f58dc3..6bc462932e 100644
--- a/cypress/integration/mocked-okta/rateLimit.1.cy.ts
+++ b/cypress/integration/mocked-okta/rateLimit.1.cy.ts
@@ -1,153 +1,153 @@
describe('POST requests return a user-facing error message when encountering a rate limit from Okta', () => {
- specify('Submit /signin', () => {
- cy.visit('/signin');
- cy.get('input[name="email"]').type('example@example.com');
- cy.get('input[name="password"]').type('password');
-
- cy.mockNext(429, {
- errorCode: 'E0000047',
- errorSummary: 'API call exceeded rate limit due to too many requests.',
- errorLink: 'E0000047',
- errorId: 'sampleXAy5B35EOzELmZL1zMy',
- errorCauses: [],
- });
- cy.get('button[type=submit]').click();
- cy.contains('There was a problem signing in, please try again.');
- });
-
- specify('Submit /reauthenticate', () => {
- cy.visit('/reauthenticate');
- cy.get('input[name="email"]').type('example@example.com');
- cy.get('input[name="password"]').type('password');
-
- cy.mockNext(429, {
- errorCode: 'E0000047',
- errorSummary: 'API call exceeded rate limit due to too many requests.',
- errorLink: 'E0000047',
- errorId: 'sampleXAy5B35EOzELmZL1zMy',
- errorCauses: [],
- });
- cy.get('button[type=submit]').click();
- cy.contains('There was a problem signing in, please try again.');
- });
-
- specify('Submit /register', () => {
- cy.visit('/register');
- cy.get('input[name="email"]').type('example@example.com');
-
- cy.mockNext(429, {
- errorCode: 'E0000047',
- errorSummary: 'API call exceeded rate limit due to too many requests.',
- errorLink: 'E0000047',
- errorId: 'sampleXAy5B35EOzELmZL1zMy',
- errorCauses: [],
- });
- cy.get('button[type=submit]').click();
- cy.contains('There was a problem registering, please try again.');
- });
-
- specify('Submit /reset-password', () => {
- cy.visit('/reset-password');
- cy.get('input[name="email"]').type('example@example.com');
-
- cy.mockNext(429, {
- errorCode: 'E0000047',
- errorSummary: 'API call exceeded rate limit due to too many requests.',
- errorLink: 'E0000047',
- errorId: 'sampleXAy5B35EOzELmZL1zMy',
- errorCauses: [],
- });
- cy.get('button[type=submit]').click();
- cy.contains('Sorry, something went wrong. Please try again.');
- });
-
- specify('Submit /welcome/resend', () => {
- cy.visit(`/welcome/resend`);
- cy.get('input[name="email"]').type('example@example.com');
-
- cy.mockNext(429, {
- errorCode: 'E0000047',
- errorSummary: 'API call exceeded rate limit due to too many requests.',
- errorLink: 'E0000047',
- errorId: 'sampleXAy5B35EOzELmZL1zMy',
- errorCauses: [],
- });
- cy.get('button[type=submit]').click();
- cy.contains('Sorry, something went wrong. Please try again.');
- });
-
- specify('Submit /welcome/expired', () => {
- cy.visit(`/welcome/expired`);
- cy.get('input[name="email"]').type('example@example.com');
-
- cy.mockNext(429, {
- errorCode: 'E0000047',
- errorSummary: 'API call exceeded rate limit due to too many requests.',
- errorLink: 'E0000047',
- errorId: 'sampleXAy5B35EOzELmZL1zMy',
- errorCauses: [],
- });
- cy.get('button[type=submit]').click();
- cy.contains('Sorry, something went wrong. Please try again.');
- });
-
- specify('Submit /reset-password/resend', () => {
- cy.visit(`/reset-password/resend`);
- cy.get('input[name="email"]').type('example@example.com');
-
- cy.mockNext(429, {
- errorCode: 'E0000047',
- errorSummary: 'API call exceeded rate limit due to too many requests.',
- errorLink: 'E0000047',
- errorId: 'sampleXAy5B35EOzELmZL1zMy',
- errorCauses: [],
- });
- cy.get('button[type=submit]').click();
- cy.contains('Sorry, something went wrong. Please try again.');
- });
-
- specify('Submit /reset-password/expired', () => {
- cy.visit(`/reset-password/expired`);
- cy.get('input[name="email"]').type('example@example.com');
-
- cy.mockNext(429, {
- errorCode: 'E0000047',
- errorSummary: 'API call exceeded rate limit due to too many requests.',
- errorLink: 'E0000047',
- errorId: 'sampleXAy5B35EOzELmZL1zMy',
- errorCauses: [],
- });
- cy.get('button[type=submit]').click();
- cy.contains('Sorry, something went wrong. Please try again.');
- });
-
- specify('Submit /set-password/resend', () => {
- cy.visit(`/set-password/resend`);
- cy.get('input[name="email"]').type('example@example.com');
-
- cy.mockNext(429, {
- errorCode: 'E0000047',
- errorSummary: 'API call exceeded rate limit due to too many requests.',
- errorLink: 'E0000047',
- errorId: 'sampleXAy5B35EOzELmZL1zMy',
- errorCauses: [],
- });
- cy.get('button[type=submit]').click();
- cy.contains('Sorry, something went wrong. Please try again.');
- });
-
- specify('Submit /set-password/expired', () => {
- cy.visit(`/set-password/expired`);
- cy.get('input[name="email"]').type('example@example.com');
-
- cy.mockNext(429, {
- errorCode: 'E0000047',
- errorSummary: 'API call exceeded rate limit due to too many requests.',
- errorLink: 'E0000047',
- errorId: 'sampleXAy5B35EOzELmZL1zMy',
- errorCauses: [],
- });
- cy.get('button[type=submit]').click();
- cy.contains('Sorry, something went wrong. Please try again.');
- });
+ specify('Submit /signin', () => {
+ cy.visit('/signin');
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.get('input[name="password"]').type('password');
+
+ cy.mockNext(429, {
+ errorCode: 'E0000047',
+ errorSummary: 'API call exceeded rate limit due to too many requests.',
+ errorLink: 'E0000047',
+ errorId: 'sampleXAy5B35EOzELmZL1zMy',
+ errorCauses: [],
+ });
+ cy.get('button[type=submit]').click();
+ cy.contains('There was a problem signing in, please try again.');
+ });
+
+ specify('Submit /reauthenticate', () => {
+ cy.visit('/reauthenticate');
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.get('input[name="password"]').type('password');
+
+ cy.mockNext(429, {
+ errorCode: 'E0000047',
+ errorSummary: 'API call exceeded rate limit due to too many requests.',
+ errorLink: 'E0000047',
+ errorId: 'sampleXAy5B35EOzELmZL1zMy',
+ errorCauses: [],
+ });
+ cy.get('button[type=submit]').click();
+ cy.contains('There was a problem signing in, please try again.');
+ });
+
+ specify('Submit /register', () => {
+ cy.visit('/register');
+ cy.get('input[name="email"]').type('example@example.com');
+
+ cy.mockNext(429, {
+ errorCode: 'E0000047',
+ errorSummary: 'API call exceeded rate limit due to too many requests.',
+ errorLink: 'E0000047',
+ errorId: 'sampleXAy5B35EOzELmZL1zMy',
+ errorCauses: [],
+ });
+ cy.get('button[type=submit]').click();
+ cy.contains('There was a problem registering, please try again.');
+ });
+
+ specify('Submit /reset-password', () => {
+ cy.visit('/reset-password');
+ cy.get('input[name="email"]').type('example@example.com');
+
+ cy.mockNext(429, {
+ errorCode: 'E0000047',
+ errorSummary: 'API call exceeded rate limit due to too many requests.',
+ errorLink: 'E0000047',
+ errorId: 'sampleXAy5B35EOzELmZL1zMy',
+ errorCauses: [],
+ });
+ cy.get('button[type=submit]').click();
+ cy.contains('Sorry, something went wrong. Please try again.');
+ });
+
+ specify('Submit /welcome/resend', () => {
+ cy.visit(`/welcome/resend`);
+ cy.get('input[name="email"]').type('example@example.com');
+
+ cy.mockNext(429, {
+ errorCode: 'E0000047',
+ errorSummary: 'API call exceeded rate limit due to too many requests.',
+ errorLink: 'E0000047',
+ errorId: 'sampleXAy5B35EOzELmZL1zMy',
+ errorCauses: [],
+ });
+ cy.get('button[type=submit]').click();
+ cy.contains('Sorry, something went wrong. Please try again.');
+ });
+
+ specify('Submit /welcome/expired', () => {
+ cy.visit(`/welcome/expired`);
+ cy.get('input[name="email"]').type('example@example.com');
+
+ cy.mockNext(429, {
+ errorCode: 'E0000047',
+ errorSummary: 'API call exceeded rate limit due to too many requests.',
+ errorLink: 'E0000047',
+ errorId: 'sampleXAy5B35EOzELmZL1zMy',
+ errorCauses: [],
+ });
+ cy.get('button[type=submit]').click();
+ cy.contains('Sorry, something went wrong. Please try again.');
+ });
+
+ specify('Submit /reset-password/resend', () => {
+ cy.visit(`/reset-password/resend`);
+ cy.get('input[name="email"]').type('example@example.com');
+
+ cy.mockNext(429, {
+ errorCode: 'E0000047',
+ errorSummary: 'API call exceeded rate limit due to too many requests.',
+ errorLink: 'E0000047',
+ errorId: 'sampleXAy5B35EOzELmZL1zMy',
+ errorCauses: [],
+ });
+ cy.get('button[type=submit]').click();
+ cy.contains('Sorry, something went wrong. Please try again.');
+ });
+
+ specify('Submit /reset-password/expired', () => {
+ cy.visit(`/reset-password/expired`);
+ cy.get('input[name="email"]').type('example@example.com');
+
+ cy.mockNext(429, {
+ errorCode: 'E0000047',
+ errorSummary: 'API call exceeded rate limit due to too many requests.',
+ errorLink: 'E0000047',
+ errorId: 'sampleXAy5B35EOzELmZL1zMy',
+ errorCauses: [],
+ });
+ cy.get('button[type=submit]').click();
+ cy.contains('Sorry, something went wrong. Please try again.');
+ });
+
+ specify('Submit /set-password/resend', () => {
+ cy.visit(`/set-password/resend`);
+ cy.get('input[name="email"]').type('example@example.com');
+
+ cy.mockNext(429, {
+ errorCode: 'E0000047',
+ errorSummary: 'API call exceeded rate limit due to too many requests.',
+ errorLink: 'E0000047',
+ errorId: 'sampleXAy5B35EOzELmZL1zMy',
+ errorCauses: [],
+ });
+ cy.get('button[type=submit]').click();
+ cy.contains('Sorry, something went wrong. Please try again.');
+ });
+
+ specify('Submit /set-password/expired', () => {
+ cy.visit(`/set-password/expired`);
+ cy.get('input[name="email"]').type('example@example.com');
+
+ cy.mockNext(429, {
+ errorCode: 'E0000047',
+ errorSummary: 'API call exceeded rate limit due to too many requests.',
+ errorLink: 'E0000047',
+ errorId: 'sampleXAy5B35EOzELmZL1zMy',
+ errorCauses: [],
+ });
+ cy.get('button[type=submit]').click();
+ cy.contains('Sorry, something went wrong. Please try again.');
+ });
});
diff --git a/cypress/integration/mocked-okta/registerController.1.cy.ts b/cypress/integration/mocked-okta/registerController.1.cy.ts
index 6993027418..22d6423c75 100644
--- a/cypress/integration/mocked-okta/registerController.1.cy.ts
+++ b/cypress/integration/mocked-okta/registerController.1.cy.ts
@@ -7,209 +7,209 @@ import successTokenResponse from '../../fixtures/okta-responses/success/token.js
import resetPasswordResponse from '../../fixtures/okta-responses/success/reset-password.json';
beforeEach(() => {
- cy.mockPurge();
+ cy.mockPurge();
});
const verifyInRegularEmailSentPage = () => {
- cy.contains('Check your email inbox');
- cy.contains('Resend email');
+ cy.contains('Check your email inbox');
+ cy.contains('Resend email');
};
userStatuses.forEach((status) => {
- context(`Given I am a ${status || 'nonexistent'} user`, () => {
- context('When I submit the form on /register', () => {
- beforeEach(() => {
- cy.visit(`/register`);
- cy.get('input[name="email"]').type('example@example.com');
- });
- switch (status) {
- case false:
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status: 'STAGED' };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- successTokenResponse.code,
- successTokenResponse.response,
- );
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'ACTIVE':
- specify(
- "Then I should be shown the 'Check your email inbox' page if I have a validated email",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- const responseWithPassword = {
- ...response,
- credentials: {
- ...response.credentials,
- password: {},
- },
- };
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(userResponse.code, responseWithPassword);
- cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- specify(
- "Then I should be shown the 'Check your email inbox' page if I have a validated email but no password",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(userResponse.code, response);
- cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
- // dangerouslyResetPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/reset_password/XE6wE17zmphl3KqAPFxO',
- });
- // validateRecoveryToken()
- cy.mockNext(200, {
- stateToken: 'sometoken',
- });
- // authenticationResetPassword()
- cy.mockNext(200, {});
- // from sendEmailToUnvalidatedUser() --> forgotPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
- });
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- specify(
- "Then I should be shown the 'Check your email inbox' page for social user",
- () => {
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(socialUserResponse.code, socialUserResponse.response);
- cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
- // dangerouslyResetPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/reset_password/XE6wE17zmphl3KqAPFxO',
- });
- // validateRecoveryToken()
- cy.mockNext(200, {
- stateToken: 'sometoken',
- });
- // authenticationResetPassword()
- cy.mockNext(200, {});
- // from sendEmailToUnvalidatedUser() --> forgotPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
- });
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- specify(
- "Then I should be shown the 'Check your email inbox' page if I don't have a validated email and don't have a password set",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userExistsError.code, userExistsError.response);
- // This user response doesn't have a password credential
- cy.mockNext(userResponse.code, response);
- const userGroupsResponseWithoutEmailValidated =
- userGroupsResponse.response.filter(
- (group) =>
- group.profile.name !== 'GuardianUser-EmailValidated',
- );
- cy.mockNext(
- userGroupsResponse.code,
- userGroupsResponseWithoutEmailValidated,
- );
- // dangerouslyResetPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/reset_password/XE6wE17zmphl3KqAPFxO',
- });
- // validateRecoveryToken()
- cy.mockNext(200, {
- stateToken: 'sometoken',
- });
- // authenticationResetPassword()
- cy.mockNext(200, {});
- // from sendEmailToUnvalidatedUser() --> forgotPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
- });
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- specify(
- "Then I should be shown the 'Check your email inbox' page if I don't have a validated email and do have a password set",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- const responseWithPassword = {
- ...response,
- credentials: {
- ...response.credentials,
- password: {},
- },
- };
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(userResponse.code, responseWithPassword);
- cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- //not sure if we need to do anything for the social case here. the only mocked response I can change is the user response
- //but it would be changing fields that no one looks at
- break;
- case 'PROVISIONED':
- case 'STAGED':
- // Then Gateway should generate an activation token
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- successTokenResponse.code,
- successTokenResponse.response,
- );
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'RECOVERY':
- case 'PASSWORD_EXPIRED':
- // Then Gateway should generate a reset password token
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- resetPasswordResponse.code,
- resetPasswordResponse.response,
- );
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- }
- });
- });
+ context(`Given I am a ${status || 'nonexistent'} user`, () => {
+ context('When I submit the form on /register', () => {
+ beforeEach(() => {
+ cy.visit(`/register`);
+ cy.get('input[name="email"]').type('example@example.com');
+ });
+ switch (status) {
+ case false:
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status: 'STAGED' };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ successTokenResponse.code,
+ successTokenResponse.response,
+ );
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'ACTIVE':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page if I have a validated email",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ const responseWithPassword = {
+ ...response,
+ credentials: {
+ ...response.credentials,
+ password: {},
+ },
+ };
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(userResponse.code, responseWithPassword);
+ cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ specify(
+ "Then I should be shown the 'Check your email inbox' page if I have a validated email but no password",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
+ // dangerouslyResetPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/reset_password/XE6wE17zmphl3KqAPFxO',
+ });
+ // validateRecoveryToken()
+ cy.mockNext(200, {
+ stateToken: 'sometoken',
+ });
+ // authenticationResetPassword()
+ cy.mockNext(200, {});
+ // from sendEmailToUnvalidatedUser() --> forgotPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
+ });
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ specify(
+ "Then I should be shown the 'Check your email inbox' page for social user",
+ () => {
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(socialUserResponse.code, socialUserResponse.response);
+ cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
+ // dangerouslyResetPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/reset_password/XE6wE17zmphl3KqAPFxO',
+ });
+ // validateRecoveryToken()
+ cy.mockNext(200, {
+ stateToken: 'sometoken',
+ });
+ // authenticationResetPassword()
+ cy.mockNext(200, {});
+ // from sendEmailToUnvalidatedUser() --> forgotPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
+ });
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ specify(
+ "Then I should be shown the 'Check your email inbox' page if I don't have a validated email and don't have a password set",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ // This user response doesn't have a password credential
+ cy.mockNext(userResponse.code, response);
+ const userGroupsResponseWithoutEmailValidated =
+ userGroupsResponse.response.filter(
+ (group) =>
+ group.profile.name !== 'GuardianUser-EmailValidated',
+ );
+ cy.mockNext(
+ userGroupsResponse.code,
+ userGroupsResponseWithoutEmailValidated,
+ );
+ // dangerouslyResetPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/reset_password/XE6wE17zmphl3KqAPFxO',
+ });
+ // validateRecoveryToken()
+ cy.mockNext(200, {
+ stateToken: 'sometoken',
+ });
+ // authenticationResetPassword()
+ cy.mockNext(200, {});
+ // from sendEmailToUnvalidatedUser() --> forgotPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
+ });
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ specify(
+ "Then I should be shown the 'Check your email inbox' page if I don't have a validated email and do have a password set",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ const responseWithPassword = {
+ ...response,
+ credentials: {
+ ...response.credentials,
+ password: {},
+ },
+ };
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(userResponse.code, responseWithPassword);
+ cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ //not sure if we need to do anything for the social case here. the only mocked response I can change is the user response
+ //but it would be changing fields that no one looks at
+ break;
+ case 'PROVISIONED':
+ case 'STAGED':
+ // Then Gateway should generate an activation token
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ successTokenResponse.code,
+ successTokenResponse.response,
+ );
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'RECOVERY':
+ case 'PASSWORD_EXPIRED':
+ // Then Gateway should generate a reset password token
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ resetPasswordResponse.code,
+ resetPasswordResponse.response,
+ );
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ }
+ });
+ });
});
diff --git a/cypress/integration/mocked-okta/resendEmailController.3.cy.ts b/cypress/integration/mocked-okta/resendEmailController.3.cy.ts
index d23f5273d0..01d1f18528 100644
--- a/cypress/integration/mocked-okta/resendEmailController.3.cy.ts
+++ b/cypress/integration/mocked-okta/resendEmailController.3.cy.ts
@@ -7,497 +7,497 @@ import successTokenResponse from '../../fixtures/okta-responses/success/token.js
import resetPasswordResponse from '../../fixtures/okta-responses/success/reset-password.json';
beforeEach(() => {
- cy.mockPurge();
+ cy.mockPurge();
});
const verifyInRegularEmailSentPage = () => {
- cy.contains('Check your email inbox');
- cy.contains('Resend email');
- cy.contains('Email sent');
- cy.contains('within 2 minutes').should('not.exist');
+ cy.contains('Check your email inbox');
+ cy.contains('Resend email');
+ cy.contains('Email sent');
+ cy.contains('within 2 minutes').should('not.exist');
};
userStatuses.forEach((status) => {
- context(`Given I am a ${status || 'nonexistent'} user`, () => {
- context('When I submit the form on /register/email-sent', () => {
- beforeEach(() => {
- // We mock the encrypted state cookie here to trick the endpoint
- // into thinking we've just gone through the preceeding flow.
- // For readEncryptedStateCookie to succeed, it relies on a testing
- // env variable to be set, otherwise it won't be able to read the cookie.
- cy.setEncryptedStateCookie({
- email: 'example@example.com',
- status: String(status),
- });
- cy.visit(`/register/email-sent`);
- });
- switch (status) {
- case false:
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status: 'STAGED' };
- cy.mockNext(userResponse.code, response);
- cy.get('[data-cy="main-form-submit-button"]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'ACTIVE':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(userResponse.code, response);
- cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
- cy.get('[data-cy="main-form-submit-button"]').click();
- verifyInRegularEmailSentPage();
- },
- );
- specify(
- "Then I should be shown the 'Check your email inbox' page for social users ",
- () => {
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(socialUserResponse.code, socialUserResponse.response);
- cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
- cy.get('[data-cy="main-form-submit-button"]').click();
- verifyInRegularEmailSentPage();
- },
- );
- specify(
- "Then I should be shown the 'Check your email inbox' page if I don't have a validated email and don't have a password set",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userExistsError.code, userExistsError.response);
- // This user response doesn't have a password credential
- cy.mockNext(userResponse.code, response);
- const userGroupsResponseWithoutEmailValidated =
- userGroupsResponse.response.filter(
- (group) =>
- group.profile.name !== 'GuardianUser-EmailValidated',
- );
- cy.mockNext(
- userGroupsResponse.code,
- userGroupsResponseWithoutEmailValidated,
- );
- // dangerouslyResetPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/reset_password/XE6wE17zmphl3KqAPFxO',
- });
- // validateRecoveryToken()
- cy.mockNext(200, {
- stateToken: 'sometoken',
- });
- // authenticationResetPassword()
- cy.mockNext(200, {});
- // from sendEmailToUnvalidatedUser() --> forgotPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
- });
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- specify(
- "Then I should be shown the 'Check your email inbox' page if I don't have a validated email and do have a password set",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(userResponse.code, response);
- cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- //i Think this is the same as register.. I don't know if I should add the modked social user here
- // when the execution doesn't check the credentials part of the response
- break;
- case 'PROVISIONED':
- case 'STAGED':
- // Then Gateway should generate an activation token
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- successTokenResponse.code,
- successTokenResponse.response,
- );
- cy.get('[data-cy="main-form-submit-button"]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'RECOVERY':
- case 'PASSWORD_EXPIRED':
- // Then Gateway should generate a reset password token
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- resetPasswordResponse.code,
- resetPasswordResponse.response,
- );
- cy.get('[data-cy="main-form-submit-button"]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- }
- });
- context('When I submit the form on /welcome/email-sent', () => {
- beforeEach(() => {
- // We mock the encrypted state cookie here to trick the endpoint
- // into thinking we've just gone through the preceeding flow.
- // For readEncryptedStateCookie to succeed, it relies on a testing
- // env variable to be set, otherwise it won't be able to read the cookie.
- cy.setEncryptedStateCookie({
- email: 'example@example.com',
- status: String(status),
- });
- cy.visit(`/welcome/email-sent`);
- });
- switch (status) {
- case false:
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status: 'STAGED' };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- successTokenResponse.code,
- successTokenResponse.response,
- );
- cy.get('[data-cy="main-form-submit-button"]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'ACTIVE':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- const responseWithPassword = {
- ...response,
- credentials: {
- ...response.credentials,
- password: {},
- },
- };
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(userResponse.code, responseWithPassword);
- cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.contains('Check your email inbox');
- cy.contains('Resend email');
- cy.contains('Email sent');
- },
- );
- specify(
- "Then I should be shown the 'Check your email inbox' page for social user",
- () => {
- cy.mockNext(userExistsError.code, userExistsError.response);
- // This user response doesn't have a password, which is what we want
- // for a social user.
- cy.mockNext(socialUserResponse.code, socialUserResponse.response);
- cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
- // dangerouslyResetPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/reset_password/XE6wE17zmphl3KqAPFxO',
- });
- // validateRecoveryToken()
- cy.mockNext(200, {
- stateToken: 'sometoken',
- });
- // authenticationResetPassword()
- cy.mockNext(200, {});
- // from sendEmailToUnvalidatedUser() --> forgotPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
- });
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.contains('Check your email inbox');
- cy.contains('Resend email');
- cy.contains('Email sent');
- },
- );
- break;
- case 'PROVISIONED':
- case 'STAGED':
- // Then Gateway should generate an activation token
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- successTokenResponse.code,
- successTokenResponse.response,
- );
- cy.get('[data-cy="main-form-submit-button"]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'RECOVERY':
- case 'PASSWORD_EXPIRED':
- // Then Gateway should generate a reset password token
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- resetPasswordResponse.code,
- resetPasswordResponse.response,
- );
- cy.get('[data-cy="main-form-submit-button"]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- }
- });
- context('When I submit the form on /welcome/resend', () => {
- beforeEach(() => {
- cy.visit(`/welcome/resend`);
- cy.get('input[name="email"]').type('example@example.com');
- });
- switch (status) {
- case false:
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status: 'STAGED' };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- successTokenResponse.code,
- successTokenResponse.response,
- );
- cy.get('[data-cy="main-form-submit-button"]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'ACTIVE':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- const responseWithPassword = {
- ...response,
- credentials: {
- ...response.credentials,
- password: {},
- },
- };
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(userResponse.code, responseWithPassword);
- cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
- cy.get('[data-cy="main-form-submit-button"]').click();
- verifyInRegularEmailSentPage();
- },
- );
- specify(
- "Then I should be shown the 'Check your email inbox' page for social user",
- () => {
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(socialUserResponse.code, socialUserResponse.response);
- cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
- // dangerouslyResetPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/reset_password/XE6wE17zmphl3KqAPFxO',
- });
- // validateRecoveryToken()
- cy.mockNext(200, {
- stateToken: 'sometoken',
- });
- // authenticationResetPassword()
- cy.mockNext(200, {});
- // from sendEmailToUnvalidatedUser() --> forgotPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
- });
- cy.get('[data-cy="main-form-submit-button"]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'PROVISIONED':
- case 'STAGED':
- // Then Gateway should generate an activation token
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- successTokenResponse.code,
- successTokenResponse.response,
- );
- cy.get('[data-cy="main-form-submit-button"]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'RECOVERY':
- case 'PASSWORD_EXPIRED':
- // Then Gateway should generate a reset password token
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- resetPasswordResponse.code,
- resetPasswordResponse.response,
- );
- cy.get('[data-cy="main-form-submit-button"]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- }
- });
- context('When I submit the form on /welcome/expired', () => {
- beforeEach(() => {
- cy.visit(`/welcome/expired`);
- cy.get('input[name="email"]').type('example@example.com');
- });
- switch (status) {
- case false:
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status: 'STAGED' };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- successTokenResponse.code,
- successTokenResponse.response,
- );
- cy.get('[data-cy="main-form-submit-button"]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'ACTIVE':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- const responseWithPassword = {
- ...response,
- credentials: {
- ...response.credentials,
- password: {},
- },
- };
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(userResponse.code, responseWithPassword);
- cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
- cy.get('[data-cy="main-form-submit-button"]').click();
- verifyInRegularEmailSentPage();
- },
- );
- specify(
- "Then I should be shown the 'Check your email inbox' page for social users",
- () => {
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(socialUserResponse.code, socialUserResponse.response);
- cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
- // dangerouslyResetPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/reset_password/XE6wE17zmphl3KqAPFxO',
- });
- // validateRecoveryToken()
- cy.mockNext(200, {
- stateToken: 'sometoken',
- });
- // authenticationResetPassword()
- cy.mockNext(200, {});
- // from sendEmailToUnvalidatedUser() --> forgotPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
- });
- cy.get('[data-cy="main-form-submit-button"]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'PROVISIONED':
- case 'STAGED':
- // Then Gateway should generate an activation token
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- successTokenResponse.code,
- successTokenResponse.response,
- );
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.contains('Check your email inbox');
- cy.contains('Resend email');
- cy.contains('Email sent');
- },
- );
- break;
- case 'RECOVERY':
- case 'PASSWORD_EXPIRED':
- // Then Gateway should generate a reset password token
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userExistsError.code, userExistsError.response);
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- resetPasswordResponse.code,
- resetPasswordResponse.response,
- );
- cy.get('[data-cy="main-form-submit-button"]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- }
- });
- });
+ context(`Given I am a ${status || 'nonexistent'} user`, () => {
+ context('When I submit the form on /register/email-sent', () => {
+ beforeEach(() => {
+ // We mock the encrypted state cookie here to trick the endpoint
+ // into thinking we've just gone through the preceeding flow.
+ // For readEncryptedStateCookie to succeed, it relies on a testing
+ // env variable to be set, otherwise it won't be able to read the cookie.
+ cy.setEncryptedStateCookie({
+ email: 'example@example.com',
+ status: String(status),
+ });
+ cy.visit(`/register/email-sent`);
+ });
+ switch (status) {
+ case false:
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status: 'STAGED' };
+ cy.mockNext(userResponse.code, response);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'ACTIVE':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ specify(
+ "Then I should be shown the 'Check your email inbox' page for social users ",
+ () => {
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(socialUserResponse.code, socialUserResponse.response);
+ cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ specify(
+ "Then I should be shown the 'Check your email inbox' page if I don't have a validated email and don't have a password set",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ // This user response doesn't have a password credential
+ cy.mockNext(userResponse.code, response);
+ const userGroupsResponseWithoutEmailValidated =
+ userGroupsResponse.response.filter(
+ (group) =>
+ group.profile.name !== 'GuardianUser-EmailValidated',
+ );
+ cy.mockNext(
+ userGroupsResponse.code,
+ userGroupsResponseWithoutEmailValidated,
+ );
+ // dangerouslyResetPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/reset_password/XE6wE17zmphl3KqAPFxO',
+ });
+ // validateRecoveryToken()
+ cy.mockNext(200, {
+ stateToken: 'sometoken',
+ });
+ // authenticationResetPassword()
+ cy.mockNext(200, {});
+ // from sendEmailToUnvalidatedUser() --> forgotPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
+ });
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ specify(
+ "Then I should be shown the 'Check your email inbox' page if I don't have a validated email and do have a password set",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ //i Think this is the same as register.. I don't know if I should add the modked social user here
+ // when the execution doesn't check the credentials part of the response
+ break;
+ case 'PROVISIONED':
+ case 'STAGED':
+ // Then Gateway should generate an activation token
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ successTokenResponse.code,
+ successTokenResponse.response,
+ );
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'RECOVERY':
+ case 'PASSWORD_EXPIRED':
+ // Then Gateway should generate a reset password token
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ resetPasswordResponse.code,
+ resetPasswordResponse.response,
+ );
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ }
+ });
+ context('When I submit the form on /welcome/email-sent', () => {
+ beforeEach(() => {
+ // We mock the encrypted state cookie here to trick the endpoint
+ // into thinking we've just gone through the preceeding flow.
+ // For readEncryptedStateCookie to succeed, it relies on a testing
+ // env variable to be set, otherwise it won't be able to read the cookie.
+ cy.setEncryptedStateCookie({
+ email: 'example@example.com',
+ status: String(status),
+ });
+ cy.visit(`/welcome/email-sent`);
+ });
+ switch (status) {
+ case false:
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status: 'STAGED' };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ successTokenResponse.code,
+ successTokenResponse.response,
+ );
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'ACTIVE':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ const responseWithPassword = {
+ ...response,
+ credentials: {
+ ...response.credentials,
+ password: {},
+ },
+ };
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(userResponse.code, responseWithPassword);
+ cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.contains('Check your email inbox');
+ cy.contains('Resend email');
+ cy.contains('Email sent');
+ },
+ );
+ specify(
+ "Then I should be shown the 'Check your email inbox' page for social user",
+ () => {
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ // This user response doesn't have a password, which is what we want
+ // for a social user.
+ cy.mockNext(socialUserResponse.code, socialUserResponse.response);
+ cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
+ // dangerouslyResetPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/reset_password/XE6wE17zmphl3KqAPFxO',
+ });
+ // validateRecoveryToken()
+ cy.mockNext(200, {
+ stateToken: 'sometoken',
+ });
+ // authenticationResetPassword()
+ cy.mockNext(200, {});
+ // from sendEmailToUnvalidatedUser() --> forgotPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
+ });
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.contains('Check your email inbox');
+ cy.contains('Resend email');
+ cy.contains('Email sent');
+ },
+ );
+ break;
+ case 'PROVISIONED':
+ case 'STAGED':
+ // Then Gateway should generate an activation token
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ successTokenResponse.code,
+ successTokenResponse.response,
+ );
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'RECOVERY':
+ case 'PASSWORD_EXPIRED':
+ // Then Gateway should generate a reset password token
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ resetPasswordResponse.code,
+ resetPasswordResponse.response,
+ );
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ }
+ });
+ context('When I submit the form on /welcome/resend', () => {
+ beforeEach(() => {
+ cy.visit(`/welcome/resend`);
+ cy.get('input[name="email"]').type('example@example.com');
+ });
+ switch (status) {
+ case false:
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status: 'STAGED' };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ successTokenResponse.code,
+ successTokenResponse.response,
+ );
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'ACTIVE':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ const responseWithPassword = {
+ ...response,
+ credentials: {
+ ...response.credentials,
+ password: {},
+ },
+ };
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(userResponse.code, responseWithPassword);
+ cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ specify(
+ "Then I should be shown the 'Check your email inbox' page for social user",
+ () => {
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(socialUserResponse.code, socialUserResponse.response);
+ cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
+ // dangerouslyResetPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/reset_password/XE6wE17zmphl3KqAPFxO',
+ });
+ // validateRecoveryToken()
+ cy.mockNext(200, {
+ stateToken: 'sometoken',
+ });
+ // authenticationResetPassword()
+ cy.mockNext(200, {});
+ // from sendEmailToUnvalidatedUser() --> forgotPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
+ });
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'PROVISIONED':
+ case 'STAGED':
+ // Then Gateway should generate an activation token
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ successTokenResponse.code,
+ successTokenResponse.response,
+ );
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'RECOVERY':
+ case 'PASSWORD_EXPIRED':
+ // Then Gateway should generate a reset password token
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ resetPasswordResponse.code,
+ resetPasswordResponse.response,
+ );
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ }
+ });
+ context('When I submit the form on /welcome/expired', () => {
+ beforeEach(() => {
+ cy.visit(`/welcome/expired`);
+ cy.get('input[name="email"]').type('example@example.com');
+ });
+ switch (status) {
+ case false:
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status: 'STAGED' };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ successTokenResponse.code,
+ successTokenResponse.response,
+ );
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'ACTIVE':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ const responseWithPassword = {
+ ...response,
+ credentials: {
+ ...response.credentials,
+ password: {},
+ },
+ };
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(userResponse.code, responseWithPassword);
+ cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ specify(
+ "Then I should be shown the 'Check your email inbox' page for social users",
+ () => {
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(socialUserResponse.code, socialUserResponse.response);
+ cy.mockNext(userGroupsResponse.code, userGroupsResponse.response);
+ // dangerouslyResetPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/reset_password/XE6wE17zmphl3KqAPFxO',
+ });
+ // validateRecoveryToken()
+ cy.mockNext(200, {
+ stateToken: 'sometoken',
+ });
+ // authenticationResetPassword()
+ cy.mockNext(200, {});
+ // from sendEmailToUnvalidatedUser() --> forgotPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
+ });
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'PROVISIONED':
+ case 'STAGED':
+ // Then Gateway should generate an activation token
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ successTokenResponse.code,
+ successTokenResponse.response,
+ );
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.contains('Check your email inbox');
+ cy.contains('Resend email');
+ cy.contains('Email sent');
+ },
+ );
+ break;
+ case 'RECOVERY':
+ case 'PASSWORD_EXPIRED':
+ // Then Gateway should generate a reset password token
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userExistsError.code, userExistsError.response);
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ resetPasswordResponse.code,
+ resetPasswordResponse.response,
+ );
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ }
+ });
+ });
});
diff --git a/cypress/integration/mocked-okta/resetPasswordController.4.cy.ts b/cypress/integration/mocked-okta/resetPasswordController.4.cy.ts
index 50c21bac94..e51b75b0ec 100644
--- a/cypress/integration/mocked-okta/resetPasswordController.4.cy.ts
+++ b/cypress/integration/mocked-okta/resetPasswordController.4.cy.ts
@@ -8,668 +8,668 @@ import resetPasswordResponse from '../../fixtures/okta-responses/success/reset-p
import verifyRecoveryTokenReponse from '../../fixtures/okta-responses/success/verify-recovery-token.json';
import authResetPasswordResponse from '../../fixtures/okta-responses/success/auth-reset-password.json';
beforeEach(() => {
- cy.mockPurge();
+ cy.mockPurge();
});
const verifyIn2MinutesEmailSentPage = () => {
- cy.contains('Check your email inbox');
- cy.contains('Resend email');
- cy.contains('Email sent');
- cy.contains('within 2 minutes');
+ cy.contains('Check your email inbox');
+ cy.contains('Resend email');
+ cy.contains('Email sent');
+ cy.contains('within 2 minutes');
};
const verifyInRegularEmailSentPage = () => {
- cy.contains('Check your email inbox');
- cy.contains('Resend email');
- cy.contains('Email sent');
- cy.contains('within 2 minutes').should('not.exist');
+ cy.contains('Check your email inbox');
+ cy.contains('Resend email');
+ cy.contains('Email sent');
+ cy.contains('within 2 minutes').should('not.exist');
};
const setupMocksForSocialUserPasswordReset = () => {
- // Response from getUser()
- cy.mockNext(socialUserResponse.code, socialUserResponse.response);
- // Response from sendForgotPasswordEmail() - an Okta error
- cy.mockNext(oktaPermissionsError.code, oktaPermissionsError.response);
- // Response from dangerouslyResetPassword() - a reset password URL
- cy.mockNext(resetPasswordResponse.code, resetPasswordResponse.response);
- // Response from validateRecoveryToken() - a state token
- cy.mockNext(
- verifyRecoveryTokenReponse.code,
- verifyRecoveryTokenReponse.response,
- );
- // Response from resetPassword()
- cy.mockNext(
- authResetPasswordResponse.code,
- authResetPasswordResponse.response,
- );
+ // Response from getUser()
+ cy.mockNext(socialUserResponse.code, socialUserResponse.response);
+ // Response from sendForgotPasswordEmail() - an Okta error
+ cy.mockNext(oktaPermissionsError.code, oktaPermissionsError.response);
+ // Response from dangerouslyResetPassword() - a reset password URL
+ cy.mockNext(resetPasswordResponse.code, resetPasswordResponse.response);
+ // Response from validateRecoveryToken() - a state token
+ cy.mockNext(
+ verifyRecoveryTokenReponse.code,
+ verifyRecoveryTokenReponse.response,
+ );
+ // Response from resetPassword()
+ cy.mockNext(
+ authResetPasswordResponse.code,
+ authResetPasswordResponse.response,
+ );
- // retry sending the email now that the user is "fixed"
- // so we need to mock the same as for the non social user
- cy.mockNext(socialUserResponse.code, socialUserResponse.response);
- // forgotPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
- });
+ // retry sending the email now that the user is "fixed"
+ // so we need to mock the same as for the non social user
+ cy.mockNext(socialUserResponse.code, socialUserResponse.response);
+ // forgotPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
+ });
};
userStatuses.forEach((status) => {
- context(`Given I am a ${status || 'nonexistent'} user`, () => {
- context('When I submit the form on /reset-password', () => {
- beforeEach(() => {
- cy.visit(`/reset-password`);
- cy.get('input[name="email"]').type('example@example.com');
- });
- switch (status) {
- case false:
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- cy.mockNext(userNotFoundError.code, userNotFoundError.response);
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- break;
- case 'ACTIVE':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- // forgotPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
- });
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- specify(
- "Then I should be shown the 'Check your email inbox' page for social user",
- () => {
- setupMocksForSocialUserPasswordReset();
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- break;
- case 'PROVISIONED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(tokenResponse.code, tokenResponse.response);
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- break;
- case 'STAGED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(tokenResponse.code, tokenResponse.response);
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- break;
- case 'RECOVERY':
- case 'PASSWORD_EXPIRED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- resetPasswordResponse.code,
- resetPasswordResponse.response,
- );
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- break;
- }
- });
- context('When I submit the form on /reset-password/email-sent', () => {
- beforeEach(() => {
- // We mock the encrypted state cookie here to trick the endpoint
- // into thinking we've just gone through the preceeding flow.
- // For readEncryptedStateCookie to succeed, it relies on a testing
- // env variable to be set, otherwise it won't be able to read the cookie.
- cy.setEncryptedStateCookie({
- email: 'example@example.com',
- status: String(status),
- });
- cy.visit(`/reset-password/email-sent`);
- });
- switch (status) {
- case false:
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- cy.mockNext(userNotFoundError.code, userNotFoundError.response);
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- break;
- case 'ACTIVE':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- // forgotPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
- });
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- specify(
- "Then I should be shown the 'Check your email inbox' page for social user",
- () => {
- setupMocksForSocialUserPasswordReset();
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- break;
- case 'PROVISIONED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(tokenResponse.code, tokenResponse.response);
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- break;
- case 'STAGED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(tokenResponse.code, tokenResponse.response);
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- break;
- case 'RECOVERY':
- case 'PASSWORD_EXPIRED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- resetPasswordResponse.code,
- resetPasswordResponse.response,
- );
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- break;
- }
- });
- context('When I submit the form on /reset-password/resend', () => {
- beforeEach(() => {
- cy.visit(`/reset-password/resend`);
- cy.get('input[name="email"]').type('example@example.com');
- });
- switch (status) {
- case false:
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- cy.mockNext(userNotFoundError.code, userNotFoundError.response);
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- break;
- case 'ACTIVE':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- // forgotPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
- });
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- specify(
- "Then I should be shown the 'Check your email inbox' page for social user",
- () => {
- setupMocksForSocialUserPasswordReset();
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- break;
- case 'PROVISIONED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(tokenResponse.code, tokenResponse.response);
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- break;
- case 'STAGED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(tokenResponse.code, tokenResponse.response);
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- break;
- case 'RECOVERY':
- case 'PASSWORD_EXPIRED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- resetPasswordResponse.code,
- resetPasswordResponse.response,
- );
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- break;
- }
- });
- context('When I submit the form on /reset-password/expired', () => {
- beforeEach(() => {
- cy.visit(`/reset-password/expired`);
- cy.get('input[name="email"]').type('example@example.com');
- });
- switch (status) {
- case false:
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- cy.mockNext(userNotFoundError.code, userNotFoundError.response);
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- break;
- case 'ACTIVE':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- // forgotPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
- });
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- specify(
- "Then I should be shown the 'Check your email inbox' page for social user",
- () => {
- setupMocksForSocialUserPasswordReset();
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- break;
- case 'PROVISIONED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(tokenResponse.code, tokenResponse.response);
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- break;
- case 'STAGED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(tokenResponse.code, tokenResponse.response);
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- break;
- case 'RECOVERY':
- case 'PASSWORD_EXPIRED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- resetPasswordResponse.code,
- resetPasswordResponse.response,
- );
- cy.get('button[type=submit]').click();
- verifyIn2MinutesEmailSentPage();
- },
- );
- break;
- }
- });
- context('When I submit the form on /set-password/email-sent', () => {
- beforeEach(() => {
- // We mock the encrypted state cookie here to trick the endpoint
- // into thinking we've just gone through the preceeding flow.
- // For readEncryptedStateCookie to succeed, it relies on a testing
- // env variable to be set, otherwise it won't be able to read the cookie.
- cy.setEncryptedStateCookie({
- email: 'example@example.com',
- status: String(status),
- });
- cy.visit(`/set-password/email-sent`);
- });
- switch (status) {
- case false:
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- cy.mockNext(userNotFoundError.code, userNotFoundError.response);
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'ACTIVE':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- // forgotPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
- });
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- specify(
- "Then I should be shown the 'Check your email inbox' page for social user",
- () => {
- setupMocksForSocialUserPasswordReset();
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'PROVISIONED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(tokenResponse.code, tokenResponse.response);
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'STAGED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(tokenResponse.code, tokenResponse.response);
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'RECOVERY':
- case 'PASSWORD_EXPIRED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- resetPasswordResponse.code,
- resetPasswordResponse.response,
- );
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- }
- });
- context('When I submit the form on /set-password/resend', () => {
- beforeEach(() => {
- cy.visit(`/set-password/resend`);
- cy.get('input[name="email"]').type('example@example.com');
- });
- switch (status) {
- case false:
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- cy.mockNext(userNotFoundError.code, userNotFoundError.response);
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'ACTIVE':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- // forgotPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
- });
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- specify(
- "Then I should be shown the 'Check your email inbox' page for social user",
- () => {
- setupMocksForSocialUserPasswordReset();
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'PROVISIONED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(tokenResponse.code, tokenResponse.response);
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'STAGED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(tokenResponse.code, tokenResponse.response);
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'RECOVERY':
- case 'PASSWORD_EXPIRED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- resetPasswordResponse.code,
- resetPasswordResponse.response,
- );
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- }
- });
+ context(`Given I am a ${status || 'nonexistent'} user`, () => {
+ context('When I submit the form on /reset-password', () => {
+ beforeEach(() => {
+ cy.visit(`/reset-password`);
+ cy.get('input[name="email"]').type('example@example.com');
+ });
+ switch (status) {
+ case false:
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ cy.mockNext(userNotFoundError.code, userNotFoundError.response);
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ break;
+ case 'ACTIVE':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ // forgotPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
+ });
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ specify(
+ "Then I should be shown the 'Check your email inbox' page for social user",
+ () => {
+ setupMocksForSocialUserPasswordReset();
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ break;
+ case 'PROVISIONED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(tokenResponse.code, tokenResponse.response);
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ break;
+ case 'STAGED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(tokenResponse.code, tokenResponse.response);
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ break;
+ case 'RECOVERY':
+ case 'PASSWORD_EXPIRED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ resetPasswordResponse.code,
+ resetPasswordResponse.response,
+ );
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ break;
+ }
+ });
+ context('When I submit the form on /reset-password/email-sent', () => {
+ beforeEach(() => {
+ // We mock the encrypted state cookie here to trick the endpoint
+ // into thinking we've just gone through the preceeding flow.
+ // For readEncryptedStateCookie to succeed, it relies on a testing
+ // env variable to be set, otherwise it won't be able to read the cookie.
+ cy.setEncryptedStateCookie({
+ email: 'example@example.com',
+ status: String(status),
+ });
+ cy.visit(`/reset-password/email-sent`);
+ });
+ switch (status) {
+ case false:
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ cy.mockNext(userNotFoundError.code, userNotFoundError.response);
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ break;
+ case 'ACTIVE':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ // forgotPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
+ });
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ specify(
+ "Then I should be shown the 'Check your email inbox' page for social user",
+ () => {
+ setupMocksForSocialUserPasswordReset();
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ break;
+ case 'PROVISIONED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(tokenResponse.code, tokenResponse.response);
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ break;
+ case 'STAGED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(tokenResponse.code, tokenResponse.response);
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ break;
+ case 'RECOVERY':
+ case 'PASSWORD_EXPIRED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ resetPasswordResponse.code,
+ resetPasswordResponse.response,
+ );
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ break;
+ }
+ });
+ context('When I submit the form on /reset-password/resend', () => {
+ beforeEach(() => {
+ cy.visit(`/reset-password/resend`);
+ cy.get('input[name="email"]').type('example@example.com');
+ });
+ switch (status) {
+ case false:
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ cy.mockNext(userNotFoundError.code, userNotFoundError.response);
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ break;
+ case 'ACTIVE':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ // forgotPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
+ });
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ specify(
+ "Then I should be shown the 'Check your email inbox' page for social user",
+ () => {
+ setupMocksForSocialUserPasswordReset();
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ break;
+ case 'PROVISIONED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(tokenResponse.code, tokenResponse.response);
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ break;
+ case 'STAGED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(tokenResponse.code, tokenResponse.response);
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ break;
+ case 'RECOVERY':
+ case 'PASSWORD_EXPIRED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ resetPasswordResponse.code,
+ resetPasswordResponse.response,
+ );
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ break;
+ }
+ });
+ context('When I submit the form on /reset-password/expired', () => {
+ beforeEach(() => {
+ cy.visit(`/reset-password/expired`);
+ cy.get('input[name="email"]').type('example@example.com');
+ });
+ switch (status) {
+ case false:
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ cy.mockNext(userNotFoundError.code, userNotFoundError.response);
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ break;
+ case 'ACTIVE':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ // forgotPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
+ });
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ specify(
+ "Then I should be shown the 'Check your email inbox' page for social user",
+ () => {
+ setupMocksForSocialUserPasswordReset();
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ break;
+ case 'PROVISIONED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(tokenResponse.code, tokenResponse.response);
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ break;
+ case 'STAGED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(tokenResponse.code, tokenResponse.response);
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ break;
+ case 'RECOVERY':
+ case 'PASSWORD_EXPIRED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ resetPasswordResponse.code,
+ resetPasswordResponse.response,
+ );
+ cy.get('button[type=submit]').click();
+ verifyIn2MinutesEmailSentPage();
+ },
+ );
+ break;
+ }
+ });
+ context('When I submit the form on /set-password/email-sent', () => {
+ beforeEach(() => {
+ // We mock the encrypted state cookie here to trick the endpoint
+ // into thinking we've just gone through the preceeding flow.
+ // For readEncryptedStateCookie to succeed, it relies on a testing
+ // env variable to be set, otherwise it won't be able to read the cookie.
+ cy.setEncryptedStateCookie({
+ email: 'example@example.com',
+ status: String(status),
+ });
+ cy.visit(`/set-password/email-sent`);
+ });
+ switch (status) {
+ case false:
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ cy.mockNext(userNotFoundError.code, userNotFoundError.response);
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'ACTIVE':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ // forgotPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
+ });
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ specify(
+ "Then I should be shown the 'Check your email inbox' page for social user",
+ () => {
+ setupMocksForSocialUserPasswordReset();
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'PROVISIONED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(tokenResponse.code, tokenResponse.response);
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'STAGED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(tokenResponse.code, tokenResponse.response);
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'RECOVERY':
+ case 'PASSWORD_EXPIRED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ resetPasswordResponse.code,
+ resetPasswordResponse.response,
+ );
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ }
+ });
+ context('When I submit the form on /set-password/resend', () => {
+ beforeEach(() => {
+ cy.visit(`/set-password/resend`);
+ cy.get('input[name="email"]').type('example@example.com');
+ });
+ switch (status) {
+ case false:
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ cy.mockNext(userNotFoundError.code, userNotFoundError.response);
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'ACTIVE':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ // forgotPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
+ });
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ specify(
+ "Then I should be shown the 'Check your email inbox' page for social user",
+ () => {
+ setupMocksForSocialUserPasswordReset();
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'PROVISIONED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(tokenResponse.code, tokenResponse.response);
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'STAGED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(tokenResponse.code, tokenResponse.response);
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'RECOVERY':
+ case 'PASSWORD_EXPIRED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ resetPasswordResponse.code,
+ resetPasswordResponse.response,
+ );
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ }
+ });
- context('When I submit the form on /set-password/expired', () => {
- beforeEach(() => {
- cy.visit(`/set-password/expired`);
- cy.get('input[name="email"]').type('example@example.com');
- });
- switch (status) {
- case false:
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- cy.mockNext(userNotFoundError.code, userNotFoundError.response);
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'ACTIVE':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- // forgotPassword()
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
- });
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- specify(
- "Then I should be shown the 'Check your email inbox' page for social user",
- () => {
- setupMocksForSocialUserPasswordReset();
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'PROVISIONED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(tokenResponse.code, tokenResponse.response);
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'STAGED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(tokenResponse.code, tokenResponse.response);
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- case 'RECOVERY':
- case 'PASSWORD_EXPIRED':
- specify(
- "Then I should be shown the 'Check your email inbox' page",
- () => {
- // Set the correct user status on the response
- const response = { ...userResponse.response, status };
- cy.mockNext(userResponse.code, response);
- cy.mockNext(
- resetPasswordResponse.code,
- resetPasswordResponse.response,
- );
- cy.get('button[type=submit]').click();
- verifyInRegularEmailSentPage();
- },
- );
- break;
- }
- });
- });
+ context('When I submit the form on /set-password/expired', () => {
+ beforeEach(() => {
+ cy.visit(`/set-password/expired`);
+ cy.get('input[name="email"]').type('example@example.com');
+ });
+ switch (status) {
+ case false:
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ cy.mockNext(userNotFoundError.code, userNotFoundError.response);
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'ACTIVE':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ // forgotPassword()
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
+ });
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ specify(
+ "Then I should be shown the 'Check your email inbox' page for social user",
+ () => {
+ setupMocksForSocialUserPasswordReset();
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'PROVISIONED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(tokenResponse.code, tokenResponse.response);
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'STAGED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(tokenResponse.code, tokenResponse.response);
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ case 'RECOVERY':
+ case 'PASSWORD_EXPIRED':
+ specify(
+ "Then I should be shown the 'Check your email inbox' page",
+ () => {
+ // Set the correct user status on the response
+ const response = { ...userResponse.response, status };
+ cy.mockNext(userResponse.code, response);
+ cy.mockNext(
+ resetPasswordResponse.code,
+ resetPasswordResponse.response,
+ );
+ cy.get('button[type=submit]').click();
+ verifyInRegularEmailSentPage();
+ },
+ );
+ break;
+ }
+ });
+ });
});
diff --git a/cypress/integration/mocked-okta/signInController.2.cy.ts b/cypress/integration/mocked-okta/signInController.2.cy.ts
index 4212dcf780..4ddd9ca0d7 100644
--- a/cypress/integration/mocked-okta/signInController.2.cy.ts
+++ b/cypress/integration/mocked-okta/signInController.2.cy.ts
@@ -3,83 +3,83 @@ import validUserResponse from '../../fixtures/okta-responses/success/valid-user.
import validUserGroupsResponse from '../../fixtures/okta-responses/success/valid-user-groups.json';
beforeEach(() => {
- cy.mockPurge();
+ cy.mockPurge();
});
context('When I submit the form on /signin', () => {
- beforeEach(() => {
- cy.visit(`/signin`);
- cy.get('input[name="email"]').type('example@example.com');
- cy.get('input[name="password"]').type('password');
- });
- //This is expected for non existent, non active users or when the email and password are incorrect
- specify(
- 'if okta authentication fails then I should be shown an "Email or password incorrect" error. ',
- () => {
- cy.mockNext(
- authenticationFailedError.code,
- authenticationFailedError.response,
- );
- cy.get('button[type=submit]').click();
- cy.contains("Email and password don't match");
- },
- );
- specify('if okta authentication succeeds then I should be signed in.', () => {
- cy.mockNext(validUserResponse.code, validUserResponse.response);
- cy.mockNext(validUserGroupsResponse.code, validUserGroupsResponse.response);
+ beforeEach(() => {
+ cy.visit(`/signin`);
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.get('input[name="password"]').type('password');
+ });
+ //This is expected for non existent, non active users or when the email and password are incorrect
+ specify(
+ 'if okta authentication fails then I should be shown an "Email or password incorrect" error. ',
+ () => {
+ cy.mockNext(
+ authenticationFailedError.code,
+ authenticationFailedError.response,
+ );
+ cy.get('button[type=submit]').click();
+ cy.contains("Email and password don't match");
+ },
+ );
+ specify('if okta authentication succeeds then I should be signed in.', () => {
+ cy.mockNext(validUserResponse.code, validUserResponse.response);
+ cy.mockNext(validUserGroupsResponse.code, validUserGroupsResponse.response);
- cy.get('button[type=submit]').click();
- // we can't actually check the authorization code flow
- // so simply intercept the request and verify that it contains
- // the mocked response
- cy.intercept(
- `http://localhost:9000/oauth2/${Cypress.env(
- 'OKTA_CUSTOM_OAUTH_SERVER',
- )}/v1/authorize*`,
- 'OAuth',
- );
- cy.contains('OAuth');
- });
+ cy.get('button[type=submit]').click();
+ // we can't actually check the authorization code flow
+ // so simply intercept the request and verify that it contains
+ // the mocked response
+ cy.intercept(
+ `http://localhost:9000/oauth2/${Cypress.env(
+ 'OKTA_CUSTOM_OAUTH_SERVER',
+ )}/v1/authorize*`,
+ 'OAuth',
+ );
+ cy.contains('OAuth');
+ });
});
context('When I submit the form on /reauthenticate', () => {
- beforeEach(() => {
- cy.visit(`/reauthenticate`);
- cy.get('input[name="email"]').type('example@example.com');
- cy.get('input[name="password"]').type('password');
- });
- //This is expected for non existent, non active users or when the email and password are incorrect
- specify(
- 'If okta authentication fails then I should be shown an "Email or password incorrect" error.',
- () => {
- cy.mockNext(
- authenticationFailedError.code,
- authenticationFailedError.response,
- );
- cy.get('button[type=submit]').click();
- cy.contains("Email and password don't match");
- },
- );
+ beforeEach(() => {
+ cy.visit(`/reauthenticate`);
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.get('input[name="password"]').type('password');
+ });
+ //This is expected for non existent, non active users or when the email and password are incorrect
+ specify(
+ 'If okta authentication fails then I should be shown an "Email or password incorrect" error.',
+ () => {
+ cy.mockNext(
+ authenticationFailedError.code,
+ authenticationFailedError.response,
+ );
+ cy.get('button[type=submit]').click();
+ cy.contains("Email and password don't match");
+ },
+ );
- specify(
- 'If okta authentication succeeeds then I should be signed in.',
- () => {
- cy.mockNext(validUserResponse.code, validUserResponse.response);
- cy.mockNext(
- validUserGroupsResponse.code,
- validUserGroupsResponse.response,
- );
+ specify(
+ 'If okta authentication succeeeds then I should be signed in.',
+ () => {
+ cy.mockNext(validUserResponse.code, validUserResponse.response);
+ cy.mockNext(
+ validUserGroupsResponse.code,
+ validUserGroupsResponse.response,
+ );
- cy.get('button[type=submit]').click();
- // we can't actually check the authorization code flow
- // so simply intercept the request and verify that it contains
- // the mocked response
- cy.intercept(
- `http://localhost:9000/oauth2/${Cypress.env(
- 'OKTA_CUSTOM_OAUTH_SERVER',
- )}/v1/authorize*`,
- 'OAuth',
- );
- cy.contains('OAuth');
- },
- );
+ cy.get('button[type=submit]').click();
+ // we can't actually check the authorization code flow
+ // so simply intercept the request and verify that it contains
+ // the mocked response
+ cy.intercept(
+ `http://localhost:9000/oauth2/${Cypress.env(
+ 'OKTA_CUSTOM_OAUTH_SERVER',
+ )}/v1/authorize*`,
+ 'OAuth',
+ );
+ cy.contains('OAuth');
+ },
+ );
});
diff --git a/cypress/integration/mocked/change_email.5.cy.ts b/cypress/integration/mocked/change_email.5.cy.ts
index 093f0686b3..1d9c87ae42 100644
--- a/cypress/integration/mocked/change_email.5.cy.ts
+++ b/cypress/integration/mocked/change_email.5.cy.ts
@@ -1,52 +1,52 @@
import { injectAndCheckAxe } from '../../support/cypress-axe';
describe('Change email', () => {
- beforeEach(() => {
- cy.mockPurge();
- });
+ beforeEach(() => {
+ cy.mockPurge();
+ });
- context('a11y checks', () => {
- it('Has no detectable a11y violations on change email complete page', () => {
- cy.visit('/change-email/complete');
- injectAndCheckAxe();
- });
+ context('a11y checks', () => {
+ it('Has no detectable a11y violations on change email complete page', () => {
+ cy.visit('/change-email/complete');
+ injectAndCheckAxe();
+ });
- it('Has no detectable a11y violations on change email error page', () => {
- cy.mockNext(500, {
- status: 'error',
- errors: [
- {
- message: 'Invalid token',
- },
- ],
- });
- cy.visit('/change-email/token');
- injectAndCheckAxe();
- });
- });
+ it('Has no detectable a11y violations on change email error page', () => {
+ cy.mockNext(500, {
+ status: 'error',
+ errors: [
+ {
+ message: 'Invalid token',
+ },
+ ],
+ });
+ cy.visit('/change-email/token');
+ injectAndCheckAxe();
+ });
+ });
- context('change email flow', () => {
- it('should be able to change email', () => {
- cy.mockNext(200, {
- status: 'ok',
- });
- cy.visit('/change-email/token');
- cy.contains('Success! Your email address has been updated.');
- });
+ context('change email flow', () => {
+ it('should be able to change email', () => {
+ cy.mockNext(200, {
+ status: 'ok',
+ });
+ cy.visit('/change-email/token');
+ cy.contains('Success! Your email address has been updated.');
+ });
- it('should be able to handle a change email error', () => {
- cy.mockNext(500, {
- status: 'error',
- errors: [
- {
- message: 'Invalid token',
- },
- ],
- });
- cy.visit('/change-email/token');
- cy.contains(
- 'The email change link you followed has expired or was invalid.',
- );
- });
- });
+ it('should be able to handle a change email error', () => {
+ cy.mockNext(500, {
+ status: 'error',
+ errors: [
+ {
+ message: 'Invalid token',
+ },
+ ],
+ });
+ cy.visit('/change-email/token');
+ cy.contains(
+ 'The email change link you followed has expired or was invalid.',
+ );
+ });
+ });
});
diff --git a/cypress/integration/mocked/change_password.3.cy.ts b/cypress/integration/mocked/change_password.3.cy.ts
index 7085ffc572..2253f5d577 100644
--- a/cypress/integration/mocked/change_password.3.cy.ts
+++ b/cypress/integration/mocked/change_password.3.cy.ts
@@ -1,352 +1,352 @@
import { injectAndCheckAxe } from '../../support/cypress-axe';
describe('Password change flow', () => {
- const fakeValidationResponse = (
- timeUntilExpiry: number | undefined = undefined,
- ) => ({
- user: {
- primaryEmailAddress: 'name@example.com',
- },
- timeUntilExpiry,
- });
+ const fakeValidationResponse = (
+ timeUntilExpiry: number | undefined = undefined,
+ ) => ({
+ user: {
+ primaryEmailAddress: 'name@example.com',
+ },
+ timeUntilExpiry,
+ });
- const fakeSuccessResponse = {
- cookies: {
- values: [
- {
- key: 'GU_U',
- value: 'FAKE_VALUE_0',
- },
- {
- key: 'SC_GU_LA',
- value: 'FAKE_VALUE_1',
- sessionCookie: true,
- },
- {
- key: 'SC_GU_U',
- value: 'FAKE_VALUE_2',
- },
- ],
- expiresAt: 1,
- },
- };
+ const fakeSuccessResponse = {
+ cookies: {
+ values: [
+ {
+ key: 'GU_U',
+ value: 'FAKE_VALUE_0',
+ },
+ {
+ key: 'SC_GU_LA',
+ value: 'FAKE_VALUE_1',
+ sessionCookie: true,
+ },
+ {
+ key: 'SC_GU_U',
+ value: 'FAKE_VALUE_2',
+ },
+ ],
+ expiresAt: 1,
+ },
+ };
- beforeEach(() => {
- cy.mockPurge();
- });
+ beforeEach(() => {
+ cy.mockPurge();
+ });
- context('A11y checks', () => {
- it('Has no detectable a11y violations on resend password page', () => {
- cy.mockNext(500, {
- status: 'error',
- errors: [
- {
- message: 'Invalid token',
- },
- ],
- });
- cy.visit(`/reset-password/fake_token?useIdapi=true`);
- injectAndCheckAxe();
- });
+ context('A11y checks', () => {
+ it('Has no detectable a11y violations on resend password page', () => {
+ cy.mockNext(500, {
+ status: 'error',
+ errors: [
+ {
+ message: 'Invalid token',
+ },
+ ],
+ });
+ cy.visit(`/reset-password/fake_token?useIdapi=true`);
+ injectAndCheckAxe();
+ });
- it('Has no detectable a11y violations on change password page', () => {
- cy.mockNext(200);
- cy.mockNext(200, fakeSuccessResponse);
- cy.visit(`/reset-password/fake_token?useIdapi=true`);
- injectAndCheckAxe();
- });
+ it('Has no detectable a11y violations on change password page', () => {
+ cy.mockNext(200);
+ cy.mockNext(200, fakeSuccessResponse);
+ cy.visit(`/reset-password/fake_token?useIdapi=true`);
+ injectAndCheckAxe();
+ });
- it('Has no detectable a11y violations on change password page with error', () => {
- cy.mockNext(200);
- cy.visit(`/reset-password/fake_token?useIdapi=true`);
- cy.get('input[name="password"]').type('short');
- cy.get('button[type="submit"]').click();
- injectAndCheckAxe();
- });
+ it('Has no detectable a11y violations on change password page with error', () => {
+ cy.mockNext(200);
+ cy.visit(`/reset-password/fake_token?useIdapi=true`);
+ cy.get('input[name="password"]').type('short');
+ cy.get('button[type="submit"]').click();
+ injectAndCheckAxe();
+ });
- it('Has no detectable a11y violations on change password complete page', () => {
- cy.mockNext(200);
- cy.mockNext(200, fakeSuccessResponse);
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.visit(`/reset-password/fake_token?useIdapi=true`);
- cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
- cy.wait('@breachCheck');
- cy.get('button[type="submit"]').click();
- injectAndCheckAxe();
- });
- });
+ it('Has no detectable a11y violations on change password complete page', () => {
+ cy.mockNext(200);
+ cy.mockNext(200, fakeSuccessResponse);
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.visit(`/reset-password/fake_token?useIdapi=true`);
+ cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
+ cy.wait('@breachCheck');
+ cy.get('button[type="submit"]').click();
+ injectAndCheckAxe();
+ });
+ });
- context('show / hide password eye button', () => {
- it('clicking on the password eye shows the password and clicking it again hides it', () => {
- cy.mockNext(200);
- cy.visit(`/reset-password/fake_token?useIdapi=true`);
- cy.get('input[name="password"]').should('have.attr', 'type', 'password');
- cy.get('input[name="password"]').type('some_password');
- cy.get('[data-cy=password-input-eye-button]').click();
- cy.get('input[name="password"]').should('have.attr', 'type', 'text');
- cy.get('[data-cy=password-input-eye-button]').click();
- cy.get('input[name="password"]').should('have.attr', 'type', 'password');
- });
- });
+ context('show / hide password eye button', () => {
+ it('clicking on the password eye shows the password and clicking it again hides it', () => {
+ cy.mockNext(200);
+ cy.visit(`/reset-password/fake_token?useIdapi=true`);
+ cy.get('input[name="password"]').should('have.attr', 'type', 'password');
+ cy.get('input[name="password"]').type('some_password');
+ cy.get('[data-cy=password-input-eye-button]').click();
+ cy.get('input[name="password"]').should('have.attr', 'type', 'text');
+ cy.get('[data-cy=password-input-eye-button]').click();
+ cy.get('input[name="password"]').should('have.attr', 'type', 'password');
+ });
+ });
- context('An expired/invalid token is used', () => {
- it('shows a resend password page', () => {
- cy.mockNext(500, {
- status: 'error',
- errors: [
- {
- message: 'Invalid token',
- },
- ],
- });
- cy.visit(`/reset-password/fake_token?useIdapi=true`);
- cy.contains('Link expired');
- });
+ context('An expired/invalid token is used', () => {
+ it('shows a resend password page', () => {
+ cy.mockNext(500, {
+ status: 'error',
+ errors: [
+ {
+ message: 'Invalid token',
+ },
+ ],
+ });
+ cy.visit(`/reset-password/fake_token?useIdapi=true`);
+ cy.contains('Link expired');
+ });
- it('shows the session time out page if the token expires while on the set password page', () => {
- cy.mockNext(200, fakeValidationResponse(1000));
- cy.visit(`/reset-password/fake_token?useIdapi=true`);
- cy.contains('Session timed out');
- });
- });
+ it('shows the session time out page if the token expires while on the set password page', () => {
+ cy.mockNext(200, fakeValidationResponse(1000));
+ cy.visit(`/reset-password/fake_token?useIdapi=true`);
+ cy.contains('Session timed out');
+ });
+ });
- context('Password exists in breach dataset', () => {
- it('displays a breached error', () => {
- cy.mockNext(200);
- cy.mockNext(200, fakeSuccessResponse);
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.visit(`/reset-password/fake_token?useIdapi=true`);
- cy.get('input[name="password"]').type('password');
- cy.wait('@breachCheck');
- cy.contains('use a password that is hard to guess');
- cy.get('button[type="submit"]').click().should('not.be.disabled');
- cy.contains('Please use a password that is hard to guess.');
- });
- });
+ context('Password exists in breach dataset', () => {
+ it('displays a breached error', () => {
+ cy.mockNext(200);
+ cy.mockNext(200, fakeSuccessResponse);
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.visit(`/reset-password/fake_token?useIdapi=true`);
+ cy.get('input[name="password"]').type('password');
+ cy.wait('@breachCheck');
+ cy.contains('use a password that is hard to guess');
+ cy.get('button[type="submit"]').click().should('not.be.disabled');
+ cy.contains('Please use a password that is hard to guess.');
+ });
+ });
- context('CSRF token error on submission', () => {
- it('should fail on submission due to CSRF token failure if CSRF token cookie is not sent', () => {
- cy.mockNext(200);
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.visit(`/reset-password/fake_token?useIdapi=true`);
- cy.clearCookie('_csrf');
- cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
- cy.wait('@breachCheck');
- cy.get('button[type="submit"]').click();
- cy.contains('Please try again.');
- });
- });
+ context('CSRF token error on submission', () => {
+ it('should fail on submission due to CSRF token failure if CSRF token cookie is not sent', () => {
+ cy.mockNext(200);
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.visit(`/reset-password/fake_token?useIdapi=true`);
+ cy.clearCookie('_csrf');
+ cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
+ cy.wait('@breachCheck');
+ cy.get('button[type="submit"]').click();
+ cy.contains('Please try again.');
+ });
+ });
- context('Password field is left blank', () => {
- it('uses the standard HTML5 empty field validation', () => {
- cy.mockNext(200);
- cy.visit(`/reset-password/fake_token?useIdapi=true`);
- cy.get('button[type="submit"]').click();
- cy.get('input[name="password"]:invalid').should('have.length', 1);
- });
- });
+ context('Password field is left blank', () => {
+ it('uses the standard HTML5 empty field validation', () => {
+ cy.mockNext(200);
+ cy.visit(`/reset-password/fake_token?useIdapi=true`);
+ cy.get('button[type="submit"]').click();
+ cy.get('input[name="password"]:invalid').should('have.length', 1);
+ });
+ });
- context('Email shown on page', () => {
- it('shows the users email address on the page', () => {
- cy.mockNext(200, fakeValidationResponse());
- cy.visit(`/reset-password/fake_token?useIdapi=true`);
- cy.contains(fakeValidationResponse().user.primaryEmailAddress);
- });
- });
+ context('Email shown on page', () => {
+ it('shows the users email address on the page', () => {
+ cy.mockNext(200, fakeValidationResponse());
+ cy.visit(`/reset-password/fake_token?useIdapi=true`);
+ cy.contains(fakeValidationResponse().user.primaryEmailAddress);
+ });
+ });
- context('Valid password entered', () => {
- it('shows password change success screen, with a default redirect button.', () => {
- cy.mockNext(200);
- cy.mockNext(200, fakeSuccessResponse);
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.visit(`/reset-password/fake_token?useIdapi=true`);
+ context('Valid password entered', () => {
+ it('shows password change success screen, with a default redirect button.', () => {
+ cy.mockNext(200);
+ cy.mockNext(200, fakeSuccessResponse);
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.visit(`/reset-password/fake_token?useIdapi=true`);
- cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
- cy.wait('@breachCheck');
- // Submit the button
- cy.contains('Valid password');
- cy.get('button[type="submit"]').click();
- cy.contains('Password updated');
- cy.contains('Continue to the Guardian').should(
- 'have.attr',
- 'href',
- `${Cypress.env('DEFAULT_RETURN_URI')}/`,
- );
+ cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
+ cy.wait('@breachCheck');
+ // Submit the button
+ cy.contains('Valid password');
+ cy.get('button[type="submit"]').click();
+ cy.contains('Password updated');
+ cy.contains('Continue to the Guardian').should(
+ 'have.attr',
+ 'href',
+ `${Cypress.env('DEFAULT_RETURN_URI')}/`,
+ );
- // Not currently possible to test login cookie,
- // Cookie is not set to domain we can access, even in cypress.
- // e.g.
- // cy.getCookie('GU_U')
- // .should('have.property', 'value', 'FAKE_VALUE_0');
- });
+ // Not currently possible to test login cookie,
+ // Cookie is not set to domain we can access, even in cypress.
+ // e.g.
+ // cy.getCookie('GU_U')
+ // .should('have.property', 'value', 'FAKE_VALUE_0');
+ });
- it('shows password change success screen, with default redirect button, and users email', () => {
- cy.mockNext(200, fakeValidationResponse());
- cy.mockNext(200, fakeSuccessResponse);
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.visit(`/reset-password/fake_token?useIdapi=true`);
- cy.contains(fakeValidationResponse().user.primaryEmailAddress);
+ it('shows password change success screen, with default redirect button, and users email', () => {
+ cy.mockNext(200, fakeValidationResponse());
+ cy.mockNext(200, fakeSuccessResponse);
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.visit(`/reset-password/fake_token?useIdapi=true`);
+ cy.contains(fakeValidationResponse().user.primaryEmailAddress);
- cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
- cy.wait('@breachCheck');
- cy.get('button[type="submit"]').click();
- cy.contains('Password updated');
- cy.contains('Continue to the Guardian').should(
- 'have.attr',
- 'href',
- `${Cypress.env('DEFAULT_RETURN_URI')}/`,
- );
- cy.contains(fakeValidationResponse().user.primaryEmailAddress);
- });
- });
+ cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
+ cy.wait('@breachCheck');
+ cy.get('button[type="submit"]').click();
+ cy.contains('Password updated');
+ cy.contains('Continue to the Guardian').should(
+ 'have.attr',
+ 'href',
+ `${Cypress.env('DEFAULT_RETURN_URI')}/`,
+ );
+ cy.contains(fakeValidationResponse().user.primaryEmailAddress);
+ });
+ });
- context(
- 'Valid password entered and a return url with a Guardian domain is specified.',
- () => {
- it('shows password change success screen, with a redirect button linking to the return url.', () => {
- cy.mockNext(200);
- cy.mockNext(200, fakeSuccessResponse);
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.visit(
- `/reset-password/fake_token?returnUrl=https://news.theguardian.com&useIdapi=true`,
- );
- cy.get('input[name="password"]').type(
- 'thisisalongandunbreachedpassword',
- );
- cy.wait('@breachCheck');
- cy.get('button[type="submit"]').click();
- cy.contains('Password updated');
- cy.contains('Continue to the Guardian').should(
- 'have.attr',
- 'href',
- 'https://news.theguardian.com/',
- );
- });
- },
- );
+ context(
+ 'Valid password entered and a return url with a Guardian domain is specified.',
+ () => {
+ it('shows password change success screen, with a redirect button linking to the return url.', () => {
+ cy.mockNext(200);
+ cy.mockNext(200, fakeSuccessResponse);
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.visit(
+ `/reset-password/fake_token?returnUrl=https://news.theguardian.com&useIdapi=true`,
+ );
+ cy.get('input[name="password"]').type(
+ 'thisisalongandunbreachedpassword',
+ );
+ cy.wait('@breachCheck');
+ cy.get('button[type="submit"]').click();
+ cy.contains('Password updated');
+ cy.contains('Continue to the Guardian').should(
+ 'have.attr',
+ 'href',
+ 'https://news.theguardian.com/',
+ );
+ });
+ },
+ );
- context(
- 'Valid password entered and an return url from a non-Guardian domain is specified.',
- () => {
- it('shows password change success screen, with a default redirect button.', () => {
- cy.mockNext(200);
- cy.mockNext(200, fakeSuccessResponse);
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.visit(
- `/reset-password/fake_token?returnUrl=https://news.badsite.com&useIdapi=true`,
- );
- cy.get('input[name="password"]').type(
- 'thisisalongandunbreachedpassword',
- );
- cy.wait('@breachCheck');
- cy.get('button[type="submit"]').click();
- cy.contains('Password updated');
- cy.contains('Continue to the Guardian').should(
- 'have.attr',
- 'href',
- `${Cypress.env('DEFAULT_RETURN_URI')}/`,
- );
- });
- },
- );
+ context(
+ 'Valid password entered and an return url from a non-Guardian domain is specified.',
+ () => {
+ it('shows password change success screen, with a default redirect button.', () => {
+ cy.mockNext(200);
+ cy.mockNext(200, fakeSuccessResponse);
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.visit(
+ `/reset-password/fake_token?returnUrl=https://news.badsite.com&useIdapi=true`,
+ );
+ cy.get('input[name="password"]').type(
+ 'thisisalongandunbreachedpassword',
+ );
+ cy.wait('@breachCheck');
+ cy.get('button[type="submit"]').click();
+ cy.contains('Password updated');
+ cy.contains('Continue to the Guardian').should(
+ 'have.attr',
+ 'href',
+ `${Cypress.env('DEFAULT_RETURN_URI')}/`,
+ );
+ });
+ },
+ );
- context('password too short', () => {
- it('shows an error showing the password length must be within certain limits', () => {
- cy.mockNext(200);
- cy.visit(`/reset-password/fake_token?useIdapi=true`);
- cy.mockNext(200);
- cy.get('input[name="password"]').type('p');
- cy.get('button[type="submit"]').focus();
- // Error is shown before clicking submit
- cy.contains('At least 8');
- cy.get('button[type="submit"]').click();
- // Error still exists after clicking submit
- cy.contains(
- 'Please make sure your password is at least 8 characters long.',
- );
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.get('input[name="password"]').type('iamaveryuniqueandlongstring');
- cy.wait('@breachCheck');
- cy.contains('Valid password');
- });
- });
+ context('password too short', () => {
+ it('shows an error showing the password length must be within certain limits', () => {
+ cy.mockNext(200);
+ cy.visit(`/reset-password/fake_token?useIdapi=true`);
+ cy.mockNext(200);
+ cy.get('input[name="password"]').type('p');
+ cy.get('button[type="submit"]').focus();
+ // Error is shown before clicking submit
+ cy.contains('At least 8');
+ cy.get('button[type="submit"]').click();
+ // Error still exists after clicking submit
+ cy.contains(
+ 'Please make sure your password is at least 8 characters long.',
+ );
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.get('input[name="password"]').type('iamaveryuniqueandlongstring');
+ cy.wait('@breachCheck');
+ cy.contains('Valid password');
+ });
+ });
- context('password too long', () => {
- it('shows an error showing the password length must be within certain limits', () => {
- const excessivelyLongPassword = Array.from(Array(73), () => 'a').join('');
- cy.mockNext(200);
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.visit(`/reset-password/fake_token?useIdapi=true`);
- cy.mockNext(200);
- cy.get('input[name="password"]').type(excessivelyLongPassword);
- cy.get('button[type="submit"]').focus();
- // Error is shown before clicking submit
- cy.contains('Maximum of 72');
- cy.wait('@breachCheck');
- cy.get('button[type="submit"]').click();
- // Error still exists after clicking submit
- cy.contains(
- 'Please make sure your password is not longer than 72 characters.',
- );
- cy.get('input[name="password"]').type(
- '{selectall}{backspace}iamaveryuniqueandlongstring',
- );
- cy.wait('@breachCheck');
- cy.contains('Valid password');
- });
- });
+ context('password too long', () => {
+ it('shows an error showing the password length must be within certain limits', () => {
+ const excessivelyLongPassword = Array.from(Array(73), () => 'a').join('');
+ cy.mockNext(200);
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.visit(`/reset-password/fake_token?useIdapi=true`);
+ cy.mockNext(200);
+ cy.get('input[name="password"]').type(excessivelyLongPassword);
+ cy.get('button[type="submit"]').focus();
+ // Error is shown before clicking submit
+ cy.contains('Maximum of 72');
+ cy.wait('@breachCheck');
+ cy.get('button[type="submit"]').click();
+ // Error still exists after clicking submit
+ cy.contains(
+ 'Please make sure your password is not longer than 72 characters.',
+ );
+ cy.get('input[name="password"]').type(
+ '{selectall}{backspace}iamaveryuniqueandlongstring',
+ );
+ cy.wait('@breachCheck');
+ cy.contains('Valid password');
+ });
+ });
- context('General IDAPI failure on token read', () => {
- it('displays the password resend page', () => {
- cy.mockNext(500);
- cy.visit(`/reset-password/fake_token?useIdapi=true`);
- cy.contains('Link expired');
- });
- });
+ context('General IDAPI failure on token read', () => {
+ it('displays the password resend page', () => {
+ cy.mockNext(500);
+ cy.visit(`/reset-password/fake_token?useIdapi=true`);
+ cy.contains('Link expired');
+ });
+ });
- context('General IDAPI failure on password change', () => {
- it('displays a generic error message', () => {
- cy.mockNext(200);
- cy.mockNext(500);
- cy.mockNext(200);
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.visit(`/reset-password/fake_token?useIdapi=true`);
- cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
- cy.wait('@breachCheck');
- cy.get('button[type="submit"]').click();
- cy.contains(
- 'There was a problem changing your password, please try again.',
- );
- });
- });
+ context('General IDAPI failure on password change', () => {
+ it('displays a generic error message', () => {
+ cy.mockNext(200);
+ cy.mockNext(500);
+ cy.mockNext(200);
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.visit(`/reset-password/fake_token?useIdapi=true`);
+ cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
+ cy.wait('@breachCheck');
+ cy.get('button[type="submit"]').click();
+ cy.contains(
+ 'There was a problem changing your password, please try again.',
+ );
+ });
+ });
});
diff --git a/cypress/integration/mocked/consent_token.3.cy.ts b/cypress/integration/mocked/consent_token.3.cy.ts
index cffc8f9616..77953d05d7 100644
--- a/cypress/integration/mocked/consent_token.3.cy.ts
+++ b/cypress/integration/mocked/consent_token.3.cy.ts
@@ -1,44 +1,44 @@
import { injectAndCheckAxe } from '../../support/cypress-axe';
describe('Consent token accept flow', () => {
- beforeEach(() => {
- cy.mockPurge();
- });
+ beforeEach(() => {
+ cy.mockPurge();
+ });
- context('a11y checks', () => {
- it('Has no detectable a11y violations on consent token expired page', () => {
- cy.visit('/consent-token/abc123/accept');
- injectAndCheckAxe();
- });
+ context('a11y checks', () => {
+ it('Has no detectable a11y violations on consent token expired page', () => {
+ cy.visit('/consent-token/abc123/accept');
+ injectAndCheckAxe();
+ });
- it('Has no detectable a11y violations on consent token email sent page', () => {
- cy.visit('/consent-token/abc123/accept');
- cy.get('button[type=submit]').click();
- injectAndCheckAxe();
- });
- });
+ it('Has no detectable a11y violations on consent token email sent page', () => {
+ cy.visit('/consent-token/abc123/accept');
+ cy.get('button[type=submit]').click();
+ injectAndCheckAxe();
+ });
+ });
- context('consent token flow', () => {
- // This test needs to be run mocked because we need to mock the
- // expired token response from IDAPI.
- it('shows the email sent page when supplied a valid, expired token', () => {
- const expiredToken = 'expired-consent-token';
- cy.mockNext(403, {
- error: {
- status: 'error',
- errors: [
- {
- message: 'Token expired',
- description: 'The link is no longer valid',
- },
- ],
- },
- });
- cy.visit(`/consent-token/${expiredToken}/accept`);
- cy.contains('This link has expired.');
- cy.get('button[type=submit]').click();
- cy.url().should('include', '/consent-token/email-sent');
- cy.contains('Check your email inbox');
- });
- });
+ context('consent token flow', () => {
+ // This test needs to be run mocked because we need to mock the
+ // expired token response from IDAPI.
+ it('shows the email sent page when supplied a valid, expired token', () => {
+ const expiredToken = 'expired-consent-token';
+ cy.mockNext(403, {
+ error: {
+ status: 'error',
+ errors: [
+ {
+ message: 'Token expired',
+ description: 'The link is no longer valid',
+ },
+ ],
+ },
+ });
+ cy.visit(`/consent-token/${expiredToken}/accept`);
+ cy.contains('This link has expired.');
+ cy.get('button[type=submit]').click();
+ cy.url().should('include', '/consent-token/email-sent');
+ cy.contains('Check your email inbox');
+ });
+ });
});
diff --git a/cypress/integration/mocked/email_input.2.cy.ts b/cypress/integration/mocked/email_input.2.cy.ts
index 8b2bc7f37b..837c94b71c 100644
--- a/cypress/integration/mocked/email_input.2.cy.ts
+++ b/cypress/integration/mocked/email_input.2.cy.ts
@@ -1,37 +1,37 @@
describe('Email input component', () => {
- beforeEach(() => {
- cy.mockPurge();
- });
+ beforeEach(() => {
+ cy.mockPurge();
+ });
- it('should show an error message when nothing submitted ', () => {
- cy.visit('/register?useIdapi=true');
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.contains('Please enter your email.');
- });
+ it('should show an error message when nothing submitted ', () => {
+ cy.visit('/register?useIdapi=true');
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.contains('Please enter your email.');
+ });
- it('should show an error message when an invalid email is submitted', () => {
- cy.visit('/register?useIdapi=true');
- cy.get('input[name="email"]').type('invalid.email.com');
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.contains('Please enter a valid email format.');
- });
+ it('should show an error message when an invalid email is submitted', () => {
+ cy.visit('/register?useIdapi=true');
+ cy.get('input[name="email"]').type('invalid.email.com');
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.contains('Please enter a valid email format.');
+ });
- it('does not show an error message when a valid email is submitted', () => {
- cy.visit('/register?useIdapi=true');
- cy.get('input[name="email"]').type('test@email.com');
- cy.get('[data-cy=main-form-submit-button]').focus();
- cy.contains('Please enter a valid email format.').should('not.exist');
- cy.contains('Please enter your email.').should('not.exist');
- });
+ it('does not show an error message when a valid email is submitted', () => {
+ cy.visit('/register?useIdapi=true');
+ cy.get('input[name="email"]').type('test@email.com');
+ cy.get('[data-cy=main-form-submit-button]').focus();
+ cy.contains('Please enter a valid email format.').should('not.exist');
+ cy.contains('Please enter your email.').should('not.exist');
+ });
- it('should correct error once a valid email is submitted', () => {
- cy.visit('/register?useIdapi=true');
- cy.get('input[name="email"]').type('invalid.email.com');
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.contains('Please enter a valid email format.');
- cy.get('input[name="email"]').type('test@email.com');
- cy.get('[data-cy=main-form-submit-button]').focus();
- cy.contains('Please enter a valid email format.').should('not.exist');
- cy.contains('Please enter your email.').should('not.exist');
- });
+ it('should correct error once a valid email is submitted', () => {
+ cy.visit('/register?useIdapi=true');
+ cy.get('input[name="email"]').type('invalid.email.com');
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.contains('Please enter a valid email format.');
+ cy.get('input[name="email"]').type('test@email.com');
+ cy.get('[data-cy=main-form-submit-button]').focus();
+ cy.contains('Please enter a valid email format.').should('not.exist');
+ cy.contains('Please enter your email.').should('not.exist');
+ });
});
diff --git a/cypress/integration/mocked/email_templates.5.cy.ts b/cypress/integration/mocked/email_templates.5.cy.ts
index ee804d72d7..2ba87b9d36 100644
--- a/cypress/integration/mocked/email_templates.5.cy.ts
+++ b/cypress/integration/mocked/email_templates.5.cy.ts
@@ -1,22 +1,22 @@
describe('Email template generation', () => {
- it('renders an accidental email', () => {
- cy.request('/email/accidental-email').then((response) => {
- expect(response.body.plain).to.contain(
- 'This email has been triggered accidentally.',
- );
- expect(response.body.html).to.contain(
- 'This email has been triggered accidentally.',
- );
- });
- });
- it('returns a 404 error for an invalid template name', () => {
- cy.request({
- url: '/email/invalid-template',
- failOnStatusCode: false,
- }).then((response) => {
- expect(response.status).to.equal(404);
- expect(response.body.plain).to.not.exist;
- expect(response.body.html).to.not.exist;
- });
- });
+ it('renders an accidental email', () => {
+ cy.request('/email/accidental-email').then((response) => {
+ expect(response.body.plain).to.contain(
+ 'This email has been triggered accidentally.',
+ );
+ expect(response.body.html).to.contain(
+ 'This email has been triggered accidentally.',
+ );
+ });
+ });
+ it('returns a 404 error for an invalid template name', () => {
+ cy.request({
+ url: '/email/invalid-template',
+ failOnStatusCode: false,
+ }).then((response) => {
+ expect(response.status).to.equal(404);
+ expect(response.body.plain).to.not.exist;
+ expect(response.body.html).to.not.exist;
+ });
+ });
});
diff --git a/cypress/integration/mocked/okta_change_password.2.cy.ts b/cypress/integration/mocked/okta_change_password.2.cy.ts
index ab6eaff341..d3d52af1ea 100644
--- a/cypress/integration/mocked/okta_change_password.2.cy.ts
+++ b/cypress/integration/mocked/okta_change_password.2.cy.ts
@@ -20,299 +20,299 @@
import { randomPassword } from '../../support/commands/testUser';
describe('Change password in Okta', () => {
- context('reset password page', () => {
- const email = 'mrtest@theguardian.com';
-
- beforeEach(() => {
- cy.mockPurge();
- });
-
- const mockValidateRecoveryTokenSuccess = (
- date: Date = new Date(Date.now() + 1800000 /* 30min */),
- ) => {
- cy.mockNext(200, {
- stateToken: 'stateToken',
- expiresAt: date.toISOString(),
- status: 'SUCCESS',
- _embedded: {
- user: {
- id: '12345',
- passwordChanged: new Date().toISOString(),
- profile: {
- login: email,
- firstName: null,
- lastName: null,
- },
- },
- },
- });
- };
-
- const mockValidateRecoveryTokenFailure = () => {
- cy.mockNext(403, {
- errorCode: 'E0000105',
- errorSummary:
- 'You have accessed an account recovery link that has expired or been previously used.',
- errorLink: 'E0000105',
- errorId: 'errorId',
- errorCauses: [],
- });
- };
-
- const mockPasswordResetSuccess = (
- date: Date = new Date(Date.now() + 1800000 /* 30min */),
- ) => {
- cy.mockNext(200, {
- expiresAt: date.toISOString(),
- status: 'SUCCESS',
- sessionToken: 'aValidSessionToken',
- _embedded: {
- user: {
- id: '12345',
- passwordChanged: new Date().toISOString(),
- profile: {
- login: email,
- firstName: null,
- lastName: null,
- locale: 'en_US',
- timeZone: 'America/Los_Angeles',
- },
- },
- },
- });
- };
-
- const mockUpdateUserSuccess = () => {
- cy.mockNext(200, {
- id: '12345',
- status: 'SUCCESS',
- profile: {
- login: email,
- email,
- isGuardianUser: true,
- },
- credentials: {},
- });
- };
-
- const mockPasswordResetFailure = (cause: string) => {
- cy.mockNext(403, {
- errorCode: 'E0000080',
- errorSummary:
- 'The password does not meet the complexity requirements of the current password policy.',
- errorLink: 'E0000080',
- errorId: 'errorId',
- errorCauses: [
- {
- errorSummary: cause,
- },
- ],
- });
- };
-
- const mockPasswordResetInvalidStateTokenFailure = () => {
- cy.mockNext(403, {
- errorCode: 'E0000011',
- errorSummary: 'Invalid token provided',
- errorLink: 'E0000011',
- errorId: 'errorId',
- errorCauses: [],
- });
- };
-
- const interceptBreachPasswordCheck = () => {
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- };
-
- it('shows the link expired page if the state token and the recovery token are invalid', () => {
- interceptBreachPasswordCheck();
-
- mockValidateRecoveryTokenSuccess(); // needs to succeed once for the page to display
- mockPasswordResetInvalidStateTokenFailure();
- mockValidateRecoveryTokenFailure();
-
- cy.visit('/reset-password/token');
-
- cy.get('input[name="password"]').type(randomPassword());
- cy.get('button[type="submit"]').click();
-
- cy.contains('Link expired');
- });
-
- it('shows the password reset page with errors if the state token is invalid but the recovery token is still valid', () => {
- interceptBreachPasswordCheck();
-
- mockValidateRecoveryTokenSuccess();
- mockValidateRecoveryTokenSuccess();
- mockPasswordResetInvalidStateTokenFailure();
- mockValidateRecoveryTokenSuccess();
-
- cy.visit('/reset-password/token');
-
- cy.get('input[name="password"]').type(randomPassword());
- cy.get('button[type="submit"]').click();
-
- cy.contains('Reset password');
- cy.contains(`Please enter your new password for ${email}`);
- cy.contains(
- 'There was a problem changing your password, please try again.',
- );
- });
-
- it('shows the link expired page if recovery token is invalid after submitting password', () => {
- interceptBreachPasswordCheck();
-
- mockValidateRecoveryTokenSuccess();
- mockValidateRecoveryTokenFailure();
-
- cy.visit('/reset-password/token');
- cy.clearCookie('GU_GATEWAY_STATE');
-
- cy.get('input[name="password"]').type(randomPassword());
- cy.get('button[type="submit"]').click();
-
- cy.contains('Link expired');
- });
-
- it('shows the link expired page if an unexpected error occurred when validating the recovery token', () => {
- cy.mockNext(500);
- cy.visit('/reset-password/token');
- cy.contains('Link expired');
- });
-
- it('shows the reset password page with errors if an unexpected error occurred when resetting the password', () => {
- interceptBreachPasswordCheck();
-
- mockValidateRecoveryTokenSuccess();
- cy.mockNext(503);
- mockValidateRecoveryTokenSuccess();
-
- cy.visit('/reset-password/token');
-
- cy.get('input[name="password"]').type(randomPassword());
- cy.get('button[type="submit"]').click();
-
- cy.contains('Reset password');
- cy.contains(`Please enter your new password for ${email}`);
- cy.contains(
- 'There was a problem changing your password, please try again.',
- );
- });
-
- it('shows the reset password page with field error if the password is too short', () => {
- interceptBreachPasswordCheck();
-
- mockValidateRecoveryTokenSuccess();
- mockPasswordResetFailure(
- 'Password requirements were not met. Password requirements: at least 6 characters.',
- );
- mockValidateRecoveryTokenSuccess();
-
- cy.visit('/reset-password/token');
-
- // even though this test is for a short password, we enter a valid password here to bypass
- // client-side password complexity checks in order to test the server-side response
- cy.get('input[name="password"]').type(randomPassword());
- cy.get('button[type="submit"]').click();
-
- cy.contains('Reset password');
- cy.contains(
- 'Please make sure your password is at least 8 characters long.',
- );
- });
-
- it('shows the reset password page with field error if the password is too long', () => {
- interceptBreachPasswordCheck();
-
- mockValidateRecoveryTokenSuccess();
- mockPasswordResetFailure(
- 'Password requirements were not met. Password requirements: maximum 72 characters.',
- );
- mockValidateRecoveryTokenSuccess();
-
- cy.visit('/reset-password/token');
-
- cy.get('input[name="password"]').type(randomPassword());
- cy.get('button[type="submit"]').click();
-
- cy.contains('Reset password');
- cy.contains(
- 'Please make sure your password is not longer than 72 characters.',
- );
- });
-
- it('shows the reset password page with field error if the password is the same as the current password', () => {
- interceptBreachPasswordCheck();
-
- mockValidateRecoveryTokenSuccess();
- mockPasswordResetFailure('Password cannot be your current password');
- mockValidateRecoveryTokenSuccess();
-
- cy.visit('/reset-password/token');
-
- cy.get('input[name="password"]').type(randomPassword());
- cy.get('button[type="submit"]').click();
-
- cy.contains('Reset password');
- cy.contains(
- 'Please use a password that is different to your current password.',
- );
- });
-
- it('shows the reset password page with field error if the password is a common or breached password', () => {
- interceptBreachPasswordCheck();
-
- mockValidateRecoveryTokenSuccess();
- mockPasswordResetFailure(
- 'This password was found in a list of commonly used passwords. Please try another password.',
- );
- mockValidateRecoveryTokenSuccess();
-
- cy.visit('/reset-password/token');
-
- cy.get('input[name="password"]').type(randomPassword());
- cy.get('button[type="submit"]').click();
-
- cy.contains('Reset password');
- cy.contains('Please use a password that is hard to guess.');
- });
-
- it('shows the password updated page on successful update', () => {
- interceptBreachPasswordCheck();
-
- mockValidateRecoveryTokenSuccess();
- mockValidateRecoveryTokenSuccess();
- mockPasswordResetSuccess();
- mockUpdateUserSuccess();
-
- cy.intercept(
- `http://localhost:9000/oauth2/${Cypress.env(
- 'OKTA_CUSTOM_OAUTH_SERVER',
- )}/v1/authorize*`,
- (req) => {
- req.redirect(
- `https://${Cypress.env('BASE_URI')}/reset-password/complete`,
- );
- },
- ).as('authRedirect');
-
- cy.visit('/reset-password/token');
-
- cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
- cy.wait('@breachCheck');
- cy.get('button[type="submit"]').click();
- cy.wait('@authRedirect').then(() => {
- cy.contains('Password updated');
- cy.contains(email);
- cy.contains('Continue to the Guardian').should(
- 'have.attr',
- 'href',
- `${Cypress.env('DEFAULT_RETURN_URI')}`,
- );
- });
- });
- });
+ context('reset password page', () => {
+ const email = 'mrtest@theguardian.com';
+
+ beforeEach(() => {
+ cy.mockPurge();
+ });
+
+ const mockValidateRecoveryTokenSuccess = (
+ date: Date = new Date(Date.now() + 1800000 /* 30min */),
+ ) => {
+ cy.mockNext(200, {
+ stateToken: 'stateToken',
+ expiresAt: date.toISOString(),
+ status: 'SUCCESS',
+ _embedded: {
+ user: {
+ id: '12345',
+ passwordChanged: new Date().toISOString(),
+ profile: {
+ login: email,
+ firstName: null,
+ lastName: null,
+ },
+ },
+ },
+ });
+ };
+
+ const mockValidateRecoveryTokenFailure = () => {
+ cy.mockNext(403, {
+ errorCode: 'E0000105',
+ errorSummary:
+ 'You have accessed an account recovery link that has expired or been previously used.',
+ errorLink: 'E0000105',
+ errorId: 'errorId',
+ errorCauses: [],
+ });
+ };
+
+ const mockPasswordResetSuccess = (
+ date: Date = new Date(Date.now() + 1800000 /* 30min */),
+ ) => {
+ cy.mockNext(200, {
+ expiresAt: date.toISOString(),
+ status: 'SUCCESS',
+ sessionToken: 'aValidSessionToken',
+ _embedded: {
+ user: {
+ id: '12345',
+ passwordChanged: new Date().toISOString(),
+ profile: {
+ login: email,
+ firstName: null,
+ lastName: null,
+ locale: 'en_US',
+ timeZone: 'America/Los_Angeles',
+ },
+ },
+ },
+ });
+ };
+
+ const mockUpdateUserSuccess = () => {
+ cy.mockNext(200, {
+ id: '12345',
+ status: 'SUCCESS',
+ profile: {
+ login: email,
+ email,
+ isGuardianUser: true,
+ },
+ credentials: {},
+ });
+ };
+
+ const mockPasswordResetFailure = (cause: string) => {
+ cy.mockNext(403, {
+ errorCode: 'E0000080',
+ errorSummary:
+ 'The password does not meet the complexity requirements of the current password policy.',
+ errorLink: 'E0000080',
+ errorId: 'errorId',
+ errorCauses: [
+ {
+ errorSummary: cause,
+ },
+ ],
+ });
+ };
+
+ const mockPasswordResetInvalidStateTokenFailure = () => {
+ cy.mockNext(403, {
+ errorCode: 'E0000011',
+ errorSummary: 'Invalid token provided',
+ errorLink: 'E0000011',
+ errorId: 'errorId',
+ errorCauses: [],
+ });
+ };
+
+ const interceptBreachPasswordCheck = () => {
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ };
+
+ it('shows the link expired page if the state token and the recovery token are invalid', () => {
+ interceptBreachPasswordCheck();
+
+ mockValidateRecoveryTokenSuccess(); // needs to succeed once for the page to display
+ mockPasswordResetInvalidStateTokenFailure();
+ mockValidateRecoveryTokenFailure();
+
+ cy.visit('/reset-password/token');
+
+ cy.get('input[name="password"]').type(randomPassword());
+ cy.get('button[type="submit"]').click();
+
+ cy.contains('Link expired');
+ });
+
+ it('shows the password reset page with errors if the state token is invalid but the recovery token is still valid', () => {
+ interceptBreachPasswordCheck();
+
+ mockValidateRecoveryTokenSuccess();
+ mockValidateRecoveryTokenSuccess();
+ mockPasswordResetInvalidStateTokenFailure();
+ mockValidateRecoveryTokenSuccess();
+
+ cy.visit('/reset-password/token');
+
+ cy.get('input[name="password"]').type(randomPassword());
+ cy.get('button[type="submit"]').click();
+
+ cy.contains('Reset password');
+ cy.contains(`Please enter your new password for ${email}`);
+ cy.contains(
+ 'There was a problem changing your password, please try again.',
+ );
+ });
+
+ it('shows the link expired page if recovery token is invalid after submitting password', () => {
+ interceptBreachPasswordCheck();
+
+ mockValidateRecoveryTokenSuccess();
+ mockValidateRecoveryTokenFailure();
+
+ cy.visit('/reset-password/token');
+ cy.clearCookie('GU_GATEWAY_STATE');
+
+ cy.get('input[name="password"]').type(randomPassword());
+ cy.get('button[type="submit"]').click();
+
+ cy.contains('Link expired');
+ });
+
+ it('shows the link expired page if an unexpected error occurred when validating the recovery token', () => {
+ cy.mockNext(500);
+ cy.visit('/reset-password/token');
+ cy.contains('Link expired');
+ });
+
+ it('shows the reset password page with errors if an unexpected error occurred when resetting the password', () => {
+ interceptBreachPasswordCheck();
+
+ mockValidateRecoveryTokenSuccess();
+ cy.mockNext(503);
+ mockValidateRecoveryTokenSuccess();
+
+ cy.visit('/reset-password/token');
+
+ cy.get('input[name="password"]').type(randomPassword());
+ cy.get('button[type="submit"]').click();
+
+ cy.contains('Reset password');
+ cy.contains(`Please enter your new password for ${email}`);
+ cy.contains(
+ 'There was a problem changing your password, please try again.',
+ );
+ });
+
+ it('shows the reset password page with field error if the password is too short', () => {
+ interceptBreachPasswordCheck();
+
+ mockValidateRecoveryTokenSuccess();
+ mockPasswordResetFailure(
+ 'Password requirements were not met. Password requirements: at least 6 characters.',
+ );
+ mockValidateRecoveryTokenSuccess();
+
+ cy.visit('/reset-password/token');
+
+ // even though this test is for a short password, we enter a valid password here to bypass
+ // client-side password complexity checks in order to test the server-side response
+ cy.get('input[name="password"]').type(randomPassword());
+ cy.get('button[type="submit"]').click();
+
+ cy.contains('Reset password');
+ cy.contains(
+ 'Please make sure your password is at least 8 characters long.',
+ );
+ });
+
+ it('shows the reset password page with field error if the password is too long', () => {
+ interceptBreachPasswordCheck();
+
+ mockValidateRecoveryTokenSuccess();
+ mockPasswordResetFailure(
+ 'Password requirements were not met. Password requirements: maximum 72 characters.',
+ );
+ mockValidateRecoveryTokenSuccess();
+
+ cy.visit('/reset-password/token');
+
+ cy.get('input[name="password"]').type(randomPassword());
+ cy.get('button[type="submit"]').click();
+
+ cy.contains('Reset password');
+ cy.contains(
+ 'Please make sure your password is not longer than 72 characters.',
+ );
+ });
+
+ it('shows the reset password page with field error if the password is the same as the current password', () => {
+ interceptBreachPasswordCheck();
+
+ mockValidateRecoveryTokenSuccess();
+ mockPasswordResetFailure('Password cannot be your current password');
+ mockValidateRecoveryTokenSuccess();
+
+ cy.visit('/reset-password/token');
+
+ cy.get('input[name="password"]').type(randomPassword());
+ cy.get('button[type="submit"]').click();
+
+ cy.contains('Reset password');
+ cy.contains(
+ 'Please use a password that is different to your current password.',
+ );
+ });
+
+ it('shows the reset password page with field error if the password is a common or breached password', () => {
+ interceptBreachPasswordCheck();
+
+ mockValidateRecoveryTokenSuccess();
+ mockPasswordResetFailure(
+ 'This password was found in a list of commonly used passwords. Please try another password.',
+ );
+ mockValidateRecoveryTokenSuccess();
+
+ cy.visit('/reset-password/token');
+
+ cy.get('input[name="password"]').type(randomPassword());
+ cy.get('button[type="submit"]').click();
+
+ cy.contains('Reset password');
+ cy.contains('Please use a password that is hard to guess.');
+ });
+
+ it('shows the password updated page on successful update', () => {
+ interceptBreachPasswordCheck();
+
+ mockValidateRecoveryTokenSuccess();
+ mockValidateRecoveryTokenSuccess();
+ mockPasswordResetSuccess();
+ mockUpdateUserSuccess();
+
+ cy.intercept(
+ `http://localhost:9000/oauth2/${Cypress.env(
+ 'OKTA_CUSTOM_OAUTH_SERVER',
+ )}/v1/authorize*`,
+ (req) => {
+ req.redirect(
+ `https://${Cypress.env('BASE_URI')}/reset-password/complete`,
+ );
+ },
+ ).as('authRedirect');
+
+ cy.visit('/reset-password/token');
+
+ cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
+ cy.wait('@breachCheck');
+ cy.get('button[type="submit"]').click();
+ cy.wait('@authRedirect').then(() => {
+ cy.contains('Password updated');
+ cy.contains(email);
+ cy.contains('Continue to the Guardian').should(
+ 'have.attr',
+ 'href',
+ `${Cypress.env('DEFAULT_RETURN_URI')}`,
+ );
+ });
+ });
+ });
});
diff --git a/cypress/integration/mocked/okta_register.3.cy.ts b/cypress/integration/mocked/okta_register.3.cy.ts
index 83a28139d9..c25361755b 100644
--- a/cypress/integration/mocked/okta_register.3.cy.ts
+++ b/cypress/integration/mocked/okta_register.3.cy.ts
@@ -1,160 +1,160 @@
describe('Okta Register flow', () => {
- const setSidCookie = () => {
- cy.setCookie('sid', `the_sid_cookie`, {
- domain: Cypress.env('BASE_URI'),
- });
- };
-
- context('Signed in user posts to /register', () => {
- beforeEach(() => {
- cy.mockPurge();
- cy.clearCookies();
- // we visit the healthcheck page to make sure the cookies are cleared from the browser
- cy.visit('/healthcheck');
- cy.disableCMP();
- });
-
- it('should redirect to homepage if the sid Okta session cookie is valid', () => {
- cy.mockPattern(
- 200,
- {
- id: 'test',
- login: 'user@example.com',
- userId: 'userId',
- status: 'ACTIVE',
- expiresAt: '2016-01-03T09:13:17.000Z',
- lastPasswordVerification: '2016-01-03T07:02:00.000Z',
- lastFactorVerification: null,
- amr: ['pwd'],
- idp: {
- id: '01a2bcdef3GHIJKLMNOP',
- type: 'OKTA',
- },
- mfaActive: true,
- },
- '/api/v1/sessions/the_sid_cookie',
- );
-
- cy.mockPattern(204, {}, '/api/v1/users/userId/sessions');
-
- cy.intercept('POST', '/register**').as('registerPost');
-
- cy.visit('/register');
-
- setSidCookie();
-
- cy.get('input[name="email"]').type('example@example.com');
- cy.mockNext(200, {
- userType: 'new',
- });
- cy.mockNext(200, {
- status: 'success',
- errors: [],
- });
- cy.get('[data-cy=main-form-submit-button]').click();
-
- cy.contains('Sign in to the Guardian');
- cy.contains('You are signed in with');
- cy.contains('user@example.com');
- cy.contains('Continue')
- .should('have.attr', 'href')
- .and('include', '/signin/refresh')
- .and(
- 'include',
- 'returnUrl=https%3A%2F%2Fm.code.dev-theguardian.com%2F',
- );
- cy.contains('a', 'Sign in')
- .should('have.attr', 'href')
- .and(
- 'include',
- '/signout?returnUrl=https%253A%252F%252Fprofile.thegulocal.com%252Fsignin',
- );
- cy.contains('Sign in with a different email');
- });
-
- it('should redirect to /reauthenticate if the sid Okta session cookie is set, but invalid', () => {
- cy.mockPattern(404, '/api/v1/sessions/the_sid_cookie');
-
- cy.mockPattern(204, {}, '/api/v1/users/userId/sessions');
-
- setSidCookie();
-
- // visit healthcheck to set the cookie
- cy.visit('/healthcheck');
-
- cy.visit('/register');
-
- cy.location('pathname').should('eq', '/reauthenticate');
-
- cy.getCookie('sid').should('not.exist');
- });
- });
-
- context('Signed in user visits /register', () => {
- beforeEach(() => {
- cy.mockPurge();
- });
- it('should redirect to homepage if the sid Okta session cookie is valid', () => {
- cy.mockPattern(
- 200,
- {
- id: 'test',
- login: 'user@example.com',
- userId: 'userId',
- status: 'ACTIVE',
- expiresAt: '2016-01-03T09:13:17.000Z',
- lastPasswordVerification: '2016-01-03T07:02:00.000Z',
- lastFactorVerification: null,
- amr: ['pwd'],
- idp: {
- id: '01a2bcdef3GHIJKLMNOP',
- type: 'OKTA',
- },
- mfaActive: true,
- },
- '/api/v1/sessions/the_sid_cookie',
- );
-
- cy.mockPattern(204, {}, '/api/v1/users/userId/sessions');
-
- setSidCookie();
-
- // disable the cmp on the redirect
- cy.disableCMP();
-
- cy.visit('/register');
-
- cy.contains('Sign in to the Guardian');
- cy.contains('You are signed in with');
- cy.contains('user@example.com');
- cy.contains('Continue')
- .should('have.attr', 'href')
- .and('include', '/signin/refresh')
- .and('include', 'returnUrl=https%3A%2F%2Fm.code.dev-theguardian.com');
- cy.contains('a', 'Sign in')
- .should('have.attr', 'href')
- .and(
- 'include',
- '/signout?returnUrl=https%253A%252F%252Fprofile.thegulocal.com%252Fsignin',
- );
- cy.contains('Sign in with a different email');
- });
-
- it('should redirect to /reauthenticate if the sid Okta session cookie is set but invalid', () => {
- cy.mockPattern(404, '/api/v1/sessions/the_sid_cookie');
-
- cy.mockPattern(204, {}, '/api/v1/users/userId/sessions');
-
- setSidCookie();
-
- // visit healthcheck to set the cookie
- cy.visit('/healthcheck');
-
- cy.visit('/register');
-
- cy.location('pathname').should('eq', '/reauthenticate');
-
- cy.getCookie('sid').should('not.exist');
- });
- });
+ const setSidCookie = () => {
+ cy.setCookie('sid', `the_sid_cookie`, {
+ domain: Cypress.env('BASE_URI'),
+ });
+ };
+
+ context('Signed in user posts to /register', () => {
+ beforeEach(() => {
+ cy.mockPurge();
+ cy.clearCookies();
+ // we visit the healthcheck page to make sure the cookies are cleared from the browser
+ cy.visit('/healthcheck');
+ cy.disableCMP();
+ });
+
+ it('should redirect to homepage if the sid Okta session cookie is valid', () => {
+ cy.mockPattern(
+ 200,
+ {
+ id: 'test',
+ login: 'user@example.com',
+ userId: 'userId',
+ status: 'ACTIVE',
+ expiresAt: '2016-01-03T09:13:17.000Z',
+ lastPasswordVerification: '2016-01-03T07:02:00.000Z',
+ lastFactorVerification: null,
+ amr: ['pwd'],
+ idp: {
+ id: '01a2bcdef3GHIJKLMNOP',
+ type: 'OKTA',
+ },
+ mfaActive: true,
+ },
+ '/api/v1/sessions/the_sid_cookie',
+ );
+
+ cy.mockPattern(204, {}, '/api/v1/users/userId/sessions');
+
+ cy.intercept('POST', '/register**').as('registerPost');
+
+ cy.visit('/register');
+
+ setSidCookie();
+
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.mockNext(200, {
+ userType: 'new',
+ });
+ cy.mockNext(200, {
+ status: 'success',
+ errors: [],
+ });
+ cy.get('[data-cy=main-form-submit-button]').click();
+
+ cy.contains('Sign in to the Guardian');
+ cy.contains('You are signed in with');
+ cy.contains('user@example.com');
+ cy.contains('Continue')
+ .should('have.attr', 'href')
+ .and('include', '/signin/refresh')
+ .and(
+ 'include',
+ 'returnUrl=https%3A%2F%2Fm.code.dev-theguardian.com%2F',
+ );
+ cy.contains('a', 'Sign in')
+ .should('have.attr', 'href')
+ .and(
+ 'include',
+ '/signout?returnUrl=https%253A%252F%252Fprofile.thegulocal.com%252Fsignin',
+ );
+ cy.contains('Sign in with a different email');
+ });
+
+ it('should redirect to /reauthenticate if the sid Okta session cookie is set, but invalid', () => {
+ cy.mockPattern(404, '/api/v1/sessions/the_sid_cookie');
+
+ cy.mockPattern(204, {}, '/api/v1/users/userId/sessions');
+
+ setSidCookie();
+
+ // visit healthcheck to set the cookie
+ cy.visit('/healthcheck');
+
+ cy.visit('/register');
+
+ cy.location('pathname').should('eq', '/reauthenticate');
+
+ cy.getCookie('sid').should('not.exist');
+ });
+ });
+
+ context('Signed in user visits /register', () => {
+ beforeEach(() => {
+ cy.mockPurge();
+ });
+ it('should redirect to homepage if the sid Okta session cookie is valid', () => {
+ cy.mockPattern(
+ 200,
+ {
+ id: 'test',
+ login: 'user@example.com',
+ userId: 'userId',
+ status: 'ACTIVE',
+ expiresAt: '2016-01-03T09:13:17.000Z',
+ lastPasswordVerification: '2016-01-03T07:02:00.000Z',
+ lastFactorVerification: null,
+ amr: ['pwd'],
+ idp: {
+ id: '01a2bcdef3GHIJKLMNOP',
+ type: 'OKTA',
+ },
+ mfaActive: true,
+ },
+ '/api/v1/sessions/the_sid_cookie',
+ );
+
+ cy.mockPattern(204, {}, '/api/v1/users/userId/sessions');
+
+ setSidCookie();
+
+ // disable the cmp on the redirect
+ cy.disableCMP();
+
+ cy.visit('/register');
+
+ cy.contains('Sign in to the Guardian');
+ cy.contains('You are signed in with');
+ cy.contains('user@example.com');
+ cy.contains('Continue')
+ .should('have.attr', 'href')
+ .and('include', '/signin/refresh')
+ .and('include', 'returnUrl=https%3A%2F%2Fm.code.dev-theguardian.com');
+ cy.contains('a', 'Sign in')
+ .should('have.attr', 'href')
+ .and(
+ 'include',
+ '/signout?returnUrl=https%253A%252F%252Fprofile.thegulocal.com%252Fsignin',
+ );
+ cy.contains('Sign in with a different email');
+ });
+
+ it('should redirect to /reauthenticate if the sid Okta session cookie is set but invalid', () => {
+ cy.mockPattern(404, '/api/v1/sessions/the_sid_cookie');
+
+ cy.mockPattern(204, {}, '/api/v1/users/userId/sessions');
+
+ setSidCookie();
+
+ // visit healthcheck to set the cookie
+ cy.visit('/healthcheck');
+
+ cy.visit('/register');
+
+ cy.location('pathname').should('eq', '/reauthenticate');
+
+ cy.getCookie('sid').should('not.exist');
+ });
+ });
});
diff --git a/cypress/integration/mocked/okta_send_reset_password.4.cy.ts b/cypress/integration/mocked/okta_send_reset_password.4.cy.ts
index 62a7139164..2b581c84d0 100644
--- a/cypress/integration/mocked/okta_send_reset_password.4.cy.ts
+++ b/cypress/integration/mocked/okta_send_reset_password.4.cy.ts
@@ -1,282 +1,282 @@
import { UserResponse } from '@/server/models/okta/User';
describe('Send password reset email in Okta', () => {
- const email = 'mrtest@theguardian.com';
+ const email = 'mrtest@theguardian.com';
- const mockUserActiveWithPassword: UserResponse = {
- id: 'test',
- status: 'ACTIVE',
- profile: {
- login: 'mrtest@theguardian.com',
- email: 'mrtest@theguardian.com',
- },
- credentials: {
- password: {},
- provider: {
- type: 'OKTA',
- name: 'OKTA',
- },
- },
- };
+ const mockUserActiveWithPassword: UserResponse = {
+ id: 'test',
+ status: 'ACTIVE',
+ profile: {
+ login: 'mrtest@theguardian.com',
+ email: 'mrtest@theguardian.com',
+ },
+ credentials: {
+ password: {},
+ provider: {
+ type: 'OKTA',
+ name: 'OKTA',
+ },
+ },
+ };
- const mockUserActiveWithoutPassword: UserResponse = {
- id: 'test',
- status: 'ACTIVE',
- profile: {
- login: 'mrtest@theguardian.com',
- email: 'mrtest@theguardian.com',
- },
- credentials: {
- provider: {
- type: 'OKTA',
- name: 'OKTA',
- },
- },
- };
+ const mockUserActiveWithoutPassword: UserResponse = {
+ id: 'test',
+ status: 'ACTIVE',
+ profile: {
+ login: 'mrtest@theguardian.com',
+ email: 'mrtest@theguardian.com',
+ },
+ credentials: {
+ provider: {
+ type: 'OKTA',
+ name: 'OKTA',
+ },
+ },
+ };
- const mockUserStaged: UserResponse = {
- id: 'test',
- status: 'STAGED',
- profile: {
- login: 'mrtest@theguardian.com',
- email: 'mrtest@theguardian.com',
- },
- credentials: {
- provider: {
- type: 'OKTA',
- name: 'OKTA',
- },
- },
- };
+ const mockUserStaged: UserResponse = {
+ id: 'test',
+ status: 'STAGED',
+ profile: {
+ login: 'mrtest@theguardian.com',
+ email: 'mrtest@theguardian.com',
+ },
+ credentials: {
+ provider: {
+ type: 'OKTA',
+ name: 'OKTA',
+ },
+ },
+ };
- const mockUserProvisioned: UserResponse = {
- id: 'test',
- status: 'PROVISIONED',
- profile: {
- login: 'mrtest@theguardian.com',
- email: 'mrtest@theguardian.com',
- },
- credentials: {
- provider: {
- type: 'OKTA',
- name: 'OKTA',
- },
- },
- };
+ const mockUserProvisioned: UserResponse = {
+ id: 'test',
+ status: 'PROVISIONED',
+ profile: {
+ login: 'mrtest@theguardian.com',
+ email: 'mrtest@theguardian.com',
+ },
+ credentials: {
+ provider: {
+ type: 'OKTA',
+ name: 'OKTA',
+ },
+ },
+ };
- const mockUserRecovery: UserResponse = {
- id: 'test',
- status: 'RECOVERY',
- profile: {
- login: 'mrtest@theguardian.com',
- email: 'mrtest@theguardian.com',
- },
- credentials: {
- provider: {
- type: 'OKTA',
- name: 'OKTA',
- },
- },
- };
+ const mockUserRecovery: UserResponse = {
+ id: 'test',
+ status: 'RECOVERY',
+ profile: {
+ login: 'mrtest@theguardian.com',
+ email: 'mrtest@theguardian.com',
+ },
+ credentials: {
+ provider: {
+ type: 'OKTA',
+ name: 'OKTA',
+ },
+ },
+ };
- const mockUserPasswordExpired: UserResponse = {
- id: 'test',
- status: 'PASSWORD_EXPIRED',
- profile: {
- login: 'mrtest@theguardian.com',
- email: 'mrtest@theguardian.com',
- },
- credentials: {
- provider: {
- type: 'OKTA',
- name: 'OKTA',
- },
- },
- };
+ const mockUserPasswordExpired: UserResponse = {
+ id: 'test',
+ status: 'PASSWORD_EXPIRED',
+ profile: {
+ login: 'mrtest@theguardian.com',
+ email: 'mrtest@theguardian.com',
+ },
+ credentials: {
+ provider: {
+ type: 'OKTA',
+ name: 'OKTA',
+ },
+ },
+ };
- beforeEach(() => {
- cy.mockPurge();
- });
+ beforeEach(() => {
+ cy.mockPurge();
+ });
- context('send reset password email for ACTIVE user', () => {
- it('shows email sent page when successful', () => {
- cy.visit('/reset-password');
- cy.get('input[name="email"]').type(email);
- cy.mockNext(200, mockUserActiveWithPassword);
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
- });
- cy.get('button[type="submit"]').click();
- cy.contains('Check your email inbox');
- cy.contains('email within 2 minutes');
- cy.contains('Resend email');
- });
- });
+ context('send reset password email for ACTIVE user', () => {
+ it('shows email sent page when successful', () => {
+ cy.visit('/reset-password');
+ cy.get('input[name="email"]').type(email);
+ cy.mockNext(200, mockUserActiveWithPassword);
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
+ });
+ cy.get('button[type="submit"]').click();
+ cy.contains('Check your email inbox');
+ cy.contains('email within 2 minutes');
+ cy.contains('Resend email');
+ });
+ });
- context('send reset password email for ACTIVE user without password', () => {
- it('shows email sent page when successful', () => {
- cy.visit('/reset-password');
- cy.get('input[name="email"]').type(email);
- cy.mockNext(200, mockUserActiveWithoutPassword);
- cy.mockNext(403, {
- errorCode: 'E0000006',
- errorSummary:
- 'You do not have permission to perform the requested action',
- errorLink: 'E0000006',
- errorId: 'errorId',
- errorCauses: [],
- });
- cy.mockNext(200, {
- resetPasswordUrl: `https://${Cypress.env(
- 'BASE_URI',
- )}/reset_password/token_token_token_to`,
- });
- cy.mockNext(200, {
- stateToken: 'stateToken',
- expiresAt: new Date(Date.now() + 1800000 /* 30min */),
- status: 'SUCCESS',
- _embedded: {
- user: {
- id: '12345',
- passwordChanged: new Date().toISOString(),
- profile: {
- login: email,
- firstName: null,
- lastName: null,
- },
- },
- },
- });
- cy.mockNext(200, {
- expiresAt: new Date(Date.now() + 1800000 /* 30min */),
- status: 'SUCCESS',
- sessionToken: 'aValidSessionToken',
- _embedded: {
- user: {
- id: '12345',
- passwordChanged: new Date().toISOString(),
- profile: {
- login: email,
- firstName: null,
- lastName: null,
- locale: 'en_US',
- timeZone: 'America/Los_Angeles',
- },
- },
- },
- });
- cy.mockNext(200, mockUserActiveWithoutPassword);
- cy.mockNext(200, {
- resetPasswordUrl:
- 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
- });
- cy.get('button[type="submit"]').click();
- cy.contains('Check your email inbox');
- cy.contains('email within 2 minutes');
- cy.contains('Resend email');
- });
- });
+ context('send reset password email for ACTIVE user without password', () => {
+ it('shows email sent page when successful', () => {
+ cy.visit('/reset-password');
+ cy.get('input[name="email"]').type(email);
+ cy.mockNext(200, mockUserActiveWithoutPassword);
+ cy.mockNext(403, {
+ errorCode: 'E0000006',
+ errorSummary:
+ 'You do not have permission to perform the requested action',
+ errorLink: 'E0000006',
+ errorId: 'errorId',
+ errorCauses: [],
+ });
+ cy.mockNext(200, {
+ resetPasswordUrl: `https://${Cypress.env(
+ 'BASE_URI',
+ )}/reset_password/token_token_token_to`,
+ });
+ cy.mockNext(200, {
+ stateToken: 'stateToken',
+ expiresAt: new Date(Date.now() + 1800000 /* 30min */),
+ status: 'SUCCESS',
+ _embedded: {
+ user: {
+ id: '12345',
+ passwordChanged: new Date().toISOString(),
+ profile: {
+ login: email,
+ firstName: null,
+ lastName: null,
+ },
+ },
+ },
+ });
+ cy.mockNext(200, {
+ expiresAt: new Date(Date.now() + 1800000 /* 30min */),
+ status: 'SUCCESS',
+ sessionToken: 'aValidSessionToken',
+ _embedded: {
+ user: {
+ id: '12345',
+ passwordChanged: new Date().toISOString(),
+ profile: {
+ login: email,
+ firstName: null,
+ lastName: null,
+ locale: 'en_US',
+ timeZone: 'America/Los_Angeles',
+ },
+ },
+ },
+ });
+ cy.mockNext(200, mockUserActiveWithoutPassword);
+ cy.mockNext(200, {
+ resetPasswordUrl:
+ 'https://example.com/signin/reset-password/XE6wE17zmphl3KqAPFxO',
+ });
+ cy.get('button[type="submit"]').click();
+ cy.contains('Check your email inbox');
+ cy.contains('email within 2 minutes');
+ cy.contains('Resend email');
+ });
+ });
- context('send create password email for STAGED user', () => {
- it('shows email sent page when successful', () => {
- cy.visit('/reset-password');
- cy.get('input[name="email"]').type(email);
- cy.mockNext(200, mockUserStaged);
- cy.mockNext(200, {
- activationUrl: `token_token_token_to`,
- activationToken: `token_token_token_to`,
- });
- cy.get('button[type="submit"]').click();
- cy.contains('Check your email inbox');
- cy.contains('email within 2 minutes');
- cy.contains('Resend email');
- });
- });
+ context('send create password email for STAGED user', () => {
+ it('shows email sent page when successful', () => {
+ cy.visit('/reset-password');
+ cy.get('input[name="email"]').type(email);
+ cy.mockNext(200, mockUserStaged);
+ cy.mockNext(200, {
+ activationUrl: `token_token_token_to`,
+ activationToken: `token_token_token_to`,
+ });
+ cy.get('button[type="submit"]').click();
+ cy.contains('Check your email inbox');
+ cy.contains('email within 2 minutes');
+ cy.contains('Resend email');
+ });
+ });
- context('send create password email for PROVISIONED user', () => {
- it('shows email sent page when successful', () => {
- cy.visit('/reset-password');
- cy.get('input[name="email"]').type(email);
- cy.mockNext(200, mockUserProvisioned);
- cy.mockNext(200, {
- activationUrl: `token_token_token_to`,
- activationToken: `token_token_token_to`,
- });
- cy.get('button[type="submit"]').click();
- cy.contains('Check your email inbox');
- cy.contains('email within 2 minutes');
- cy.contains('Resend email');
- });
- });
+ context('send create password email for PROVISIONED user', () => {
+ it('shows email sent page when successful', () => {
+ cy.visit('/reset-password');
+ cy.get('input[name="email"]').type(email);
+ cy.mockNext(200, mockUserProvisioned);
+ cy.mockNext(200, {
+ activationUrl: `token_token_token_to`,
+ activationToken: `token_token_token_to`,
+ });
+ cy.get('button[type="submit"]').click();
+ cy.contains('Check your email inbox');
+ cy.contains('email within 2 minutes');
+ cy.contains('Resend email');
+ });
+ });
- context('send reset password email for RECOVERY user', () => {
- it('shows email sent page when successful', () => {
- cy.visit('/reset-password');
- cy.get('input[name="email"]').type(email);
- cy.mockNext(200, mockUserRecovery);
- cy.mockNext(200, {
- resetPasswordUrl: `https://${Cypress.env(
- 'BASE_URI',
- )}/reset_password/token_token_token_to`,
- });
- cy.get('button[type="submit"]').click();
- cy.contains('Check your email inbox');
- cy.contains('email within 2 minutes');
- cy.contains('Resend email');
- });
- });
+ context('send reset password email for RECOVERY user', () => {
+ it('shows email sent page when successful', () => {
+ cy.visit('/reset-password');
+ cy.get('input[name="email"]').type(email);
+ cy.mockNext(200, mockUserRecovery);
+ cy.mockNext(200, {
+ resetPasswordUrl: `https://${Cypress.env(
+ 'BASE_URI',
+ )}/reset_password/token_token_token_to`,
+ });
+ cy.get('button[type="submit"]').click();
+ cy.contains('Check your email inbox');
+ cy.contains('email within 2 minutes');
+ cy.contains('Resend email');
+ });
+ });
- context('send reset password email for PASSWORD_EXPIRED user', () => {
- it('shows email sent page when successful', () => {
- cy.visit('/reset-password');
- cy.get('input[name="email"]').type(email);
- cy.mockNext(200, mockUserPasswordExpired);
- cy.mockNext(200, {
- resetPasswordUrl: `https://${Cypress.env(
- 'BASE_URI',
- )}/reset_password/token_token_token_to`,
- });
- cy.get('button[type="submit"]').click();
- cy.contains('Check your email inbox');
- cy.contains('email within 2 minutes');
- cy.contains('Resend email');
- });
- });
+ context('send reset password email for PASSWORD_EXPIRED user', () => {
+ it('shows email sent page when successful', () => {
+ cy.visit('/reset-password');
+ cy.get('input[name="email"]').type(email);
+ cy.mockNext(200, mockUserPasswordExpired);
+ cy.mockNext(200, {
+ resetPasswordUrl: `https://${Cypress.env(
+ 'BASE_URI',
+ )}/reset_password/token_token_token_to`,
+ });
+ cy.get('button[type="submit"]').click();
+ cy.contains('Check your email inbox');
+ cy.contains('email within 2 minutes');
+ cy.contains('Resend email');
+ });
+ });
- context('user not found', () => {
- it('shows email sent page even when user not found', () => {
- cy.visit('/reset-password');
- cy.get('input[name="email"]').type(email);
- cy.mockNext(404, {
- errorCode: 'E0000007',
- errorSummary: 'User not found',
- errorLink: 'E0000007',
- errorId: 'errorId',
- errorCauses: [],
- });
- cy.get('button[type="submit"]').click();
- cy.contains('Check your email inbox');
- cy.contains('email within 2 minutes');
- cy.contains('Resend email');
- });
- });
+ context('user not found', () => {
+ it('shows email sent page even when user not found', () => {
+ cy.visit('/reset-password');
+ cy.get('input[name="email"]').type(email);
+ cy.mockNext(404, {
+ errorCode: 'E0000007',
+ errorSummary: 'User not found',
+ errorLink: 'E0000007',
+ errorId: 'errorId',
+ errorCauses: [],
+ });
+ cy.get('button[type="submit"]').click();
+ cy.contains('Check your email inbox');
+ cy.contains('email within 2 minutes');
+ cy.contains('Resend email');
+ });
+ });
- context('generic error handling', () => {
- it('shows a generic error when something goes wrong', () => {
- cy.visit('/reset-password');
- cy.get('input[name="email"]').type(email);
- cy.mockNext(200, mockUserActiveWithPassword);
- cy.mockNext(403, {
- errorCode: 'E0000006',
- errorSummary:
- 'You do not have permission to perform the requested action',
- errorLink: 'E0000006',
- errorId: 'errorId',
- errorCauses: [],
- });
- cy.get('button[type="submit"]').click();
- cy.contains('Sorry, something went wrong. Please try again.');
- });
- });
+ context('generic error handling', () => {
+ it('shows a generic error when something goes wrong', () => {
+ cy.visit('/reset-password');
+ cy.get('input[name="email"]').type(email);
+ cy.mockNext(200, mockUserActiveWithPassword);
+ cy.mockNext(403, {
+ errorCode: 'E0000006',
+ errorSummary:
+ 'You do not have permission to perform the requested action',
+ errorLink: 'E0000006',
+ errorId: 'errorId',
+ errorCauses: [],
+ });
+ cy.get('button[type="submit"]').click();
+ cy.contains('Sorry, something went wrong. Please try again.');
+ });
+ });
});
diff --git a/cypress/integration/mocked/okta_sign_in.6.cy.ts b/cypress/integration/mocked/okta_sign_in.6.cy.ts
index bde0947b79..1f38c06bf5 100644
--- a/cypress/integration/mocked/okta_sign_in.6.cy.ts
+++ b/cypress/integration/mocked/okta_sign_in.6.cy.ts
@@ -1,262 +1,262 @@
describe('Sign in flow', () => {
- context('Signing in - Okta', () => {
- beforeEach(() => {
- cy.mockPurge();
- });
+ context('Signing in - Okta', () => {
+ beforeEach(() => {
+ cy.mockPurge();
+ });
- it('loads the "signed in as" page if user is already authenticated', function () {
- cy.mockPattern(
- 200,
- {
- id: 'test',
- login: 'user@example.com',
- userId: 'userId',
- status: 'ACTIVE',
- expiresAt: '2016-01-03T09:13:17.000Z',
- lastPasswordVerification: '2016-01-03T07:02:00.000Z',
- lastFactorVerification: null,
- amr: ['pwd'],
- idp: {
- id: '01a2bcdef3GHIJKLMNOP',
- type: 'OKTA',
- },
- mfaActive: true,
- },
- '/api/v1/sessions/the_sid_cookie',
- );
+ it('loads the "signed in as" page if user is already authenticated', function () {
+ cy.mockPattern(
+ 200,
+ {
+ id: 'test',
+ login: 'user@example.com',
+ userId: 'userId',
+ status: 'ACTIVE',
+ expiresAt: '2016-01-03T09:13:17.000Z',
+ lastPasswordVerification: '2016-01-03T07:02:00.000Z',
+ lastFactorVerification: null,
+ amr: ['pwd'],
+ idp: {
+ id: '01a2bcdef3GHIJKLMNOP',
+ type: 'OKTA',
+ },
+ mfaActive: true,
+ },
+ '/api/v1/sessions/the_sid_cookie',
+ );
- cy.mockPattern(204, {}, '/api/v1/users/userId/sessions');
+ cy.mockPattern(204, {}, '/api/v1/users/userId/sessions');
- cy.setCookie('sid', `the_sid_cookie`);
+ cy.setCookie('sid', `the_sid_cookie`);
- // disable the cmp on the redirect
- cy.disableCMP();
+ // disable the cmp on the redirect
+ cy.disableCMP();
- cy.visit('/signin');
+ cy.visit('/signin');
- cy.contains('Sign in to the Guardian');
- cy.contains('You are signed in with');
- cy.contains('user@example.com');
- cy.contains('Continue')
- .should('have.attr', 'href')
- .and('include', '/signin/refresh')
- .and('include', 'returnUrl=https%3A%2F%2Fm.code.dev-theguardian.com');
- cy.contains('a', 'Sign in')
- .should('have.attr', 'href')
- .and(
- 'include',
- '/signout?returnUrl=https%253A%252F%252Fprofile.thegulocal.com%252Fsignin%253FreturnUrl%253Dhttps%25253A%25252F%25252Fm.code.dev-theguardian.com',
- );
- cy.contains('Sign in with a different email');
- });
+ cy.contains('Sign in to the Guardian');
+ cy.contains('You are signed in with');
+ cy.contains('user@example.com');
+ cy.contains('Continue')
+ .should('have.attr', 'href')
+ .and('include', '/signin/refresh')
+ .and('include', 'returnUrl=https%3A%2F%2Fm.code.dev-theguardian.com');
+ cy.contains('a', 'Sign in')
+ .should('have.attr', 'href')
+ .and(
+ 'include',
+ '/signout?returnUrl=https%253A%252F%252Fprofile.thegulocal.com%252Fsignin%253FreturnUrl%253Dhttps%25253A%25252F%25252Fm.code.dev-theguardian.com',
+ );
+ cy.contains('Sign in with a different email');
+ });
- it('loads the "signed in as" page if user is already authenticated and coming from native app and oauth flow', function () {
- cy.mockPattern(
- 200,
- {
- id: 'test',
- login: 'user@example.com',
- userId: 'userId',
- status: 'ACTIVE',
- expiresAt: '2016-01-03T09:13:17.000Z',
- lastPasswordVerification: '2016-01-03T07:02:00.000Z',
- lastFactorVerification: null,
- amr: ['pwd'],
- idp: {
- id: '01a2bcdef3GHIJKLMNOP',
- type: 'OKTA',
- },
- mfaActive: true,
- },
- '/api/v1/sessions/the_sid_cookie',
- );
+ it('loads the "signed in as" page if user is already authenticated and coming from native app and oauth flow', function () {
+ cy.mockPattern(
+ 200,
+ {
+ id: 'test',
+ login: 'user@example.com',
+ userId: 'userId',
+ status: 'ACTIVE',
+ expiresAt: '2016-01-03T09:13:17.000Z',
+ lastPasswordVerification: '2016-01-03T07:02:00.000Z',
+ lastFactorVerification: null,
+ amr: ['pwd'],
+ idp: {
+ id: '01a2bcdef3GHIJKLMNOP',
+ type: 'OKTA',
+ },
+ mfaActive: true,
+ },
+ '/api/v1/sessions/the_sid_cookie',
+ );
- cy.mockPattern(204, {}, '/api/v1/users/userId/sessions');
+ cy.mockPattern(204, {}, '/api/v1/users/userId/sessions');
- cy.mockPattern(
- 200,
- {
- id: '123',
- label: 'ios_app',
- settings: {
- oauthClient: {
- redirect_uris: [],
- },
- },
- },
- '/api/v1/apps/123',
- );
+ cy.mockPattern(
+ 200,
+ {
+ id: '123',
+ label: 'ios_app',
+ settings: {
+ oauthClient: {
+ redirect_uris: [],
+ },
+ },
+ },
+ '/api/v1/apps/123',
+ );
- cy.setCookie('sid', `the_sid_cookie`);
+ cy.setCookie('sid', `the_sid_cookie`);
- // disable the cmp on the redirect
- cy.disableCMP();
+ // disable the cmp on the redirect
+ cy.disableCMP();
- cy.visit(
- '/signin?appClientId=123&fromURI=/fromURI=/oauth2/v1/authorize/redirect?okta_key=oktaKey',
- );
+ cy.visit(
+ '/signin?appClientId=123&fromURI=/fromURI=/oauth2/v1/authorize/redirect?okta_key=oktaKey',
+ );
- cy.contains('Sign in to the Guardian app');
- cy.contains('You are signed in with');
- cy.contains('user@example.com');
- cy.contains('Continue')
- .should('have.attr', 'href')
- .and(
- 'include',
- '/fromURI=/oauth2/v1/authorize/redirect?okta_key=oktaKey',
- );
- cy.contains('a', 'Sign in')
- .should('have.attr', 'href')
- .and(
- 'include',
- '/signout?returnUrl=https%253A%252F%252Fprofile.thegulocal.com%252Fsignin%253FappClientId%253D123%2526fromURI%253D%25252FfromURI%25253D%25252Foauth2%25252Fv1%25252Fauthorize%25252Fredirect%25253Fokta_key%25253DoktaKey%2526returnUrl%253Dhttps%25253A%25252F%25252Fm.code.dev-theguardian.com',
- );
- cy.contains('Sign in with a different email');
- });
+ cy.contains('Sign in to the Guardian app');
+ cy.contains('You are signed in with');
+ cy.contains('user@example.com');
+ cy.contains('Continue')
+ .should('have.attr', 'href')
+ .and(
+ 'include',
+ '/fromURI=/oauth2/v1/authorize/redirect?okta_key=oktaKey',
+ );
+ cy.contains('a', 'Sign in')
+ .should('have.attr', 'href')
+ .and(
+ 'include',
+ '/signout?returnUrl=https%253A%252F%252Fprofile.thegulocal.com%252Fsignin%253FappClientId%253D123%2526fromURI%253D%25252FfromURI%25253D%25252Foauth2%25252Fv1%25252Fauthorize%25252Fredirect%25253Fokta_key%25253DoktaKey%2526returnUrl%253Dhttps%25253A%25252F%25252Fm.code.dev-theguardian.com',
+ );
+ cy.contains('Sign in with a different email');
+ });
- it('shows an error message when okta authentication fails', function () {
- cy.visit('/signin');
- cy.get('input[name="email"]').type('example@example.com');
- cy.get('input[name="password"]').type('password');
- cy.mockNext(401, {
- errorCode: 'E0000004',
- errorSummary: 'errorSummary',
- errorLink: '',
- errorId: 'errorId',
- errorCauses: [],
- });
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.contains("Email and password don't match");
- });
+ it('shows an error message when okta authentication fails', function () {
+ cy.visit('/signin');
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.get('input[name="password"]').type('password');
+ cy.mockNext(401, {
+ errorCode: 'E0000004',
+ errorSummary: 'errorSummary',
+ errorLink: '',
+ errorId: 'errorId',
+ errorCauses: [],
+ });
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.contains("Email and password don't match");
+ });
- it('shows a generic error message when okta rate limited', function () {
- cy.visit('/signin');
- cy.get('input[name="email"]').type('example@example.com');
- cy.get('input[name="password"]').type('password');
- cy.mockNext(429, {
- errorCode: 'E0000047',
- errorSummary: 'errorSummary',
- errorLink: '',
- errorId: 'errorId',
- errorCauses: [],
- });
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.contains('There was a problem signing in, please try again.');
- });
+ it('shows a generic error message when okta rate limited', function () {
+ cy.visit('/signin');
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.get('input[name="password"]').type('password');
+ cy.mockNext(429, {
+ errorCode: 'E0000047',
+ errorSummary: 'errorSummary',
+ errorLink: '',
+ errorId: 'errorId',
+ errorCauses: [],
+ });
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.contains('There was a problem signing in, please try again.');
+ });
- it('shows a generic error message when okta api response unknown', function () {
- cy.visit('/signin');
- cy.get('input[name="email"]').type('example@example.com');
- cy.get('input[name="password"]').type('password');
- cy.mockNext(403, {
- errorCode: 'E0000147',
- errorSummary: 'errorSummary',
- errorLink: '',
- errorId: 'errorId',
- errorCauses: [],
- });
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.contains('There was a problem signing in, please try again.');
- });
+ it('shows a generic error message when okta api response unknown', function () {
+ cy.visit('/signin');
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.get('input[name="password"]').type('password');
+ cy.mockNext(403, {
+ errorCode: 'E0000147',
+ errorSummary: 'errorSummary',
+ errorLink: '',
+ errorId: 'errorId',
+ errorCauses: [],
+ });
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.contains('There was a problem signing in, please try again.');
+ });
- it('loads the redirectUrl upon successful authentication for validated user', function () {
- cy.visit('/signin?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout');
- cy.get('input[name="email"]').type('example@example.com');
- cy.get('input[name="password"]').type('password');
- cy.mockNext(200, {
- expiresAt: '3000-01-01T00:00:00.000Z',
- status: 'SUCCESS',
- sessionToken: 'some-session-token',
- _embedded: {
- user: {
- id: 'okta-id',
- passwordChanged: '2020-01-01T00:00:00.000Z',
- profile: {
- login: 'test.man@example.com',
- firstName: 'Test',
- lastName: 'Man',
- locale: 'en_GB',
- timeZone: 'Europe/London',
- },
- },
- },
- });
+ it('loads the redirectUrl upon successful authentication for validated user', function () {
+ cy.visit('/signin?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout');
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.get('input[name="password"]').type('password');
+ cy.mockNext(200, {
+ expiresAt: '3000-01-01T00:00:00.000Z',
+ status: 'SUCCESS',
+ sessionToken: 'some-session-token',
+ _embedded: {
+ user: {
+ id: 'okta-id',
+ passwordChanged: '2020-01-01T00:00:00.000Z',
+ profile: {
+ login: 'test.man@example.com',
+ firstName: 'Test',
+ lastName: 'Man',
+ locale: 'en_GB',
+ timeZone: 'Europe/London',
+ },
+ },
+ },
+ });
- cy.mockNext(200, [
- {
- id: '123',
- profile: {
- name: 'GuardianUser-EmailValidated',
- description: 'User has validated their email',
- },
- },
- ]);
+ cy.mockNext(200, [
+ {
+ id: '123',
+ profile: {
+ name: 'GuardianUser-EmailValidated',
+ description: 'User has validated their email',
+ },
+ },
+ ]);
- // we can't actually check the authorization code flow
- // so intercept the request and redirect to the guardian about page
- cy.intercept(
- `http://localhost:9000/oauth2/${Cypress.env(
- 'OKTA_CUSTOM_OAUTH_SERVER',
- )}/v1/authorize*`,
- (req) => {
- req.redirect('https://www.theguardian.com/about');
- },
- ).as('authRedirect');
+ // we can't actually check the authorization code flow
+ // so intercept the request and redirect to the guardian about page
+ cy.intercept(
+ `http://localhost:9000/oauth2/${Cypress.env(
+ 'OKTA_CUSTOM_OAUTH_SERVER',
+ )}/v1/authorize*`,
+ (req) => {
+ req.redirect('https://www.theguardian.com/about');
+ },
+ ).as('authRedirect');
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.wait('@authRedirect').then(() => {
- cy.url().should('include', 'https://www.theguardian.com/about');
- });
- });
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.wait('@authRedirect').then(() => {
+ cy.url().should('include', 'https://www.theguardian.com/about');
+ });
+ });
- it('redirects to the default url if no redirectUrl given', function () {
- cy.visit('/signin');
- cy.get('input[name="email"]').type('example@example.com');
- cy.get('input[name="password"]').type('password');
- cy.mockNext(200, {
- expiresAt: '3000-01-01T00:00:00.000Z',
- status: 'SUCCESS',
- sessionToken: 'some-session-token',
- _embedded: {
- user: {
- id: 'okta-id',
- passwordChanged: '2020-01-01T00:00:00.000Z',
- profile: {
- login: 'test.man@example.com',
- firstName: 'Test',
- lastName: 'Man',
- locale: 'en_GB',
- timeZone: 'Europe/London',
- },
- },
- },
- });
+ it('redirects to the default url if no redirectUrl given', function () {
+ cy.visit('/signin');
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.get('input[name="password"]').type('password');
+ cy.mockNext(200, {
+ expiresAt: '3000-01-01T00:00:00.000Z',
+ status: 'SUCCESS',
+ sessionToken: 'some-session-token',
+ _embedded: {
+ user: {
+ id: 'okta-id',
+ passwordChanged: '2020-01-01T00:00:00.000Z',
+ profile: {
+ login: 'test.man@example.com',
+ firstName: 'Test',
+ lastName: 'Man',
+ locale: 'en_GB',
+ timeZone: 'Europe/London',
+ },
+ },
+ },
+ });
- cy.mockNext(200, [
- {
- id: '123',
- profile: {
- name: 'GuardianUser-EmailValidated',
- description: 'User has validated their email',
- },
- },
- ]);
+ cy.mockNext(200, [
+ {
+ id: '123',
+ profile: {
+ name: 'GuardianUser-EmailValidated',
+ description: 'User has validated their email',
+ },
+ },
+ ]);
- // we can't actually check the authorization code flow
- // so intercept the request and redirect to the default return URL
- cy.intercept(
- `http://localhost:9000/oauth2/${Cypress.env(
- 'OKTA_CUSTOM_OAUTH_SERVER',
- )}/v1/authorize*`,
- (req) => {
- req.redirect('https://m.code.dev-theguardian.com/');
- },
- ).as('authRedirect');
+ // we can't actually check the authorization code flow
+ // so intercept the request and redirect to the default return URL
+ cy.intercept(
+ `http://localhost:9000/oauth2/${Cypress.env(
+ 'OKTA_CUSTOM_OAUTH_SERVER',
+ )}/v1/authorize*`,
+ (req) => {
+ req.redirect('https://m.code.dev-theguardian.com/');
+ },
+ ).as('authRedirect');
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.wait('@authRedirect').then(() => {
- cy.url().should('include', 'https://m.code.dev-theguardian.com/');
- });
- });
- });
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.wait('@authRedirect').then(() => {
+ cy.url().should('include', 'https://m.code.dev-theguardian.com/');
+ });
+ });
+ });
});
diff --git a/cypress/integration/mocked/onboarding_flow.1.cy.ts b/cypress/integration/mocked/onboarding_flow.1.cy.ts
index c3cde62686..3f84e4db10 100644
--- a/cypress/integration/mocked/onboarding_flow.1.cy.ts
+++ b/cypress/integration/mocked/onboarding_flow.1.cy.ts
@@ -2,24 +2,24 @@
import { injectAndCheckAxe } from '../../support/cypress-axe';
import {
- AUTH_REDIRECT_ENDPOINT,
- authRedirectSignInRecentlyEmailValidated,
+ AUTH_REDIRECT_ENDPOINT,
+ authRedirectSignInRecentlyEmailValidated,
} from '../../support/idapi/auth';
import {
- CONSENTS_ENDPOINT,
- CONSENT_ERRORS,
- allConsents,
- defaultUserConsent,
- getUserConsents,
- optedIntoPersonalisedAdvertisingUserConsent,
- optedOutUserConsent,
+ CONSENTS_ENDPOINT,
+ CONSENT_ERRORS,
+ allConsents,
+ defaultUserConsent,
+ getUserConsents,
+ optedIntoPersonalisedAdvertisingUserConsent,
+ optedOutUserConsent,
} from '../../support/idapi/consent';
import { setAuthCookies } from '../../support/idapi/cookie';
import {
- USER_CONSENTS_ENDPOINT,
- USER_ENDPOINT,
- createUser,
- verifiedUserWithNoConsent,
+ USER_CONSENTS_ENDPOINT,
+ USER_ENDPOINT,
+ createUser,
+ verifiedUserWithNoConsent,
} from '../../support/idapi/user';
import CommunicationsPage from '../../support/pages/onboarding/communications_page';
import NewslettersPage from '../../support/pages/onboarding/newsletters_page';
@@ -28,15 +28,15 @@ import YourDataPage from '../../support/pages/onboarding/your_data_page';
import { setMvtId } from '../../support/commands/setMvtId';
import {
- GEOLOCATION_CODES,
- getGeoLocationHeaders,
+ GEOLOCATION_CODES,
+ getGeoLocationHeaders,
} from '../../support/geolocation';
import {
- NEWSLETTER_ENDPOINT,
- NEWSLETTER_ERRORS,
- NEWSLETTER_SUBSCRIPTION_ENDPOINT,
- allNewsletters,
- userNewsletters,
+ NEWSLETTER_ENDPOINT,
+ NEWSLETTER_ERRORS,
+ NEWSLETTER_SUBSCRIPTION_ENDPOINT,
+ allNewsletters,
+ userNewsletters,
} from '../../support/idapi/newsletter';
import Onboarding from '../../support/pages/onboarding/onboarding_page';
import VerifyEmail from '../../support/pages/verify_email';
@@ -46,1014 +46,1014 @@ const { NEWSLETTERS } = NewslettersPage.CONTENT;
// TODO: remove this once we have migrated fully to OAuth as we're unable to mock the OAuth flow to get Tokens
// TODO: best thing to do will move as much as possible to the ete tests
describe('Onboarding flow', () => {
- beforeEach(() => {
- cy.mockPurge();
- setMvtId('0');
- });
-
- context('Full flow', () => {
- beforeEach(() => {
- setAuthCookies();
- cy.mockAll(
- 200,
- authRedirectSignInRecentlyEmailValidated,
- AUTH_REDIRECT_ENDPOINT,
- );
- cy.mockAll(200, allConsents, CONSENTS_ENDPOINT);
- cy.mockAll(200, allNewsletters, NEWSLETTER_ENDPOINT);
- cy.mockAll(200, verifiedUserWithNoConsent, USER_ENDPOINT);
- cy.mockAll(
- 200,
- verifiedUserWithNoConsent.user.consents,
- USER_CONSENTS_ENDPOINT,
- );
- cy.mockAll(200, userNewsletters(), NEWSLETTER_SUBSCRIPTION_ENDPOINT);
- });
-
- it('goes through full flow, opt in all consents/newsletters, preserve returnUrl', () => {
- const newslettersToSubscribe = [
- { listId: 4147 },
- { listId: 4156 },
- { listId: 4165 },
- ];
-
- const consent = defaultUserConsent.map(({ id }) => {
- // eslint-disable-next-line functional/no-let
- let consented = true;
- if (id.includes('_optout')) {
- consented = false;
- }
- if (id.includes('personalised_advertising')) {
- consented = true;
- }
- return {
- id,
- consented,
- };
- });
-
- const returnUrl = encodeURIComponent(
- `https://www.theguardian.com/science/grrlscientist/2012/aug/07/3`,
- );
-
- cy.enableCMP();
- CommunicationsPage.gotoFlowStart({
- query: {
- returnUrl,
- useIdapi: 'true',
- },
- });
- cy.acceptCMP();
- cy.setCookie('GU_geo_country', 'FR');
- cy.url().should('include', CommunicationsPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
- cy.get('input[name=_cmpConsentedState]').should('have.value', 'true');
- CommunicationsPage.backButton().should('not.exist');
- CommunicationsPage.allCheckboxes().should('not.be.checked');
- CommunicationsPage.allCheckboxes().click({ multiple: true });
-
- // mock form save success
- cy.mockNext(200);
-
- CommunicationsPage.saveAndContinueButton().click();
- cy.lastPayloadsAre([
- [{ id: 'supporter', consented: true }],
- { privateFields: { registrationLocation: 'Europe' } },
- ]);
-
- cy.url().should('include', NewslettersPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
-
- NewslettersPage.backButton()
- .should('have.attr', 'href')
- .and('include', CommunicationsPage.URL);
-
- NewslettersPage.allCheckboxes()
- .should('not.be.checked')
- .click({ multiple: true });
-
- // mock form save success
- cy.mockNext(200);
-
- NewslettersPage.saveAndContinueButton().click();
-
- cy.lastPayloadsAre([
- [
- { id: '4147', subscribed: true },
- { id: '4156', subscribed: true },
- { id: '4165', subscribed: true },
- ],
- [{ id: 'events', consented: true }],
- ]);
-
- cy.url().should('include', YourDataPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
-
- YourDataPage.backButton()
- .should('have.attr', 'href')
- .and('include', NewslettersPage.URL);
-
- YourDataPage.personalisedAdvertisingOptInInput().should('not.be.checked');
-
- YourDataPage.personalisedAdvertisingOptInSwitch().click();
- YourDataPage.marketingOptInSwitch().should('be.checked');
- YourDataPage.personalisedAdvertisingOptInInput().should('be.checked');
- // mock form save success
- cy.mockNext(200);
-
- // user consents mock response for review of consents flow
- cy.mockAll(200, createUser(consent), USER_ENDPOINT);
- cy.mockAll(200, consent, USER_CONSENTS_ENDPOINT);
-
- // mock load user newsletters
- cy.mockAll(
- 200,
- userNewsletters(newslettersToSubscribe),
- NEWSLETTER_SUBSCRIPTION_ENDPOINT,
- );
-
- YourDataPage.saveAndContinueButton().click();
- // Explicity check '_optin' consents are in inverted back to '_optouts' when posted
- cy.lastPayloadIs([
- { id: 'profiling_optout', consented: false },
- { id: 'personalised_advertising', consented: true },
- ]);
-
- cy.url().should('include', ReviewPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
-
- ReviewPage.backButton().should('not.exist');
- ReviewPage.saveAndContinueButton().should('not.exist');
-
- // contains opted in newsletters
- Object.values(ReviewPage.CONTENT.NEWSLETTERS).forEach((newsletter) =>
- cy.contains(newsletter),
- );
-
- // contains consents
- cy.contains(ReviewPage.CONTENT.SUPPORTER_CONSENT);
- cy.contains(ReviewPage.CONTENT.PROFILING_CONSENT);
- cy.contains(ReviewPage.CONTENT.PERSONALISED_ADVERTISING_CONSENT);
-
- // does not contain messaging encouraging user to consider other newsletters
- cy.contains(ReviewPage.CONTENT.NO_NEWSLETTERS_TITLE).should('not.exist');
-
- ReviewPage.returnButton()
- .should('have.attr', 'href')
- .and('include', decodeURIComponent(returnUrl));
- });
-
- it('goes through full flow, opt out all consents/newsletters, preserve returnUrl', () => {
- const returnUrl = encodeURIComponent(
- `https://www.theguardian.com/science/grrlscientist/2012/aug/07/3`,
- );
-
- CommunicationsPage.gotoFlowStart({
- query: {
- returnUrl,
- useIdapi: 'true',
- },
- });
+ beforeEach(() => {
+ cy.mockPurge();
+ setMvtId('0');
+ });
+
+ context('Full flow', () => {
+ beforeEach(() => {
+ setAuthCookies();
+ cy.mockAll(
+ 200,
+ authRedirectSignInRecentlyEmailValidated,
+ AUTH_REDIRECT_ENDPOINT,
+ );
+ cy.mockAll(200, allConsents, CONSENTS_ENDPOINT);
+ cy.mockAll(200, allNewsletters, NEWSLETTER_ENDPOINT);
+ cy.mockAll(200, verifiedUserWithNoConsent, USER_ENDPOINT);
+ cy.mockAll(
+ 200,
+ verifiedUserWithNoConsent.user.consents,
+ USER_CONSENTS_ENDPOINT,
+ );
+ cy.mockAll(200, userNewsletters(), NEWSLETTER_SUBSCRIPTION_ENDPOINT);
+ });
+
+ it('goes through full flow, opt in all consents/newsletters, preserve returnUrl', () => {
+ const newslettersToSubscribe = [
+ { listId: 4147 },
+ { listId: 4156 },
+ { listId: 4165 },
+ ];
+
+ const consent = defaultUserConsent.map(({ id }) => {
+ // eslint-disable-next-line functional/no-let
+ let consented = true;
+ if (id.includes('_optout')) {
+ consented = false;
+ }
+ if (id.includes('personalised_advertising')) {
+ consented = true;
+ }
+ return {
+ id,
+ consented,
+ };
+ });
+
+ const returnUrl = encodeURIComponent(
+ `https://www.theguardian.com/science/grrlscientist/2012/aug/07/3`,
+ );
+
+ cy.enableCMP();
+ CommunicationsPage.gotoFlowStart({
+ query: {
+ returnUrl,
+ useIdapi: 'true',
+ },
+ });
+ cy.acceptCMP();
+ cy.setCookie('GU_geo_country', 'FR');
+ cy.url().should('include', CommunicationsPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
+ cy.get('input[name=_cmpConsentedState]').should('have.value', 'true');
+ CommunicationsPage.backButton().should('not.exist');
+ CommunicationsPage.allCheckboxes().should('not.be.checked');
+ CommunicationsPage.allCheckboxes().click({ multiple: true });
+
+ // mock form save success
+ cy.mockNext(200);
+
+ CommunicationsPage.saveAndContinueButton().click();
+ cy.lastPayloadsAre([
+ [{ id: 'supporter', consented: true }],
+ { privateFields: { registrationLocation: 'Europe' } },
+ ]);
+
+ cy.url().should('include', NewslettersPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
+
+ NewslettersPage.backButton()
+ .should('have.attr', 'href')
+ .and('include', CommunicationsPage.URL);
+
+ NewslettersPage.allCheckboxes()
+ .should('not.be.checked')
+ .click({ multiple: true });
+
+ // mock form save success
+ cy.mockNext(200);
+
+ NewslettersPage.saveAndContinueButton().click();
+
+ cy.lastPayloadsAre([
+ [
+ { id: '4147', subscribed: true },
+ { id: '4156', subscribed: true },
+ { id: '4165', subscribed: true },
+ ],
+ [{ id: 'events', consented: true }],
+ ]);
+
+ cy.url().should('include', YourDataPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
+
+ YourDataPage.backButton()
+ .should('have.attr', 'href')
+ .and('include', NewslettersPage.URL);
+
+ YourDataPage.personalisedAdvertisingOptInInput().should('not.be.checked');
+
+ YourDataPage.personalisedAdvertisingOptInSwitch().click();
+ YourDataPage.marketingOptInSwitch().should('be.checked');
+ YourDataPage.personalisedAdvertisingOptInInput().should('be.checked');
+ // mock form save success
+ cy.mockNext(200);
+
+ // user consents mock response for review of consents flow
+ cy.mockAll(200, createUser(consent), USER_ENDPOINT);
+ cy.mockAll(200, consent, USER_CONSENTS_ENDPOINT);
+
+ // mock load user newsletters
+ cy.mockAll(
+ 200,
+ userNewsletters(newslettersToSubscribe),
+ NEWSLETTER_SUBSCRIPTION_ENDPOINT,
+ );
+
+ YourDataPage.saveAndContinueButton().click();
+ // Explicity check '_optin' consents are in inverted back to '_optouts' when posted
+ cy.lastPayloadIs([
+ { id: 'profiling_optout', consented: false },
+ { id: 'personalised_advertising', consented: true },
+ ]);
+
+ cy.url().should('include', ReviewPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
+
+ ReviewPage.backButton().should('not.exist');
+ ReviewPage.saveAndContinueButton().should('not.exist');
+
+ // contains opted in newsletters
+ Object.values(ReviewPage.CONTENT.NEWSLETTERS).forEach((newsletter) =>
+ cy.contains(newsletter),
+ );
+
+ // contains consents
+ cy.contains(ReviewPage.CONTENT.SUPPORTER_CONSENT);
+ cy.contains(ReviewPage.CONTENT.PROFILING_CONSENT);
+ cy.contains(ReviewPage.CONTENT.PERSONALISED_ADVERTISING_CONSENT);
+
+ // does not contain messaging encouraging user to consider other newsletters
+ cy.contains(ReviewPage.CONTENT.NO_NEWSLETTERS_TITLE).should('not.exist');
+
+ ReviewPage.returnButton()
+ .should('have.attr', 'href')
+ .and('include', decodeURIComponent(returnUrl));
+ });
+
+ it('goes through full flow, opt out all consents/newsletters, preserve returnUrl', () => {
+ const returnUrl = encodeURIComponent(
+ `https://www.theguardian.com/science/grrlscientist/2012/aug/07/3`,
+ );
+
+ CommunicationsPage.gotoFlowStart({
+ query: {
+ returnUrl,
+ useIdapi: 'true',
+ },
+ });
- cy.url().should('include', CommunicationsPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
+ cy.url().should('include', CommunicationsPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
- CommunicationsPage.backButton().should('not.exist');
+ CommunicationsPage.backButton().should('not.exist');
- CommunicationsPage.allCheckboxes().should('not.be.checked');
- cy.get('input[name=_cmpConsentedState]').should('have.value', 'false');
+ CommunicationsPage.allCheckboxes().should('not.be.checked');
+ cy.get('input[name=_cmpConsentedState]').should('have.value', 'false');
- // mock form save success
- cy.mockNext(200);
+ // mock form save success
+ cy.mockNext(200);
- CommunicationsPage.saveAndContinueButton().click();
+ CommunicationsPage.saveAndContinueButton().click();
- // Use .lastPayloadsAre to ensure the IDAPI registrationLocation update is NOT posted
- cy.lastPayloadsAre([[{ id: 'supporter', consented: false }]]);
+ // Use .lastPayloadsAre to ensure the IDAPI registrationLocation update is NOT posted
+ cy.lastPayloadsAre([[{ id: 'supporter', consented: false }]]);
- cy.url().should('include', NewslettersPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
+ cy.url().should('include', NewslettersPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
- NewslettersPage.backButton()
- .should('have.attr', 'href')
- .and('include', CommunicationsPage.URL);
+ NewslettersPage.backButton()
+ .should('have.attr', 'href')
+ .and('include', CommunicationsPage.URL);
- // mock form save success
- cy.mockNext(200);
+ // mock form save success
+ cy.mockNext(200);
- cy.enableCMP();
- NewslettersPage.saveAndContinueButton().click();
- cy.lastPayloadsAre([[], [{ id: 'events', consented: false }]]);
- cy.acceptCMP();
+ cy.enableCMP();
+ NewslettersPage.saveAndContinueButton().click();
+ cy.lastPayloadsAre([[], [{ id: 'events', consented: false }]]);
+ cy.acceptCMP();
- cy.url().should('include', YourDataPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
+ cy.url().should('include', YourDataPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
- YourDataPage.backButton()
- .should('have.attr', 'href')
- .and('include', NewslettersPage.URL);
+ YourDataPage.backButton()
+ .should('have.attr', 'href')
+ .and('include', NewslettersPage.URL);
- YourDataPage.marketingOptInSwitch().should('be.checked');
- YourDataPage.marketingOptInClickableSection().click();
- YourDataPage.marketingOptInSwitch().should('not.be.checked');
- YourDataPage.personalisedAdvertisingOptInSwitch().should('exist');
- YourDataPage.personalisedAdvertisingOptInInput().should('not.be.checked');
-
- // mock form save success
- cy.mockNext(200);
-
- cy.mockAll(200, createUser(optedOutUserConsent), USER_ENDPOINT);
- cy.mockAll(200, optedOutUserConsent, USER_CONSENTS_ENDPOINT);
-
- YourDataPage.saveAndContinueButton().click();
- // Explicity check '_optin' consents are in inverted back to '_optouts' when posted
- cy.lastPayloadIs([
- { id: 'profiling_optout', consented: true },
- { id: 'personalised_advertising', consented: false },
- ]);
-
- cy.url().should('include', ReviewPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
-
- ReviewPage.backButton().should('not.exist');
- ReviewPage.saveAndContinueButton().should('not.exist');
-
- // contains no opted in newsletters
- Object.values(ReviewPage.CONTENT.NEWSLETTERS).forEach((newsletter) =>
- cy.contains(newsletter).should('not.exist'),
- );
-
- // contains no consents
- cy.contains(ReviewPage.CONTENT.SUPPORTER_CONSENT).should('not.exist');
- cy.contains(ReviewPage.CONTENT.PROFILING_CONSENT).should('not.exist');
- cy.contains(ReviewPage.CONTENT.PERSONALISED_ADVERTISING_CONSENT).should(
- 'not.exist',
- );
-
- // contains messaging encouraging user to explore other newsletters
- cy.contains(ReviewPage.CONTENT.NO_NEWSLETTERS_TITLE);
-
- ReviewPage.returnButton()
- .should('have.attr', 'href')
- .and('include', decodeURIComponent(returnUrl));
- });
-
- it('uses a default returnUrl if none provided', () => {
- const returnUrl = encodeURIComponent(Cypress.env('DEFAULT_RETURN_URI'));
-
- CommunicationsPage.gotoFlowStart({
- query: {
- useIdapi: 'true',
- },
- });
-
- cy.url().should('include', CommunicationsPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
-
- // mock form save success
- cy.mockNext(200);
-
- CommunicationsPage.saveAndContinueButton().click();
-
- cy.url().should('include', NewslettersPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
-
- // mock form save success
- cy.mockNext(200);
-
- NewslettersPage.saveAndContinueButton().click();
-
- cy.url().should('include', YourDataPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
-
- YourDataPage.marketingOptInClickableSection().click();
-
- // mock form save success
- cy.mockNext(200);
-
- YourDataPage.saveAndContinueButton().click();
- cy.url().should('include', ReviewPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
-
- ReviewPage.returnButton()
- .should('have.attr', 'href')
- .and('include', decodeURIComponent(returnUrl));
- });
- });
-
- context('Login middleware', () => {
- it('no sc_gu_u cookie, redirect to login page', () => {
- const signInUrl = Cypress.env('SIGN_IN_PAGE_URL');
- cy.setCookie('GU_U', 'FAKE_GU_U');
- cy.setCookie('SC_GU_LA', 'FAKE_SC_GU_LA');
-
- cy.request({
- url: `${Onboarding.URL}?useIdapi=true`,
- followRedirect: false,
- }).then((res) => {
- expect(res.status).to.eq(303);
- expect(res.redirectedToUrl).to.include(signInUrl);
- });
- });
-
- it('no sc_gu_la cookie, redirect to login page', () => {
- const signInUrl = Cypress.env('SIGN_IN_PAGE_URL');
- cy.setCookie('GU_U', 'FAKE_GU_U');
- cy.setCookie('SC_GU_U', 'FAKE_SC_GU_U');
-
- cy.request({
- url: `${Onboarding.URL}?useIdapi=true`,
- followRedirect: false,
- }).then((res) => {
- expect(res.status).to.eq(303);
- expect(res.redirectedToUrl).to.include(signInUrl);
- });
- });
-
- it('email not validated, go to verify email page', () => {
- setAuthCookies();
- const emailNotValidatedResponse = {
- signInStatus: 'signedInRecently',
- emailValidated: false,
- redirect: null,
- };
- cy.mockAll(200, emailNotValidatedResponse, AUTH_REDIRECT_ENDPOINT);
-
- cy.request({
- url: `${Onboarding.URL}?useIdapi=true`,
- followRedirect: false,
- }).then((res) => {
- expect(res.status).to.eq(303);
- expect(res.redirectedToUrl).to.include(VerifyEmail.URL);
- });
- });
-
- it('recently logged in, go to consents flow', () => {
- setAuthCookies();
- cy.mockAll(
- 200,
- authRedirectSignInRecentlyEmailValidated,
- AUTH_REDIRECT_ENDPOINT,
- );
- cy.request({
- url: `${Onboarding.URL}?useIdapi=true`,
- followRedirect: false,
- }).then((res) => {
- expect(res.status).to.eq(303);
- expect(res.redirectedToUrl).to.include(CommunicationsPage.URL);
- });
- });
-
- it('not recently logged in, follows supplied redirect', () => {
- setAuthCookies();
- const emailNotValidatedResponse = {
- signInStatus: 'signedInNotRecently',
- emailValidated: true,
- redirect: {
- url: 'https://fakeloginfortest.code.dev-theguardian.co.uk',
- },
- };
- cy.mockAll(200, emailNotValidatedResponse, AUTH_REDIRECT_ENDPOINT);
-
- cy.request({
- url: `${Onboarding.URL}?useIdapi=true`,
- followRedirect: false,
- }).then((res) => {
- expect(res.status).to.eq(303);
- expect(res.redirectedToUrl).to.include(
- 'https://fakeloginfortest.code.dev-theguardian.co.uk',
- );
- });
- });
-
- it('if missing redirect information, it redirects to the default ', () => {
- const signInUrl = Cypress.env('SIGN_IN_PAGE_URL');
- setAuthCookies();
- const emailNotValidatedResponse = {
- signInStatus: 'signedInNotRecently',
- emailValidated: true,
- redirect: undefined,
- };
-
- cy.mockAll(200, emailNotValidatedResponse, AUTH_REDIRECT_ENDPOINT);
-
- cy.request({
- url: `${Onboarding.URL}?useIdapi=true`,
- followRedirect: false,
- }).then((res) => {
- expect(res.status).to.eq(303);
- expect(res.redirectedToUrl).to.include(signInUrl);
- });
- });
-
- it('on idapi error it redirects to the sign in page with the error flag set', () => {
- setAuthCookies();
- cy.mockAll(502, 'gateway error', AUTH_REDIRECT_ENDPOINT);
- cy.request({
- url: `${Onboarding.URL}?useIdapi=true`,
- followRedirect: false,
- }).then((res) => {
- expect(res.status).to.eq(303);
- expect(res.redirectedToUrl).to.include(
- `error=signin-error-bad-request`,
- );
- });
- });
- });
-
- context('Contact options page', () => {
- beforeEach(() => {
- setAuthCookies();
- cy.mockAll(
- 200,
- authRedirectSignInRecentlyEmailValidated,
- AUTH_REDIRECT_ENDPOINT,
- );
- cy.mockAll(200, allConsents, CONSENTS_ENDPOINT);
- });
-
- it('has no detectable a11y violations', () => {
- cy.mockAll(
- 200,
- verifiedUserWithNoConsent.user.consents,
- USER_CONSENTS_ENDPOINT,
- );
- CommunicationsPage.goto({
- query: {
- useIdapi: true,
- },
- });
- injectAndCheckAxe();
- });
-
- it('had no detectable a11y voilations if previously selected consents', () => {
- const consented = getUserConsents(['jobs', 'offers']);
- cy.mockAll(200, consented, USER_CONSENTS_ENDPOINT);
- CommunicationsPage.goto({
- query: {
- useIdapi: true,
- },
- });
- injectAndCheckAxe();
- });
-
- it('has no detectable a11y violations on with an error', () => {
- cy.mockAll(500, {}, USER_ENDPOINT);
- CommunicationsPage.goto({
- query: {
- useIdapi: true,
- },
- });
- injectAndCheckAxe();
- });
-
- it('shows correct contact options, none checked by default', () => {
- cy.mockAll(
- 200,
- verifiedUserWithNoConsent.user.consents,
- USER_CONSENTS_ENDPOINT,
- );
- CommunicationsPage.goto({
- query: {
- useIdapi: true,
- },
- });
- CommunicationsPage.backButton().should('not.exist');
- CommunicationsPage.allCheckboxes().should('not.be.checked');
- });
-
- it('shows any previously selected consents', () => {
- const consented = getUserConsents(['supporter']);
- cy.mockAll(200, consented, USER_CONSENTS_ENDPOINT);
- CommunicationsPage.goto({
- query: {
- useIdapi: true,
- },
- });
- CommunicationsPage.backButton().should('not.exist');
- CommunicationsPage.consentCheckboxWithTitle(
- 'Supporting the Guardian',
- ).should('be.checked');
- });
-
- it('displays a relevant error message on user end point failure', () => {
- cy.mockAll(500, {}, USER_CONSENTS_ENDPOINT);
- CommunicationsPage.goto({
- query: {
- useIdapi: true,
- },
- });
- CommunicationsPage.errorBanner().contains(CONSENT_ERRORS.GENERIC);
- CommunicationsPage.backButton().should('not.exist');
- CommunicationsPage.saveAndContinueButton().should('not.exist');
- });
-
- it('displays a relevant error on consents endpoint failure', () => {
- cy.mockAll(500, {}, CONSENTS_ENDPOINT);
- CommunicationsPage.goto({
- query: {
- useIdapi: true,
- },
- });
- CommunicationsPage.errorBanner().contains(CONSENT_ERRORS.GENERIC);
- CommunicationsPage.backButton().should('not.exist');
- CommunicationsPage.saveAndContinueButton().should('not.exist');
- });
- });
-
- context('Newsletters page', () => {
- beforeEach(() => {
- setAuthCookies();
- cy.mockAll(
- 200,
- authRedirectSignInRecentlyEmailValidated,
- AUTH_REDIRECT_ENDPOINT,
- );
- cy.mockAll(200, allNewsletters, NEWSLETTER_ENDPOINT);
- cy.mockAll(200, userNewsletters(), NEWSLETTER_SUBSCRIPTION_ENDPOINT);
- cy.mockAll(200, allConsents, CONSENTS_ENDPOINT);
- cy.mockAll(
- 200,
- verifiedUserWithNoConsent.user.consents,
- USER_CONSENTS_ENDPOINT,
- );
- });
-
- it('has no detectable a11y violations', () => {
- const headers = getGeoLocationHeaders(GEOLOCATION_CODES.GB);
-
- cy.visit(NewslettersPage.URL, { headers, qs: { useIdapi: 'true' } });
- injectAndCheckAxe();
- });
-
- it('had no detectable a11y voilations if previously selected newsletter', () => {
- const newslettersToSubscribe = [{ listId: 4147 }, { listId: 4165 }];
- cy.mockAll(
- 200,
- userNewsletters(newslettersToSubscribe),
- NEWSLETTER_SUBSCRIPTION_ENDPOINT,
- );
- NewslettersPage.goto({
- query: {
- useIdapi: true,
- },
- });
- injectAndCheckAxe();
- });
-
- it('has no detectable a11y violations on with an error', () => {
- cy.mockAll(500, {}, NEWSLETTER_ENDPOINT);
- NewslettersPage.goto({
- query: {
- useIdapi: true,
- },
- });
- injectAndCheckAxe();
- });
-
- it('correct newsletters shown for uk, none checked by default', () => {
- const headers = getGeoLocationHeaders(GEOLOCATION_CODES.GB);
-
- cy.visit(NewslettersPage.URL, { headers, qs: { useIdapi: 'true' } });
-
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.FIRST_EDITION_UK).should(
- 'not.be.checked',
- );
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.LONG_READ).should(
- 'not.be.checked',
- );
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.GREEN_LIGHT).should(
- 'not.be.checked',
- );
- NewslettersPage.checkboxWithTitle(
- NewslettersPage.CONTENT.Consents.EVENTS,
- ).should('not.be.checked');
-
- CommunicationsPage.backButton().should('exist');
- CommunicationsPage.saveAndContinueButton().should('exist');
- });
-
- it('correct newsletters shown for United States of America, none checked by default', () => {
- const headers = getGeoLocationHeaders(GEOLOCATION_CODES.AMERICA);
-
- cy.visit(NewslettersPage.URL, { headers, qs: { useIdapi: 'true' } });
-
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.FIRST_THING_US).should(
- 'not.be.checked',
- );
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.LONG_READ).should(
- 'not.be.checked',
- );
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.GREEN_LIGHT).should(
- 'not.be.checked',
- );
- NewslettersPage.checkboxWithTitle(
- NewslettersPage.CONTENT.Consents.EVENTS,
- ).should('not.be.checked');
-
- CommunicationsPage.backButton().should('exist');
- CommunicationsPage.saveAndContinueButton().should('exist');
- });
-
- it('correct newsletters shown for permissioned United States browser, none checked by default', () => {
- const headers = getGeoLocationHeaders(GEOLOCATION_CODES.AMERICA);
- cy.setEncryptedStateCookie({
- isCmpConsented: true,
- });
-
- cy.visit(NewslettersPage.URL, { headers, qs: { useIdapi: 'true' } });
-
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.FIRST_THING_US).should(
- 'not.be.checked',
- );
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.HEADLINES_US).should(
- 'not.be.checked',
- );
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.GREEN_LIGHT).should(
- 'not.be.checked',
- );
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.OPINION_US).should(
- 'not.be.checked',
- );
-
- cy.contains(NewslettersPage.CONTENT.Consents.EVENTS).should('not.exist');
-
- CommunicationsPage.backButton().should('exist');
- CommunicationsPage.saveAndContinueButton().should('exist');
- });
-
- it('correct newsletters shown for Australia, none checked by default', () => {
- const headers = getGeoLocationHeaders(GEOLOCATION_CODES.AUSTRALIA);
-
- cy.visit(NewslettersPage.URL, { headers, qs: { useIdapi: 'true' } });
-
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.MORNING_MAIL_AU).should(
- 'not.be.checked',
- );
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.LONG_READ).should(
- 'not.be.checked',
- );
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.GREEN_LIGHT).should(
- 'not.be.checked',
- );
- NewslettersPage.checkboxWithTitle(
- NewslettersPage.CONTENT.Consents.EVENTS,
- ).should('not.be.checked');
-
- CommunicationsPage.backButton().should('exist');
- CommunicationsPage.saveAndContinueButton().should('exist');
- });
-
- it('correct localised newsletters shown for permissioned Australian browser, none checked by default', () => {
- const headers = getGeoLocationHeaders(GEOLOCATION_CODES.AUSTRALIA);
-
- cy.setEncryptedStateCookie({
- isCmpConsented: true,
- });
- cy.visit(NewslettersPage.URL, { headers, qs: { useIdapi: 'true' } });
-
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.MORNING_MAIL_AU).should(
- 'not.be.checked',
- );
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.AFTERNOON_UPDATE_AU).should(
- 'not.be.checked',
- );
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.FIVE_GREAT_READS_AU).should(
- 'not.be.checked',
- );
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.SAVED_FOR_LATER_AU).should(
- 'not.be.checked',
- );
- cy.contains(NewslettersPage.CONTENT.Consents.EVENTS).should('not.exist');
-
- CommunicationsPage.backButton().should('exist');
- CommunicationsPage.saveAndContinueButton().should('exist');
- });
-
- it('correct newsletters shown for rest of the world, none checked by default', () => {
- const headers = getGeoLocationHeaders(GEOLOCATION_CODES.OTHERS);
-
- cy.visit(NewslettersPage.URL, { headers, qs: { useIdapi: 'true' } });
-
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.FIRST_EDITION_UK).should(
- 'not.be.checked',
- );
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.LONG_READ).should(
- 'not.be.checked',
- );
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.GREEN_LIGHT).should(
- 'not.be.checked',
- );
- NewslettersPage.checkboxWithTitle(
- NewslettersPage.CONTENT.Consents.EVENTS,
- ).should('not.be.checked');
-
- CommunicationsPage.backButton().should('exist');
- CommunicationsPage.saveAndContinueButton().should('exist');
- });
-
- it('show already selected newsletters / consents', () => {
- const newslettersToSubscribe = [{ listId: 4147 }, { listId: 4165 }];
- cy.mockAll(
- 200,
- userNewsletters(newslettersToSubscribe),
- NEWSLETTER_SUBSCRIPTION_ENDPOINT,
- );
- const consented = getUserConsents(['events']);
- cy.mockAll(200, consented, USER_CONSENTS_ENDPOINT);
- NewslettersPage.goto({
- query: {
- useIdapi: true,
- },
- });
-
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.FIRST_EDITION_UK).should(
- 'not.be.checked',
- );
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.LONG_READ).should(
- 'be.checked',
- );
- NewslettersPage.checkboxWithTitle(NEWSLETTERS.GREEN_LIGHT).should(
- 'be.checked',
- );
- NewslettersPage.checkboxWithTitle(
- NewslettersPage.CONTENT.Consents.EVENTS,
- ).should('be.checked');
- });
-
- it('displays a relevant error on newsletters endpoint failure', () => {
- cy.mockAll(500, {}, NEWSLETTER_ENDPOINT);
- NewslettersPage.goto({
- query: {
- useIdapi: true,
- },
- });
- NewslettersPage.errorBanner().contains(NEWSLETTER_ERRORS.GENERIC);
- NewslettersPage.backButton().should('not.exist');
- NewslettersPage.saveAndContinueButton().should('not.exist');
- });
-
- it('displays a relevant error on newsletters subscription endpoint failure', () => {
- cy.mockAll(500, {}, NEWSLETTER_SUBSCRIPTION_ENDPOINT);
- NewslettersPage.goto({
- query: {
- useIdapi: true,
- },
- });
- NewslettersPage.errorBanner().contains(NEWSLETTER_ERRORS.GENERIC);
- NewslettersPage.backButton().should('not.exist');
- NewslettersPage.saveAndContinueButton().should('not.exist');
- });
- });
-
- context('Your data page', () => {
- beforeEach(() => {
- setAuthCookies();
- cy.mockAll(
- 200,
- authRedirectSignInRecentlyEmailValidated,
- AUTH_REDIRECT_ENDPOINT,
- );
- cy.mockAll(200, allConsents, CONSENTS_ENDPOINT);
- cy.mockAll(
- 200,
- verifiedUserWithNoConsent.user.consents,
- USER_CONSENTS_ENDPOINT,
- );
- });
-
- it('has no detectable a11y violations', () => {
- YourDataPage.goto({
- query: {
- useIdapi: true,
- },
- });
- injectAndCheckAxe();
- });
-
- it('had no detectable a11y voilations if previously selected consent', () => {
- cy.mockAll(200, optedOutUserConsent, USER_CONSENTS_ENDPOINT);
- YourDataPage.goto({
- query: {
- useIdapi: true,
- },
- });
- injectAndCheckAxe();
- });
-
- it('has no detectable a11y violations on with an error', () => {
- cy.mockAll(500, {}, CONSENTS_ENDPOINT);
- YourDataPage.goto({
- query: {
- useIdapi: true,
- },
- });
- injectAndCheckAxe();
- });
-
- it('displays the marketing profile opt in switch, toggled ON by default', () => {
- YourDataPage.goto({
- query: {
- useIdapi: true,
- },
- });
- YourDataPage.marketingOptInSwitch().should('be.checked');
- });
-
- it('displays the marketing profile opt in switch, toggled OFF if the user has previously opted out', () => {
- cy.mockAll(200, optedOutUserConsent, USER_CONSENTS_ENDPOINT);
- YourDataPage.goto({
- query: {
- useIdapi: true,
- },
- });
- YourDataPage.marketingOptInSwitch().should('not.be.checked');
- });
-
- it('displays the personalised advertising permission if user has all CMP consents, toggled OFF by default', () => {
- cy.enableCMP();
- YourDataPage.goto({
- query: {
- useIdapi: true,
- },
- });
- cy.acceptCMP();
-
- YourDataPage.marketingOptInSwitch().should('be.checked');
- YourDataPage.personalisedAdvertisingOptInInput().should('not.be.checked');
- });
-
- it('displays the personalised advertising permission if user has all CMP consents, toggled ON if user previously opted in', () => {
- cy.enableCMP();
- cy.mockAll(
- 200,
- optedIntoPersonalisedAdvertisingUserConsent,
- USER_CONSENTS_ENDPOINT,
- );
- YourDataPage.goto({
- query: {
- useIdapi: true,
- },
- });
- cy.acceptCMP();
-
- YourDataPage.marketingOptInSwitch().should('be.checked');
- YourDataPage.personalisedAdvertisingOptInInput().should('be.checked');
- });
-
- it('does not display the personalised advertising permission if user does not have CMP consents set', () => {
- YourDataPage.goto({
- query: {
- useIdapi: true,
- },
- });
- YourDataPage.personalisedAdvertisingOptIn().should('not.exist');
- });
-
- it('does not display the personalised advertising permission if user has not accepted CMP consents', () => {
- cy.enableCMP();
- YourDataPage.goto({
- query: {
- useIdapi: true,
- },
- });
- cy.declineCMP();
-
- YourDataPage.personalisedAdvertisingOptIn().should('not.exist');
- });
-
- it('does not display the personalised advertising permission if user has all CMP consents, but has an ad free gu cookie', () => {
- cy.enableCMP();
- cy.setAdFreeCookie();
- YourDataPage.goto({
- query: {
- useIdapi: true,
- },
- });
- cy.acceptCMP();
-
- YourDataPage.personalisedAdvertisingOptIn().should('not.exist');
- });
-
- it('display a relevant error message on user end point failure', () => {
- cy.mockAll(500, {}, USER_CONSENTS_ENDPOINT);
- YourDataPage.goto({
- query: {
- useIdapi: true,
- },
- });
- YourDataPage.errorBanner().contains(CONSENT_ERRORS.GENERIC);
- YourDataPage.backButton().should('not.exist');
- YourDataPage.saveAndContinueButton().should('not.exist');
- });
-
- it('displays a relevant error on consents endpoint failure', () => {
- cy.mockAll(500, {}, CONSENTS_ENDPOINT);
- YourDataPage.goto({
- query: {
- useIdapi: true,
- },
- });
- YourDataPage.errorBanner().contains(CONSENT_ERRORS.GENERIC);
- YourDataPage.backButton().should('not.exist');
- YourDataPage.saveAndContinueButton().should('not.exist');
- });
- });
-
- context('Review page', () => {
- beforeEach(() => {
- setAuthCookies();
- cy.mockAll(
- 200,
- authRedirectSignInRecentlyEmailValidated,
- AUTH_REDIRECT_ENDPOINT,
- );
- cy.mockAll(200, allConsents, CONSENTS_ENDPOINT);
- cy.mockAll(
- 200,
- verifiedUserWithNoConsent.user.consents,
- USER_CONSENTS_ENDPOINT,
- );
- cy.mockAll(200, allNewsletters, NEWSLETTER_ENDPOINT);
- cy.mockAll(200, userNewsletters(), NEWSLETTER_SUBSCRIPTION_ENDPOINT);
- });
-
- it('has no detectable a11y violations', () => {
- ReviewPage.goto({
- query: {
- useIdapi: true,
- },
- });
- injectAndCheckAxe();
- });
-
- it('has no detectable a11y violations on with an error', () => {
- cy.mockAll(500, {}, CONSENTS_ENDPOINT);
- ReviewPage.goto({
- query: {
- useIdapi: true,
- },
- });
- injectAndCheckAxe();
- });
-
- it('displays a relevant error if on consents endpoint failure', () => {
- cy.mockAll(500, {}, CONSENTS_ENDPOINT);
- ReviewPage.goto({
- query: {
- useIdapi: true,
- },
- });
- ReviewPage.errorBanner().contains(CONSENT_ERRORS.GENERIC);
- });
-
- it('display a relevant error message on user end point failure', () => {
- cy.mockAll(500, {}, USER_CONSENTS_ENDPOINT);
- ReviewPage.goto({
- query: {
- useIdapi: true,
- },
- });
- ReviewPage.errorBanner().contains(CONSENT_ERRORS.GENERIC);
- });
-
- it('displays a relevant error on newsletters endpoint failure', () => {
- cy.mockAll(500, {}, NEWSLETTER_ENDPOINT);
- ReviewPage.goto({
- query: {
- useIdapi: true,
- },
- });
- ReviewPage.errorBanner().contains(NEWSLETTER_ERRORS.GENERIC);
- });
-
- it('displays a relevant error on newsletters subscription endpoint failure', () => {
- cy.mockAll(500, {}, NEWSLETTER_SUBSCRIPTION_ENDPOINT);
- ReviewPage.goto({
- query: {
- useIdapi: true,
- },
- });
- ReviewPage.errorBanner().contains(NEWSLETTER_ERRORS.GENERIC);
- });
- });
-
- context('Not found', () => {
- beforeEach(() => {
- setAuthCookies();
- cy.mockAll(
- 200,
- authRedirectSignInRecentlyEmailValidated,
- AUTH_REDIRECT_ENDPOINT,
- );
- });
-
- it('shows 404 page if onboarding page is not found', () => {
- cy.visit('/consents/unknown', {
- failOnStatusCode: false,
- qs: { useIdapi: true },
- });
- cy.contains('the page does not exist');
- });
- });
+ YourDataPage.marketingOptInSwitch().should('be.checked');
+ YourDataPage.marketingOptInClickableSection().click();
+ YourDataPage.marketingOptInSwitch().should('not.be.checked');
+ YourDataPage.personalisedAdvertisingOptInSwitch().should('exist');
+ YourDataPage.personalisedAdvertisingOptInInput().should('not.be.checked');
+
+ // mock form save success
+ cy.mockNext(200);
+
+ cy.mockAll(200, createUser(optedOutUserConsent), USER_ENDPOINT);
+ cy.mockAll(200, optedOutUserConsent, USER_CONSENTS_ENDPOINT);
+
+ YourDataPage.saveAndContinueButton().click();
+ // Explicity check '_optin' consents are in inverted back to '_optouts' when posted
+ cy.lastPayloadIs([
+ { id: 'profiling_optout', consented: true },
+ { id: 'personalised_advertising', consented: false },
+ ]);
+
+ cy.url().should('include', ReviewPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
+
+ ReviewPage.backButton().should('not.exist');
+ ReviewPage.saveAndContinueButton().should('not.exist');
+
+ // contains no opted in newsletters
+ Object.values(ReviewPage.CONTENT.NEWSLETTERS).forEach((newsletter) =>
+ cy.contains(newsletter).should('not.exist'),
+ );
+
+ // contains no consents
+ cy.contains(ReviewPage.CONTENT.SUPPORTER_CONSENT).should('not.exist');
+ cy.contains(ReviewPage.CONTENT.PROFILING_CONSENT).should('not.exist');
+ cy.contains(ReviewPage.CONTENT.PERSONALISED_ADVERTISING_CONSENT).should(
+ 'not.exist',
+ );
+
+ // contains messaging encouraging user to explore other newsletters
+ cy.contains(ReviewPage.CONTENT.NO_NEWSLETTERS_TITLE);
+
+ ReviewPage.returnButton()
+ .should('have.attr', 'href')
+ .and('include', decodeURIComponent(returnUrl));
+ });
+
+ it('uses a default returnUrl if none provided', () => {
+ const returnUrl = encodeURIComponent(Cypress.env('DEFAULT_RETURN_URI'));
+
+ CommunicationsPage.gotoFlowStart({
+ query: {
+ useIdapi: 'true',
+ },
+ });
+
+ cy.url().should('include', CommunicationsPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
+
+ // mock form save success
+ cy.mockNext(200);
+
+ CommunicationsPage.saveAndContinueButton().click();
+
+ cy.url().should('include', NewslettersPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
+
+ // mock form save success
+ cy.mockNext(200);
+
+ NewslettersPage.saveAndContinueButton().click();
+
+ cy.url().should('include', YourDataPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
+
+ YourDataPage.marketingOptInClickableSection().click();
+
+ // mock form save success
+ cy.mockNext(200);
+
+ YourDataPage.saveAndContinueButton().click();
+ cy.url().should('include', ReviewPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
+
+ ReviewPage.returnButton()
+ .should('have.attr', 'href')
+ .and('include', decodeURIComponent(returnUrl));
+ });
+ });
+
+ context('Login middleware', () => {
+ it('no sc_gu_u cookie, redirect to login page', () => {
+ const signInUrl = Cypress.env('SIGN_IN_PAGE_URL');
+ cy.setCookie('GU_U', 'FAKE_GU_U');
+ cy.setCookie('SC_GU_LA', 'FAKE_SC_GU_LA');
+
+ cy.request({
+ url: `${Onboarding.URL}?useIdapi=true`,
+ followRedirect: false,
+ }).then((res) => {
+ expect(res.status).to.eq(303);
+ expect(res.redirectedToUrl).to.include(signInUrl);
+ });
+ });
+
+ it('no sc_gu_la cookie, redirect to login page', () => {
+ const signInUrl = Cypress.env('SIGN_IN_PAGE_URL');
+ cy.setCookie('GU_U', 'FAKE_GU_U');
+ cy.setCookie('SC_GU_U', 'FAKE_SC_GU_U');
+
+ cy.request({
+ url: `${Onboarding.URL}?useIdapi=true`,
+ followRedirect: false,
+ }).then((res) => {
+ expect(res.status).to.eq(303);
+ expect(res.redirectedToUrl).to.include(signInUrl);
+ });
+ });
+
+ it('email not validated, go to verify email page', () => {
+ setAuthCookies();
+ const emailNotValidatedResponse = {
+ signInStatus: 'signedInRecently',
+ emailValidated: false,
+ redirect: null,
+ };
+ cy.mockAll(200, emailNotValidatedResponse, AUTH_REDIRECT_ENDPOINT);
+
+ cy.request({
+ url: `${Onboarding.URL}?useIdapi=true`,
+ followRedirect: false,
+ }).then((res) => {
+ expect(res.status).to.eq(303);
+ expect(res.redirectedToUrl).to.include(VerifyEmail.URL);
+ });
+ });
+
+ it('recently logged in, go to consents flow', () => {
+ setAuthCookies();
+ cy.mockAll(
+ 200,
+ authRedirectSignInRecentlyEmailValidated,
+ AUTH_REDIRECT_ENDPOINT,
+ );
+ cy.request({
+ url: `${Onboarding.URL}?useIdapi=true`,
+ followRedirect: false,
+ }).then((res) => {
+ expect(res.status).to.eq(303);
+ expect(res.redirectedToUrl).to.include(CommunicationsPage.URL);
+ });
+ });
+
+ it('not recently logged in, follows supplied redirect', () => {
+ setAuthCookies();
+ const emailNotValidatedResponse = {
+ signInStatus: 'signedInNotRecently',
+ emailValidated: true,
+ redirect: {
+ url: 'https://fakeloginfortest.code.dev-theguardian.co.uk',
+ },
+ };
+ cy.mockAll(200, emailNotValidatedResponse, AUTH_REDIRECT_ENDPOINT);
+
+ cy.request({
+ url: `${Onboarding.URL}?useIdapi=true`,
+ followRedirect: false,
+ }).then((res) => {
+ expect(res.status).to.eq(303);
+ expect(res.redirectedToUrl).to.include(
+ 'https://fakeloginfortest.code.dev-theguardian.co.uk',
+ );
+ });
+ });
+
+ it('if missing redirect information, it redirects to the default ', () => {
+ const signInUrl = Cypress.env('SIGN_IN_PAGE_URL');
+ setAuthCookies();
+ const emailNotValidatedResponse = {
+ signInStatus: 'signedInNotRecently',
+ emailValidated: true,
+ redirect: undefined,
+ };
+
+ cy.mockAll(200, emailNotValidatedResponse, AUTH_REDIRECT_ENDPOINT);
+
+ cy.request({
+ url: `${Onboarding.URL}?useIdapi=true`,
+ followRedirect: false,
+ }).then((res) => {
+ expect(res.status).to.eq(303);
+ expect(res.redirectedToUrl).to.include(signInUrl);
+ });
+ });
+
+ it('on idapi error it redirects to the sign in page with the error flag set', () => {
+ setAuthCookies();
+ cy.mockAll(502, 'gateway error', AUTH_REDIRECT_ENDPOINT);
+ cy.request({
+ url: `${Onboarding.URL}?useIdapi=true`,
+ followRedirect: false,
+ }).then((res) => {
+ expect(res.status).to.eq(303);
+ expect(res.redirectedToUrl).to.include(
+ `error=signin-error-bad-request`,
+ );
+ });
+ });
+ });
+
+ context('Contact options page', () => {
+ beforeEach(() => {
+ setAuthCookies();
+ cy.mockAll(
+ 200,
+ authRedirectSignInRecentlyEmailValidated,
+ AUTH_REDIRECT_ENDPOINT,
+ );
+ cy.mockAll(200, allConsents, CONSENTS_ENDPOINT);
+ });
+
+ it('has no detectable a11y violations', () => {
+ cy.mockAll(
+ 200,
+ verifiedUserWithNoConsent.user.consents,
+ USER_CONSENTS_ENDPOINT,
+ );
+ CommunicationsPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ injectAndCheckAxe();
+ });
+
+ it('had no detectable a11y voilations if previously selected consents', () => {
+ const consented = getUserConsents(['jobs', 'offers']);
+ cy.mockAll(200, consented, USER_CONSENTS_ENDPOINT);
+ CommunicationsPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ injectAndCheckAxe();
+ });
+
+ it('has no detectable a11y violations on with an error', () => {
+ cy.mockAll(500, {}, USER_ENDPOINT);
+ CommunicationsPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ injectAndCheckAxe();
+ });
+
+ it('shows correct contact options, none checked by default', () => {
+ cy.mockAll(
+ 200,
+ verifiedUserWithNoConsent.user.consents,
+ USER_CONSENTS_ENDPOINT,
+ );
+ CommunicationsPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ CommunicationsPage.backButton().should('not.exist');
+ CommunicationsPage.allCheckboxes().should('not.be.checked');
+ });
+
+ it('shows any previously selected consents', () => {
+ const consented = getUserConsents(['supporter']);
+ cy.mockAll(200, consented, USER_CONSENTS_ENDPOINT);
+ CommunicationsPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ CommunicationsPage.backButton().should('not.exist');
+ CommunicationsPage.consentCheckboxWithTitle(
+ 'Supporting the Guardian',
+ ).should('be.checked');
+ });
+
+ it('displays a relevant error message on user end point failure', () => {
+ cy.mockAll(500, {}, USER_CONSENTS_ENDPOINT);
+ CommunicationsPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ CommunicationsPage.errorBanner().contains(CONSENT_ERRORS.GENERIC);
+ CommunicationsPage.backButton().should('not.exist');
+ CommunicationsPage.saveAndContinueButton().should('not.exist');
+ });
+
+ it('displays a relevant error on consents endpoint failure', () => {
+ cy.mockAll(500, {}, CONSENTS_ENDPOINT);
+ CommunicationsPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ CommunicationsPage.errorBanner().contains(CONSENT_ERRORS.GENERIC);
+ CommunicationsPage.backButton().should('not.exist');
+ CommunicationsPage.saveAndContinueButton().should('not.exist');
+ });
+ });
+
+ context('Newsletters page', () => {
+ beforeEach(() => {
+ setAuthCookies();
+ cy.mockAll(
+ 200,
+ authRedirectSignInRecentlyEmailValidated,
+ AUTH_REDIRECT_ENDPOINT,
+ );
+ cy.mockAll(200, allNewsletters, NEWSLETTER_ENDPOINT);
+ cy.mockAll(200, userNewsletters(), NEWSLETTER_SUBSCRIPTION_ENDPOINT);
+ cy.mockAll(200, allConsents, CONSENTS_ENDPOINT);
+ cy.mockAll(
+ 200,
+ verifiedUserWithNoConsent.user.consents,
+ USER_CONSENTS_ENDPOINT,
+ );
+ });
+
+ it('has no detectable a11y violations', () => {
+ const headers = getGeoLocationHeaders(GEOLOCATION_CODES.GB);
+
+ cy.visit(NewslettersPage.URL, { headers, qs: { useIdapi: 'true' } });
+ injectAndCheckAxe();
+ });
+
+ it('had no detectable a11y voilations if previously selected newsletter', () => {
+ const newslettersToSubscribe = [{ listId: 4147 }, { listId: 4165 }];
+ cy.mockAll(
+ 200,
+ userNewsletters(newslettersToSubscribe),
+ NEWSLETTER_SUBSCRIPTION_ENDPOINT,
+ );
+ NewslettersPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ injectAndCheckAxe();
+ });
+
+ it('has no detectable a11y violations on with an error', () => {
+ cy.mockAll(500, {}, NEWSLETTER_ENDPOINT);
+ NewslettersPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ injectAndCheckAxe();
+ });
+
+ it('correct newsletters shown for uk, none checked by default', () => {
+ const headers = getGeoLocationHeaders(GEOLOCATION_CODES.GB);
+
+ cy.visit(NewslettersPage.URL, { headers, qs: { useIdapi: 'true' } });
+
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.FIRST_EDITION_UK).should(
+ 'not.be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.LONG_READ).should(
+ 'not.be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.GREEN_LIGHT).should(
+ 'not.be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(
+ NewslettersPage.CONTENT.Consents.EVENTS,
+ ).should('not.be.checked');
+
+ CommunicationsPage.backButton().should('exist');
+ CommunicationsPage.saveAndContinueButton().should('exist');
+ });
+
+ it('correct newsletters shown for United States of America, none checked by default', () => {
+ const headers = getGeoLocationHeaders(GEOLOCATION_CODES.AMERICA);
+
+ cy.visit(NewslettersPage.URL, { headers, qs: { useIdapi: 'true' } });
+
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.FIRST_THING_US).should(
+ 'not.be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.LONG_READ).should(
+ 'not.be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.GREEN_LIGHT).should(
+ 'not.be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(
+ NewslettersPage.CONTENT.Consents.EVENTS,
+ ).should('not.be.checked');
+
+ CommunicationsPage.backButton().should('exist');
+ CommunicationsPage.saveAndContinueButton().should('exist');
+ });
+
+ it('correct newsletters shown for permissioned United States browser, none checked by default', () => {
+ const headers = getGeoLocationHeaders(GEOLOCATION_CODES.AMERICA);
+ cy.setEncryptedStateCookie({
+ isCmpConsented: true,
+ });
+
+ cy.visit(NewslettersPage.URL, { headers, qs: { useIdapi: 'true' } });
+
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.FIRST_THING_US).should(
+ 'not.be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.HEADLINES_US).should(
+ 'not.be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.GREEN_LIGHT).should(
+ 'not.be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.OPINION_US).should(
+ 'not.be.checked',
+ );
+
+ cy.contains(NewslettersPage.CONTENT.Consents.EVENTS).should('not.exist');
+
+ CommunicationsPage.backButton().should('exist');
+ CommunicationsPage.saveAndContinueButton().should('exist');
+ });
+
+ it('correct newsletters shown for Australia, none checked by default', () => {
+ const headers = getGeoLocationHeaders(GEOLOCATION_CODES.AUSTRALIA);
+
+ cy.visit(NewslettersPage.URL, { headers, qs: { useIdapi: 'true' } });
+
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.MORNING_MAIL_AU).should(
+ 'not.be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.LONG_READ).should(
+ 'not.be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.GREEN_LIGHT).should(
+ 'not.be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(
+ NewslettersPage.CONTENT.Consents.EVENTS,
+ ).should('not.be.checked');
+
+ CommunicationsPage.backButton().should('exist');
+ CommunicationsPage.saveAndContinueButton().should('exist');
+ });
+
+ it('correct localised newsletters shown for permissioned Australian browser, none checked by default', () => {
+ const headers = getGeoLocationHeaders(GEOLOCATION_CODES.AUSTRALIA);
+
+ cy.setEncryptedStateCookie({
+ isCmpConsented: true,
+ });
+ cy.visit(NewslettersPage.URL, { headers, qs: { useIdapi: 'true' } });
+
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.MORNING_MAIL_AU).should(
+ 'not.be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.AFTERNOON_UPDATE_AU).should(
+ 'not.be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.FIVE_GREAT_READS_AU).should(
+ 'not.be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.SAVED_FOR_LATER_AU).should(
+ 'not.be.checked',
+ );
+ cy.contains(NewslettersPage.CONTENT.Consents.EVENTS).should('not.exist');
+
+ CommunicationsPage.backButton().should('exist');
+ CommunicationsPage.saveAndContinueButton().should('exist');
+ });
+
+ it('correct newsletters shown for rest of the world, none checked by default', () => {
+ const headers = getGeoLocationHeaders(GEOLOCATION_CODES.OTHERS);
+
+ cy.visit(NewslettersPage.URL, { headers, qs: { useIdapi: 'true' } });
+
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.FIRST_EDITION_UK).should(
+ 'not.be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.LONG_READ).should(
+ 'not.be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.GREEN_LIGHT).should(
+ 'not.be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(
+ NewslettersPage.CONTENT.Consents.EVENTS,
+ ).should('not.be.checked');
+
+ CommunicationsPage.backButton().should('exist');
+ CommunicationsPage.saveAndContinueButton().should('exist');
+ });
+
+ it('show already selected newsletters / consents', () => {
+ const newslettersToSubscribe = [{ listId: 4147 }, { listId: 4165 }];
+ cy.mockAll(
+ 200,
+ userNewsletters(newslettersToSubscribe),
+ NEWSLETTER_SUBSCRIPTION_ENDPOINT,
+ );
+ const consented = getUserConsents(['events']);
+ cy.mockAll(200, consented, USER_CONSENTS_ENDPOINT);
+ NewslettersPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.FIRST_EDITION_UK).should(
+ 'not.be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.LONG_READ).should(
+ 'be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(NEWSLETTERS.GREEN_LIGHT).should(
+ 'be.checked',
+ );
+ NewslettersPage.checkboxWithTitle(
+ NewslettersPage.CONTENT.Consents.EVENTS,
+ ).should('be.checked');
+ });
+
+ it('displays a relevant error on newsletters endpoint failure', () => {
+ cy.mockAll(500, {}, NEWSLETTER_ENDPOINT);
+ NewslettersPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ NewslettersPage.errorBanner().contains(NEWSLETTER_ERRORS.GENERIC);
+ NewslettersPage.backButton().should('not.exist');
+ NewslettersPage.saveAndContinueButton().should('not.exist');
+ });
+
+ it('displays a relevant error on newsletters subscription endpoint failure', () => {
+ cy.mockAll(500, {}, NEWSLETTER_SUBSCRIPTION_ENDPOINT);
+ NewslettersPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ NewslettersPage.errorBanner().contains(NEWSLETTER_ERRORS.GENERIC);
+ NewslettersPage.backButton().should('not.exist');
+ NewslettersPage.saveAndContinueButton().should('not.exist');
+ });
+ });
+
+ context('Your data page', () => {
+ beforeEach(() => {
+ setAuthCookies();
+ cy.mockAll(
+ 200,
+ authRedirectSignInRecentlyEmailValidated,
+ AUTH_REDIRECT_ENDPOINT,
+ );
+ cy.mockAll(200, allConsents, CONSENTS_ENDPOINT);
+ cy.mockAll(
+ 200,
+ verifiedUserWithNoConsent.user.consents,
+ USER_CONSENTS_ENDPOINT,
+ );
+ });
+
+ it('has no detectable a11y violations', () => {
+ YourDataPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ injectAndCheckAxe();
+ });
+
+ it('had no detectable a11y voilations if previously selected consent', () => {
+ cy.mockAll(200, optedOutUserConsent, USER_CONSENTS_ENDPOINT);
+ YourDataPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ injectAndCheckAxe();
+ });
+
+ it('has no detectable a11y violations on with an error', () => {
+ cy.mockAll(500, {}, CONSENTS_ENDPOINT);
+ YourDataPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ injectAndCheckAxe();
+ });
+
+ it('displays the marketing profile opt in switch, toggled ON by default', () => {
+ YourDataPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ YourDataPage.marketingOptInSwitch().should('be.checked');
+ });
+
+ it('displays the marketing profile opt in switch, toggled OFF if the user has previously opted out', () => {
+ cy.mockAll(200, optedOutUserConsent, USER_CONSENTS_ENDPOINT);
+ YourDataPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ YourDataPage.marketingOptInSwitch().should('not.be.checked');
+ });
+
+ it('displays the personalised advertising permission if user has all CMP consents, toggled OFF by default', () => {
+ cy.enableCMP();
+ YourDataPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ cy.acceptCMP();
+
+ YourDataPage.marketingOptInSwitch().should('be.checked');
+ YourDataPage.personalisedAdvertisingOptInInput().should('not.be.checked');
+ });
+
+ it('displays the personalised advertising permission if user has all CMP consents, toggled ON if user previously opted in', () => {
+ cy.enableCMP();
+ cy.mockAll(
+ 200,
+ optedIntoPersonalisedAdvertisingUserConsent,
+ USER_CONSENTS_ENDPOINT,
+ );
+ YourDataPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ cy.acceptCMP();
+
+ YourDataPage.marketingOptInSwitch().should('be.checked');
+ YourDataPage.personalisedAdvertisingOptInInput().should('be.checked');
+ });
+
+ it('does not display the personalised advertising permission if user does not have CMP consents set', () => {
+ YourDataPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ YourDataPage.personalisedAdvertisingOptIn().should('not.exist');
+ });
+
+ it('does not display the personalised advertising permission if user has not accepted CMP consents', () => {
+ cy.enableCMP();
+ YourDataPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ cy.declineCMP();
+
+ YourDataPage.personalisedAdvertisingOptIn().should('not.exist');
+ });
+
+ it('does not display the personalised advertising permission if user has all CMP consents, but has an ad free gu cookie', () => {
+ cy.enableCMP();
+ cy.setAdFreeCookie();
+ YourDataPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ cy.acceptCMP();
+
+ YourDataPage.personalisedAdvertisingOptIn().should('not.exist');
+ });
+
+ it('display a relevant error message on user end point failure', () => {
+ cy.mockAll(500, {}, USER_CONSENTS_ENDPOINT);
+ YourDataPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ YourDataPage.errorBanner().contains(CONSENT_ERRORS.GENERIC);
+ YourDataPage.backButton().should('not.exist');
+ YourDataPage.saveAndContinueButton().should('not.exist');
+ });
+
+ it('displays a relevant error on consents endpoint failure', () => {
+ cy.mockAll(500, {}, CONSENTS_ENDPOINT);
+ YourDataPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ YourDataPage.errorBanner().contains(CONSENT_ERRORS.GENERIC);
+ YourDataPage.backButton().should('not.exist');
+ YourDataPage.saveAndContinueButton().should('not.exist');
+ });
+ });
+
+ context('Review page', () => {
+ beforeEach(() => {
+ setAuthCookies();
+ cy.mockAll(
+ 200,
+ authRedirectSignInRecentlyEmailValidated,
+ AUTH_REDIRECT_ENDPOINT,
+ );
+ cy.mockAll(200, allConsents, CONSENTS_ENDPOINT);
+ cy.mockAll(
+ 200,
+ verifiedUserWithNoConsent.user.consents,
+ USER_CONSENTS_ENDPOINT,
+ );
+ cy.mockAll(200, allNewsletters, NEWSLETTER_ENDPOINT);
+ cy.mockAll(200, userNewsletters(), NEWSLETTER_SUBSCRIPTION_ENDPOINT);
+ });
+
+ it('has no detectable a11y violations', () => {
+ ReviewPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ injectAndCheckAxe();
+ });
+
+ it('has no detectable a11y violations on with an error', () => {
+ cy.mockAll(500, {}, CONSENTS_ENDPOINT);
+ ReviewPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ injectAndCheckAxe();
+ });
+
+ it('displays a relevant error if on consents endpoint failure', () => {
+ cy.mockAll(500, {}, CONSENTS_ENDPOINT);
+ ReviewPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ ReviewPage.errorBanner().contains(CONSENT_ERRORS.GENERIC);
+ });
+
+ it('display a relevant error message on user end point failure', () => {
+ cy.mockAll(500, {}, USER_CONSENTS_ENDPOINT);
+ ReviewPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ ReviewPage.errorBanner().contains(CONSENT_ERRORS.GENERIC);
+ });
+
+ it('displays a relevant error on newsletters endpoint failure', () => {
+ cy.mockAll(500, {}, NEWSLETTER_ENDPOINT);
+ ReviewPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ ReviewPage.errorBanner().contains(NEWSLETTER_ERRORS.GENERIC);
+ });
+
+ it('displays a relevant error on newsletters subscription endpoint failure', () => {
+ cy.mockAll(500, {}, NEWSLETTER_SUBSCRIPTION_ENDPOINT);
+ ReviewPage.goto({
+ query: {
+ useIdapi: true,
+ },
+ });
+ ReviewPage.errorBanner().contains(NEWSLETTER_ERRORS.GENERIC);
+ });
+ });
+
+ context('Not found', () => {
+ beforeEach(() => {
+ setAuthCookies();
+ cy.mockAll(
+ 200,
+ authRedirectSignInRecentlyEmailValidated,
+ AUTH_REDIRECT_ENDPOINT,
+ );
+ });
+
+ it('shows 404 page if onboarding page is not found', () => {
+ cy.visit('/consents/unknown', {
+ failOnStatusCode: false,
+ qs: { useIdapi: true },
+ });
+ cy.contains('the page does not exist');
+ });
+ });
});
diff --git a/cypress/integration/mocked/post_sign_in_prompt.3.cy.ts b/cypress/integration/mocked/post_sign_in_prompt.3.cy.ts
index c1b9fc2114..c35d683503 100644
--- a/cypress/integration/mocked/post_sign_in_prompt.3.cy.ts
+++ b/cypress/integration/mocked/post_sign_in_prompt.3.cy.ts
@@ -1,12 +1,12 @@
import {
- authRedirectSignInRecentlyEmailValidated,
- AUTH_REDIRECT_ENDPOINT,
+ authRedirectSignInRecentlyEmailValidated,
+ AUTH_REDIRECT_ENDPOINT,
} from '../../support/idapi/auth';
import { allConsents, CONSENTS_ENDPOINT } from '../../support/idapi/consent';
import {
- verifiedUserWithNoConsent,
- createUser,
- USER_ENDPOINT,
+ verifiedUserWithNoConsent,
+ createUser,
+ USER_ENDPOINT,
} from '../../support/idapi/user';
import { setAuthCookies } from '../../support/idapi/cookie';
import { injectAndCheckAxe } from '../../support/cypress-axe';
@@ -14,129 +14,129 @@ import { injectAndCheckAxe } from '../../support/cypress-axe';
// TODO: remove this once we have migrated fully to OAuth as we're unable to mock the OAuth flow to get Tokens
// TODO: best thing to do will move as much as possible to the ete tests
describe('Post sign-in prompt', () => {
- const defaultReturnUrl = 'https://m.code.dev-theguardian.com';
- const returnUrl = 'https://www.theguardian.com/about';
-
- beforeEach(() => {
- cy.mockPurge();
- setAuthCookies();
- cy.mockAll(
- 200,
- authRedirectSignInRecentlyEmailValidated,
- AUTH_REDIRECT_ENDPOINT,
- );
- cy.mockAll(200, allConsents, CONSENTS_ENDPOINT);
- cy.intercept('GET', defaultReturnUrl, (req) => {
- req.reply(200);
- });
- cy.intercept('GET', returnUrl, (req) => {
- req.reply(200);
- });
- });
-
- it('has no detectable a11y violations on prompt page', () => {
- cy.mockNext(200, verifiedUserWithNoConsent.user.consents);
- cy.visit('/signin/success?useIdapi=true');
- injectAndCheckAxe();
- });
-
- it('allows user to opt in and continue', () => {
- cy.mockNext(200, verifiedUserWithNoConsent.user.consents);
- cy.visit('/signin/success?useIdapi=true');
- const checkbox = cy.findByLabelText('Yes, sign me up');
- checkbox.should('not.be.checked');
- checkbox.click();
-
- // mock form save success
- cy.mockNext(200, {});
-
- cy.findByText('Continue to the Guardian').click();
- cy.lastPayloadIs([{ id: 'supporter', consented: true }]);
- cy.url().should('include', defaultReturnUrl);
- });
-
- it('allows user to opt out and continue', () => {
- const supporterConsent = allConsents.find(({ id }) => id === 'supporter');
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- const consentData = [{ ...supporterConsent!, consented: true }];
- cy.mockAll(200, createUser(consentData), USER_ENDPOINT);
- cy.mockNext(200, consentData);
- cy.visit('/signin/success?useIdapi=true');
- const checkbox = cy.findByLabelText('Yes, sign me up');
- checkbox.should('be.checked');
- checkbox.click();
-
- // mock form save success
- cy.mockNext(200, {});
-
- cy.findByText('Continue to the Guardian').click();
- cy.lastPayloadIs([{ id: 'supporter', consented: false }]);
- cy.url().should('include', defaultReturnUrl);
- });
-
- it('allows user to continue to different returnUrl', () => {
- cy.mockNext(200, verifiedUserWithNoConsent.user.consents);
- cy.visit(
- `/signin/success?returnUrl=${encodeURIComponent(
- returnUrl,
- )}&useIdapi=true`,
- );
-
- // mock form save success
- cy.mockNext(200, {});
-
- cy.findByText('Continue to the Guardian').click();
- cy.lastPayloadIs([{ id: 'supporter', consented: false }]);
- cy.url().should('include', returnUrl);
- });
-
- it('fails silently if submit fails, but user did not consent', () => {
- cy.mockNext(200, verifiedUserWithNoConsent.user.consents);
- cy.mockNext(500, {});
- cy.visit('/signin/success?useIdapi=true');
-
- cy.findByText('Continue to the Guardian').click();
- cy.lastPayloadIs([{ id: 'supporter', consented: false }]);
- cy.url().should('include', defaultReturnUrl);
- });
-
- it('shows error if submit fails and user did consent', () => {
- cy.mockNext(200, verifiedUserWithNoConsent.user.consents);
- cy.visit('/signin/success?useIdapi=true');
- cy.findByLabelText('Yes, sign me up').click();
-
- cy.mockNext(500, undefined);
- cy.mockNext(200, verifiedUserWithNoConsent.user.consents);
- cy.findByText('Continue to the Guardian').click();
- cy.lastPayloadIs([{ id: 'supporter', consented: true }]);
- cy.url().should('include', '/signin/success');
- cy.findByText(
- 'There was a problem saving your choice, please try again.',
- ).should('exist');
- });
-
- it('redirects to returnUrl if fetching consents fails', () => {
- cy.mockNext(500, {});
- /**
- * Using cy.request instead of cy.visit as we only need to test the redirect
- * and cy.intercept does not seem to work here
- */
- cy.request({
- url: '/signin/success?useIdapi=true',
- followRedirect: false,
- }).then((response) =>
- expect(response.redirectedToUrl).to.contain(defaultReturnUrl),
- );
- });
-
- it('redirects to returnUrl if fetching user consents fails', () => {
- cy.mockNext(500, undefined);
- // Using cy.request instead of cy.visit, see above for reasoning.
- cy.request({
- url: '/signin/success?useIdapi=true',
- followRedirect: false,
- }).then((response) =>
- expect(response.redirectedToUrl).to.contain(defaultReturnUrl),
- );
- });
+ const defaultReturnUrl = 'https://m.code.dev-theguardian.com';
+ const returnUrl = 'https://www.theguardian.com/about';
+
+ beforeEach(() => {
+ cy.mockPurge();
+ setAuthCookies();
+ cy.mockAll(
+ 200,
+ authRedirectSignInRecentlyEmailValidated,
+ AUTH_REDIRECT_ENDPOINT,
+ );
+ cy.mockAll(200, allConsents, CONSENTS_ENDPOINT);
+ cy.intercept('GET', defaultReturnUrl, (req) => {
+ req.reply(200);
+ });
+ cy.intercept('GET', returnUrl, (req) => {
+ req.reply(200);
+ });
+ });
+
+ it('has no detectable a11y violations on prompt page', () => {
+ cy.mockNext(200, verifiedUserWithNoConsent.user.consents);
+ cy.visit('/signin/success?useIdapi=true');
+ injectAndCheckAxe();
+ });
+
+ it('allows user to opt in and continue', () => {
+ cy.mockNext(200, verifiedUserWithNoConsent.user.consents);
+ cy.visit('/signin/success?useIdapi=true');
+ const checkbox = cy.findByLabelText('Yes, sign me up');
+ checkbox.should('not.be.checked');
+ checkbox.click();
+
+ // mock form save success
+ cy.mockNext(200, {});
+
+ cy.findByText('Continue to the Guardian').click();
+ cy.lastPayloadIs([{ id: 'supporter', consented: true }]);
+ cy.url().should('include', defaultReturnUrl);
+ });
+
+ it('allows user to opt out and continue', () => {
+ const supporterConsent = allConsents.find(({ id }) => id === 'supporter');
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const consentData = [{ ...supporterConsent!, consented: true }];
+ cy.mockAll(200, createUser(consentData), USER_ENDPOINT);
+ cy.mockNext(200, consentData);
+ cy.visit('/signin/success?useIdapi=true');
+ const checkbox = cy.findByLabelText('Yes, sign me up');
+ checkbox.should('be.checked');
+ checkbox.click();
+
+ // mock form save success
+ cy.mockNext(200, {});
+
+ cy.findByText('Continue to the Guardian').click();
+ cy.lastPayloadIs([{ id: 'supporter', consented: false }]);
+ cy.url().should('include', defaultReturnUrl);
+ });
+
+ it('allows user to continue to different returnUrl', () => {
+ cy.mockNext(200, verifiedUserWithNoConsent.user.consents);
+ cy.visit(
+ `/signin/success?returnUrl=${encodeURIComponent(
+ returnUrl,
+ )}&useIdapi=true`,
+ );
+
+ // mock form save success
+ cy.mockNext(200, {});
+
+ cy.findByText('Continue to the Guardian').click();
+ cy.lastPayloadIs([{ id: 'supporter', consented: false }]);
+ cy.url().should('include', returnUrl);
+ });
+
+ it('fails silently if submit fails, but user did not consent', () => {
+ cy.mockNext(200, verifiedUserWithNoConsent.user.consents);
+ cy.mockNext(500, {});
+ cy.visit('/signin/success?useIdapi=true');
+
+ cy.findByText('Continue to the Guardian').click();
+ cy.lastPayloadIs([{ id: 'supporter', consented: false }]);
+ cy.url().should('include', defaultReturnUrl);
+ });
+
+ it('shows error if submit fails and user did consent', () => {
+ cy.mockNext(200, verifiedUserWithNoConsent.user.consents);
+ cy.visit('/signin/success?useIdapi=true');
+ cy.findByLabelText('Yes, sign me up').click();
+
+ cy.mockNext(500, undefined);
+ cy.mockNext(200, verifiedUserWithNoConsent.user.consents);
+ cy.findByText('Continue to the Guardian').click();
+ cy.lastPayloadIs([{ id: 'supporter', consented: true }]);
+ cy.url().should('include', '/signin/success');
+ cy.findByText(
+ 'There was a problem saving your choice, please try again.',
+ ).should('exist');
+ });
+
+ it('redirects to returnUrl if fetching consents fails', () => {
+ cy.mockNext(500, {});
+ /**
+ * Using cy.request instead of cy.visit as we only need to test the redirect
+ * and cy.intercept does not seem to work here
+ */
+ cy.request({
+ url: '/signin/success?useIdapi=true',
+ followRedirect: false,
+ }).then((response) =>
+ expect(response.redirectedToUrl).to.contain(defaultReturnUrl),
+ );
+ });
+
+ it('redirects to returnUrl if fetching user consents fails', () => {
+ cy.mockNext(500, undefined);
+ // Using cy.request instead of cy.visit, see above for reasoning.
+ cy.request({
+ url: '/signin/success?useIdapi=true',
+ followRedirect: false,
+ }).then((response) =>
+ expect(response.redirectedToUrl).to.contain(defaultReturnUrl),
+ );
+ });
});
diff --git a/cypress/integration/mocked/register.6.cy.ts b/cypress/integration/mocked/register.6.cy.ts
index 46890ca923..449f82e565 100644
--- a/cypress/integration/mocked/register.6.cy.ts
+++ b/cypress/integration/mocked/register.6.cy.ts
@@ -2,191 +2,191 @@ import { injectAndCheckAxe } from '../../support/cypress-axe';
import { invalidEmailAddress } from '../../support/idapi/guest';
describe('Registration flow', () => {
- beforeEach(() => {
- cy.mockPurge();
- });
-
- context('A11y checks', () => {
- it('Has no detectable a11y violations on registration page', () => {
- cy.visit('/register?useIdapi=true');
- injectAndCheckAxe();
- });
-
- it('Has no detectable a11y violations on registration page with error', () => {
- cy.visit('/register?useIdapi=true');
- cy.get('input[name="email"]').type('Invalid email');
- cy.mockNext(500);
- cy.get('[data-cy=main-form-submit-button]').click();
- injectAndCheckAxe();
- });
- });
-
- context('Registering', () => {
- it('shows a generic error message when registration fails', () => {
- cy.visit(
- '/register?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
- );
- cy.get('input[name="email"]').type('example@example.com');
- cy.mockNext(200, {
- userType: 'new',
- });
- cy.mockNext(403, {
- status: 'error',
- errors: [
- {
- message: '',
- },
- ],
- });
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.contains('There was a problem registering, please try again.');
- });
-
- it('shows a email field error message when no email is sent', () => {
- cy.visit(
- '/register?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
- );
- cy.get('input[name="email"]').type('placeholder@example.com');
- cy.mockNext(200, {
- userType: 'new',
- });
- cy.mockNext(400, invalidEmailAddress);
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.contains('Please enter a valid email address.');
- });
-
- it('shows recaptcha error message when reCAPTCHA token request fails', () => {
- cy.visit(
- '/register?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
- );
- cy.get('input[name="email"]').type('placeholder@example.com');
- cy.intercept('POST', 'https://www.google.com/recaptcha/api2/**', {
- statusCode: 500,
- });
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.contains('Google reCAPTCHA verification failed. Please try again.');
- });
-
- it('shows detailed recaptcha error message when reCAPTCHA token request fails two times', () => {
- // Intercept "Report this error" link because we just check it is linked to.
- cy.intercept(
- 'GET',
- 'https://manage.theguardian.com/help-centre/contact-us',
- {
- statusCode: 200,
- },
- );
- cy.visit(
- '/register?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
- );
- cy.get('input[name="email"]').type('placeholder@example.com');
- cy.intercept('POST', 'https://www.google.com/recaptcha/api2/**', {
- statusCode: 500,
- });
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.contains('Google reCAPTCHA verification failed. Please try again.');
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.contains('Google reCAPTCHA verification failed.');
- cy.contains('If the problem persists please try the following:');
- cy.contains('Report this error').click();
- cy.url().should(
- 'eq',
- 'https://manage.theguardian.com/help-centre/contact-us',
- );
- });
-
- it('redirects to email sent page upon successful guest registration', () => {
- cy.visit(
- '/register?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
- );
- cy.get('input[name="email"]').type('example@example.com');
- cy.mockNext(200, {
- userType: 'new',
- });
- cy.mockNext(200, {
- status: 'success',
- errors: [],
- });
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.contains('Check your email inbox');
- cy.contains('example@example.com');
- });
-
- it('redirects to email sent page when existing user with password attempts to register', () => {
- cy.visit(
- '/register?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
- );
- cy.get('input[name="email"]').type('example@example.com');
- cy.mockNext(200, {
- userType: 'current',
- });
- cy.mockNext(200);
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.contains('Check your email inbox');
- cy.contains('example@example.com');
- });
-
- it('redirects to email sent page when existing user without password attempts to register', () => {
- cy.visit(
- '/register?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
- );
- cy.get('input[name="email"]').type('example@example.com');
- cy.mockNext(200, {
- userType: 'guest',
- });
- cy.mockNext(200);
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.contains('Check your email inbox');
- cy.contains('example@example.com');
- });
-
- it('redirects to homepage when user with existing valid session visits register page', () => {
- cy.setCookie('SC_GU_U', 'sessionvalue');
- cy.setCookie('SC_GU_LA', 'la_value');
-
- cy.request({
- url: '/register',
- followRedirect: false,
- failOnStatusCode: false,
- }).then((response) => {
- expect(response.status).to.eq(302);
- expect(response.redirectedToUrl).to.eq(
- 'https://m.code.dev-theguardian.com/',
- );
- });
- cy.mockNext(200, {
- status: 'signedInRecently',
- emailValidated: true,
- });
- });
- it('redirects to /reauthenticate when user with existing invalid session visits register page', () => {
- cy.setCookie('SC_GU_U', 'sessionvalue');
- cy.setCookie('SC_GU_LA', 'la_value');
-
- cy.mockNext(200, {
- status: 'signedInNotRecently',
- emailValidated: true,
- });
- cy.visit('/register?useIdapi=true');
-
- cy.location('pathname').should('eq', '/reauthenticate');
- });
- });
-
- context('General IDAPI failure', () => {
- it('displays a generic error message', function () {
- cy.mockNext(200, {
- userType: 'new',
- });
- cy.mockNext(500);
- cy.visit(
- '/register?returnUrl=https%3A%2F%2Flocalhost%3A8861%2Fsignin&useIdapi=true',
- );
-
- cy.get('input[name=email]').type('example@example.com');
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('There was a problem registering, please try again.');
- });
- });
+ beforeEach(() => {
+ cy.mockPurge();
+ });
+
+ context('A11y checks', () => {
+ it('Has no detectable a11y violations on registration page', () => {
+ cy.visit('/register?useIdapi=true');
+ injectAndCheckAxe();
+ });
+
+ it('Has no detectable a11y violations on registration page with error', () => {
+ cy.visit('/register?useIdapi=true');
+ cy.get('input[name="email"]').type('Invalid email');
+ cy.mockNext(500);
+ cy.get('[data-cy=main-form-submit-button]').click();
+ injectAndCheckAxe();
+ });
+ });
+
+ context('Registering', () => {
+ it('shows a generic error message when registration fails', () => {
+ cy.visit(
+ '/register?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
+ );
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.mockNext(200, {
+ userType: 'new',
+ });
+ cy.mockNext(403, {
+ status: 'error',
+ errors: [
+ {
+ message: '',
+ },
+ ],
+ });
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.contains('There was a problem registering, please try again.');
+ });
+
+ it('shows a email field error message when no email is sent', () => {
+ cy.visit(
+ '/register?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
+ );
+ cy.get('input[name="email"]').type('placeholder@example.com');
+ cy.mockNext(200, {
+ userType: 'new',
+ });
+ cy.mockNext(400, invalidEmailAddress);
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.contains('Please enter a valid email address.');
+ });
+
+ it('shows recaptcha error message when reCAPTCHA token request fails', () => {
+ cy.visit(
+ '/register?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
+ );
+ cy.get('input[name="email"]').type('placeholder@example.com');
+ cy.intercept('POST', 'https://www.google.com/recaptcha/api2/**', {
+ statusCode: 500,
+ });
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.contains('Google reCAPTCHA verification failed. Please try again.');
+ });
+
+ it('shows detailed recaptcha error message when reCAPTCHA token request fails two times', () => {
+ // Intercept "Report this error" link because we just check it is linked to.
+ cy.intercept(
+ 'GET',
+ 'https://manage.theguardian.com/help-centre/contact-us',
+ {
+ statusCode: 200,
+ },
+ );
+ cy.visit(
+ '/register?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
+ );
+ cy.get('input[name="email"]').type('placeholder@example.com');
+ cy.intercept('POST', 'https://www.google.com/recaptcha/api2/**', {
+ statusCode: 500,
+ });
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.contains('Google reCAPTCHA verification failed. Please try again.');
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.contains('Google reCAPTCHA verification failed.');
+ cy.contains('If the problem persists please try the following:');
+ cy.contains('Report this error').click();
+ cy.url().should(
+ 'eq',
+ 'https://manage.theguardian.com/help-centre/contact-us',
+ );
+ });
+
+ it('redirects to email sent page upon successful guest registration', () => {
+ cy.visit(
+ '/register?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
+ );
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.mockNext(200, {
+ userType: 'new',
+ });
+ cy.mockNext(200, {
+ status: 'success',
+ errors: [],
+ });
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.contains('Check your email inbox');
+ cy.contains('example@example.com');
+ });
+
+ it('redirects to email sent page when existing user with password attempts to register', () => {
+ cy.visit(
+ '/register?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
+ );
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.mockNext(200, {
+ userType: 'current',
+ });
+ cy.mockNext(200);
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.contains('Check your email inbox');
+ cy.contains('example@example.com');
+ });
+
+ it('redirects to email sent page when existing user without password attempts to register', () => {
+ cy.visit(
+ '/register?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
+ );
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.mockNext(200, {
+ userType: 'guest',
+ });
+ cy.mockNext(200);
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.contains('Check your email inbox');
+ cy.contains('example@example.com');
+ });
+
+ it('redirects to homepage when user with existing valid session visits register page', () => {
+ cy.setCookie('SC_GU_U', 'sessionvalue');
+ cy.setCookie('SC_GU_LA', 'la_value');
+
+ cy.request({
+ url: '/register',
+ followRedirect: false,
+ failOnStatusCode: false,
+ }).then((response) => {
+ expect(response.status).to.eq(302);
+ expect(response.redirectedToUrl).to.eq(
+ 'https://m.code.dev-theguardian.com/',
+ );
+ });
+ cy.mockNext(200, {
+ status: 'signedInRecently',
+ emailValidated: true,
+ });
+ });
+ it('redirects to /reauthenticate when user with existing invalid session visits register page', () => {
+ cy.setCookie('SC_GU_U', 'sessionvalue');
+ cy.setCookie('SC_GU_LA', 'la_value');
+
+ cy.mockNext(200, {
+ status: 'signedInNotRecently',
+ emailValidated: true,
+ });
+ cy.visit('/register?useIdapi=true');
+
+ cy.location('pathname').should('eq', '/reauthenticate');
+ });
+ });
+
+ context('General IDAPI failure', () => {
+ it('displays a generic error message', function () {
+ cy.mockNext(200, {
+ userType: 'new',
+ });
+ cy.mockNext(500);
+ cy.visit(
+ '/register?returnUrl=https%3A%2F%2Flocalhost%3A8861%2Fsignin&useIdapi=true',
+ );
+
+ cy.get('input[name=email]').type('example@example.com');
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('There was a problem registering, please try again.');
+ });
+ });
});
diff --git a/cypress/integration/mocked/reset_password.5.cy.ts b/cypress/integration/mocked/reset_password.5.cy.ts
index d2ea62400c..93f89a19cc 100644
--- a/cypress/integration/mocked/reset_password.5.cy.ts
+++ b/cypress/integration/mocked/reset_password.5.cy.ts
@@ -2,91 +2,91 @@ import { injectAndCheckAxe } from '../../support/cypress-axe';
import PageResetPassword from '../../support/pages/reset_password_page';
describe('Password reset flow', () => {
- const page = new PageResetPassword();
+ const page = new PageResetPassword();
- before(() => {
- cy.mockPurge();
- cy.fixture('users').as('users');
- });
+ before(() => {
+ cy.mockPurge();
+ cy.fixture('users').as('users');
+ });
- beforeEach(function () {
- cy.mockPurge();
- page.goto();
- });
+ beforeEach(function () {
+ cy.mockPurge();
+ page.goto();
+ });
- context('A11y checks', () => {
- it('Has no detectable a11y violations on reset password page', () => {
- injectAndCheckAxe();
- });
+ context('A11y checks', () => {
+ it('Has no detectable a11y violations on reset password page', () => {
+ injectAndCheckAxe();
+ });
- it('Has no detectable a11y violations on reset password page with error', () => {
- cy.mockNext(500);
- page.submitEmailAddress('example@example.com');
- injectAndCheckAxe();
- });
+ it('Has no detectable a11y violations on reset password page with error', () => {
+ cy.mockNext(500);
+ page.submitEmailAddress('example@example.com');
+ injectAndCheckAxe();
+ });
- it('Has no detectable a11y violations on email sent page', function () {
- const { email } = this.users.validEmail;
- cy.mockNext(200);
- page.submitEmailAddress(email);
- injectAndCheckAxe();
- });
- });
+ it('Has no detectable a11y violations on email sent page', function () {
+ const { email } = this.users.validEmail;
+ cy.mockNext(200);
+ page.submitEmailAddress(email);
+ injectAndCheckAxe();
+ });
+ });
- context('Valid email already exits', () => {
- it('successfully submits the request', function () {
- const { email } = this.users.validEmail;
- cy.mockNext(200);
- page.submitEmailAddress(email);
- cy.contains('Check your email');
- });
- });
+ context('Valid email already exits', () => {
+ it('successfully submits the request', function () {
+ const { email } = this.users.validEmail;
+ cy.mockNext(200);
+ page.submitEmailAddress(email);
+ cy.contains('Check your email');
+ });
+ });
- context('Email field is left blank', () => {
- it('displays the standard HTML validation', () => {
- page.clickResetPassword();
- page.invalidEmailAddressField().should('have.length', 1);
- });
- });
+ context('Email field is left blank', () => {
+ it('displays the standard HTML validation', () => {
+ page.clickResetPassword();
+ page.invalidEmailAddressField().should('have.length', 1);
+ });
+ });
- context('Email is invalid', () => {
- it('displays the standard HTML validation', () => {
- page.submitEmailAddress('bademail£');
- page.invalidEmailAddressField().should('have.length', 1);
- });
- });
+ context('Email is invalid', () => {
+ it('displays the standard HTML validation', () => {
+ page.submitEmailAddress('bademail£');
+ page.invalidEmailAddressField().should('have.length', 1);
+ });
+ });
- context('General IDAPI failure', () => {
- it('displays a generic error message', function () {
- const { email } = this.users.validEmail;
- cy.mockNext(500);
- page.submitEmailAddress(email);
- cy.contains(PageResetPassword.CONTENT.ERRORS.GENERIC);
- });
- });
+ context('General IDAPI failure', () => {
+ it('displays a generic error message', function () {
+ const { email } = this.users.validEmail;
+ cy.mockNext(500);
+ page.submitEmailAddress(email);
+ cy.contains(PageResetPassword.CONTENT.ERRORS.GENERIC);
+ });
+ });
- context('Recaptcha errors', () => {
- it('shows recaptcha error message when reCAPTCHA token request fails', function () {
- cy.intercept('POST', 'https://www.google.com/recaptcha/api2/**', {
- statusCode: 500,
- });
- const { email } = this.users.emailNotRegistered;
- page.submitEmailAddress(email);
- cy.contains('Google reCAPTCHA verification failed. Please try again.');
- });
+ context('Recaptcha errors', () => {
+ it('shows recaptcha error message when reCAPTCHA token request fails', function () {
+ cy.intercept('POST', 'https://www.google.com/recaptcha/api2/**', {
+ statusCode: 500,
+ });
+ const { email } = this.users.emailNotRegistered;
+ page.submitEmailAddress(email);
+ cy.contains('Google reCAPTCHA verification failed. Please try again.');
+ });
- it('shows detailed recaptcha error message when reCAPTCHA token request fails two times', function () {
- cy.intercept('POST', 'https://www.google.com/recaptcha/api2/**', {
- statusCode: 500,
- });
- const { email } = this.users.emailNotRegistered;
- page.submitEmailAddress(email);
- cy.contains('Google reCAPTCHA verification failed. Please try again.');
- page.emailAddressField().clear();
- page.submitEmailAddress(email);
- cy.contains('Google reCAPTCHA verification failed.');
- cy.contains('If the problem persists please try the following:');
- cy.contains('userhelp@');
- });
- });
+ it('shows detailed recaptcha error message when reCAPTCHA token request fails two times', function () {
+ cy.intercept('POST', 'https://www.google.com/recaptcha/api2/**', {
+ statusCode: 500,
+ });
+ const { email } = this.users.emailNotRegistered;
+ page.submitEmailAddress(email);
+ cy.contains('Google reCAPTCHA verification failed. Please try again.');
+ page.emailAddressField().clear();
+ page.submitEmailAddress(email);
+ cy.contains('Google reCAPTCHA verification failed.');
+ cy.contains('If the problem persists please try the following:');
+ cy.contains('userhelp@');
+ });
+ });
});
diff --git a/cypress/integration/mocked/set_password.5.cy.ts b/cypress/integration/mocked/set_password.5.cy.ts
index cd79fe026f..ef20ac5948 100644
--- a/cypress/integration/mocked/set_password.5.cy.ts
+++ b/cypress/integration/mocked/set_password.5.cy.ts
@@ -3,271 +3,271 @@
import { injectAndCheckAxe } from '../../support/cypress-axe';
describe('Password set/create flow', () => {
- const fakeValidationRespone = (timeUntilExpiry?: number) => ({
- user: {
- primaryEmailAddress: 'name@example.com',
- },
- timeUntilExpiry,
- });
+ const fakeValidationRespone = (timeUntilExpiry?: number) => ({
+ user: {
+ primaryEmailAddress: 'name@example.com',
+ },
+ timeUntilExpiry,
+ });
- const fakeSuccessResponse = {
- cookies: {
- values: [
- {
- key: 'GU_U',
- value: 'FAKE_VALUE_0',
- },
- {
- key: 'SC_GU_LA',
- value: 'FAKE_VALUE_1',
- sessionCookie: true,
- },
- {
- key: 'SC_GU_U',
- value: 'FAKE_VALUE_2',
- },
- ],
- expiresAt: 1,
- },
- };
+ const fakeSuccessResponse = {
+ cookies: {
+ values: [
+ {
+ key: 'GU_U',
+ value: 'FAKE_VALUE_0',
+ },
+ {
+ key: 'SC_GU_LA',
+ value: 'FAKE_VALUE_1',
+ sessionCookie: true,
+ },
+ {
+ key: 'SC_GU_U',
+ value: 'FAKE_VALUE_2',
+ },
+ ],
+ expiresAt: 1,
+ },
+ };
- beforeEach(() => {
- cy.mockPurge();
- });
+ beforeEach(() => {
+ cy.mockPurge();
+ });
- context('A11y checks', () => {
- it('Has no detectable a11y violations on resend password page', () => {
- cy.mockNext(500, {
- status: 'error',
- errors: [
- {
- message: 'Invalid token',
- },
- ],
- });
- cy.visit('/set-password/fake_token?useIdapi=true');
- injectAndCheckAxe();
- });
+ context('A11y checks', () => {
+ it('Has no detectable a11y violations on resend password page', () => {
+ cy.mockNext(500, {
+ status: 'error',
+ errors: [
+ {
+ message: 'Invalid token',
+ },
+ ],
+ });
+ cy.visit('/set-password/fake_token?useIdapi=true');
+ injectAndCheckAxe();
+ });
- it('Has no detectable a11y violations on create/set password page', () => {
- cy.mockNext(200);
- cy.mockNext(200, fakeSuccessResponse);
- cy.visit('/set-password/fake_token?useIdapi=true');
- injectAndCheckAxe();
- });
+ it('Has no detectable a11y violations on create/set password page', () => {
+ cy.mockNext(200);
+ cy.mockNext(200, fakeSuccessResponse);
+ cy.visit('/set-password/fake_token?useIdapi=true');
+ injectAndCheckAxe();
+ });
- it('Has no detectable a11y violations on create/set password page with error', () => {
- cy.mockNext(200);
- cy.visit('/set-password/fake_token?useIdapi=true');
- cy.get('input[name="password"]').type('short');
- cy.get('button[type="submit"]').click();
- injectAndCheckAxe();
- });
+ it('Has no detectable a11y violations on create/set password page with error', () => {
+ cy.mockNext(200);
+ cy.visit('/set-password/fake_token?useIdapi=true');
+ cy.get('input[name="password"]').type('short');
+ cy.get('button[type="submit"]').click();
+ injectAndCheckAxe();
+ });
- it('Has no detectable a11y violations on create/set password complete page', () => {
- cy.mockNext(200);
- cy.mockNext(200, fakeSuccessResponse);
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.visit('/set-password/fake_token?useIdapi=true');
- cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
- cy.wait('@breachCheck');
- cy.get('button[type="submit"]').click();
- injectAndCheckAxe();
- });
- });
+ it('Has no detectable a11y violations on create/set password complete page', () => {
+ cy.mockNext(200);
+ cy.mockNext(200, fakeSuccessResponse);
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.visit('/set-password/fake_token?useIdapi=true');
+ cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
+ cy.wait('@breachCheck');
+ cy.get('button[type="submit"]').click();
+ injectAndCheckAxe();
+ });
+ });
- context('show / hide password eye button', () => {
- it('clicking on the password eye shows the password and clicking it again hides it', () => {
- cy.mockNext(200);
- cy.visit('/set-password/fake_token?useIdapi=true');
- cy.get('input[name="password"]').should('have.attr', 'type', 'password');
- cy.get('input[name="password"]').type('some_password');
- cy.get('[data-cy=password-input-eye-button]').click();
- cy.get('input[name="password"]').should('have.attr', 'type', 'text');
- cy.get('[data-cy=password-input-eye-button]').click();
- cy.get('input[name="password"]').should('have.attr', 'type', 'password');
- });
- });
+ context('show / hide password eye button', () => {
+ it('clicking on the password eye shows the password and clicking it again hides it', () => {
+ cy.mockNext(200);
+ cy.visit('/set-password/fake_token?useIdapi=true');
+ cy.get('input[name="password"]').should('have.attr', 'type', 'password');
+ cy.get('input[name="password"]').type('some_password');
+ cy.get('[data-cy=password-input-eye-button]').click();
+ cy.get('input[name="password"]').should('have.attr', 'type', 'text');
+ cy.get('[data-cy=password-input-eye-button]').click();
+ cy.get('input[name="password"]').should('have.attr', 'type', 'password');
+ });
+ });
- context('An expired/invalid token is used', () => {
- it('shows a resend password page', () => {
- cy.mockNext(500, {
- status: 'error',
- errors: [
- {
- message: 'Invalid token',
- },
- ],
- });
- cy.visit('/set-password/fake_token?useIdapi=true');
- cy.contains('Link expired');
- });
+ context('An expired/invalid token is used', () => {
+ it('shows a resend password page', () => {
+ cy.mockNext(500, {
+ status: 'error',
+ errors: [
+ {
+ message: 'Invalid token',
+ },
+ ],
+ });
+ cy.visit('/set-password/fake_token?useIdapi=true');
+ cy.contains('Link expired');
+ });
- it('does not allow email resend if reCAPTCHA check fails', () => {
- cy.mockNext(500, {
- status: 'error',
- errors: [
- {
- message: 'Invalid token',
- },
- ],
- });
- cy.visit('/set-password/fake_token?useIdapi=true');
- cy.contains('Link expired');
- cy.get('input[name="email"]').type('some@email.com');
- cy.intercept('POST', 'https://www.google.com/recaptcha/api2/**', {
- statusCode: 500,
- });
- cy.get('button[type="submit"]').click();
- cy.contains('Google reCAPTCHA verification failed. Please try again.');
- cy.get('button[type="submit"]').click();
- cy.contains('Google reCAPTCHA verification failed.');
- cy.contains('If the problem persists please try the following:');
- cy.contains('userhelp@');
- });
+ it('does not allow email resend if reCAPTCHA check fails', () => {
+ cy.mockNext(500, {
+ status: 'error',
+ errors: [
+ {
+ message: 'Invalid token',
+ },
+ ],
+ });
+ cy.visit('/set-password/fake_token?useIdapi=true');
+ cy.contains('Link expired');
+ cy.get('input[name="email"]').type('some@email.com');
+ cy.intercept('POST', 'https://www.google.com/recaptcha/api2/**', {
+ statusCode: 500,
+ });
+ cy.get('button[type="submit"]').click();
+ cy.contains('Google reCAPTCHA verification failed. Please try again.');
+ cy.get('button[type="submit"]').click();
+ cy.contains('Google reCAPTCHA verification failed.');
+ cy.contains('If the problem persists please try the following:');
+ cy.contains('userhelp@');
+ });
- it('shows the session time out page if the token expires while on the set password page', () => {
- cy.mockNext(200, fakeValidationRespone(1000));
- cy.visit('/set-password/fake_token?useIdapi=true');
- cy.contains('Session timed out');
- });
- });
+ it('shows the session time out page if the token expires while on the set password page', () => {
+ cy.mockNext(200, fakeValidationRespone(1000));
+ cy.visit('/set-password/fake_token?useIdapi=true');
+ cy.contains('Session timed out');
+ });
+ });
- context('Email shown on page', () => {
- it('shows the users email address on the page', () => {
- cy.mockNext(200, fakeValidationRespone());
- cy.visit('/set-password/fake_token?useIdapi=true');
- cy.contains(fakeValidationRespone().user.primaryEmailAddress);
- });
- });
+ context('Email shown on page', () => {
+ it('shows the users email address on the page', () => {
+ cy.mockNext(200, fakeValidationRespone());
+ cy.visit('/set-password/fake_token?useIdapi=true');
+ cy.contains(fakeValidationRespone().user.primaryEmailAddress);
+ });
+ });
- context('Valid password entered', () => {
- it('shows password set success screen, with a default redirect button.', () => {
- cy.mockNext(200);
- cy.mockNext(200, fakeSuccessResponse);
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.visit('/set-password/fake_token?useIdapi=true');
+ context('Valid password entered', () => {
+ it('shows password set success screen, with a default redirect button.', () => {
+ cy.mockNext(200);
+ cy.mockNext(200, fakeSuccessResponse);
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.visit('/set-password/fake_token?useIdapi=true');
- cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
- cy.wait('@breachCheck');
- cy.get('button[type="submit"]').click();
- cy.contains('Password created');
- cy.contains('Continue to the Guardian').should(
- 'have.attr',
- 'href',
- `${Cypress.env('DEFAULT_RETURN_URI')}/`,
- );
- });
+ cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
+ cy.wait('@breachCheck');
+ cy.get('button[type="submit"]').click();
+ cy.contains('Password created');
+ cy.contains('Continue to the Guardian').should(
+ 'have.attr',
+ 'href',
+ `${Cypress.env('DEFAULT_RETURN_URI')}/`,
+ );
+ });
- it('shows password change success screen, with default redirect button, and users email', () => {
- cy.mockNext(200, fakeValidationRespone());
- cy.mockNext(200, fakeSuccessResponse);
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.visit('/set-password/fake_token?useIdapi=true');
- cy.contains(fakeValidationRespone().user.primaryEmailAddress);
+ it('shows password change success screen, with default redirect button, and users email', () => {
+ cy.mockNext(200, fakeValidationRespone());
+ cy.mockNext(200, fakeSuccessResponse);
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.visit('/set-password/fake_token?useIdapi=true');
+ cy.contains(fakeValidationRespone().user.primaryEmailAddress);
- cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
- cy.wait('@breachCheck');
- cy.get('button[type="submit"]').click();
- cy.contains('Password created');
- cy.contains('Continue to the Guardian').should(
- 'have.attr',
- 'href',
- `${Cypress.env('DEFAULT_RETURN_URI')}/`,
- );
- cy.contains(fakeValidationRespone().user.primaryEmailAddress);
- });
- });
+ cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
+ cy.wait('@breachCheck');
+ cy.get('button[type="submit"]').click();
+ cy.contains('Password created');
+ cy.contains('Continue to the Guardian').should(
+ 'have.attr',
+ 'href',
+ `${Cypress.env('DEFAULT_RETURN_URI')}/`,
+ );
+ cy.contains(fakeValidationRespone().user.primaryEmailAddress);
+ });
+ });
- context(
- 'Valid password entered and a return url with a Guardian domain is specified.',
- () => {
- it('shows password created success screen, with a redirect button linking to the return url.', () => {
- cy.mockNext(200);
- cy.mockNext(200, fakeSuccessResponse);
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.visit(
- '/set-password/fake_token?returnUrl=https://news.theguardian.com&useIdapi=true',
- );
- cy.get('input[name="password"]').type(
- 'thisisalongandunbreachedpassword',
- );
- cy.wait('@breachCheck');
- cy.get('button[type="submit"]').click();
- cy.contains('Password created');
- cy.contains('Continue to the Guardian').should(
- 'have.attr',
- 'href',
- 'https://news.theguardian.com/',
- );
- });
- },
- );
+ context(
+ 'Valid password entered and a return url with a Guardian domain is specified.',
+ () => {
+ it('shows password created success screen, with a redirect button linking to the return url.', () => {
+ cy.mockNext(200);
+ cy.mockNext(200, fakeSuccessResponse);
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.visit(
+ '/set-password/fake_token?returnUrl=https://news.theguardian.com&useIdapi=true',
+ );
+ cy.get('input[name="password"]').type(
+ 'thisisalongandunbreachedpassword',
+ );
+ cy.wait('@breachCheck');
+ cy.get('button[type="submit"]').click();
+ cy.contains('Password created');
+ cy.contains('Continue to the Guardian').should(
+ 'have.attr',
+ 'href',
+ 'https://news.theguardian.com/',
+ );
+ });
+ },
+ );
- context(
- 'Valid password entered and an return url from a non-Guardian domain is specified.',
- () => {
- it('shows password created success screen, with a default redirect button.', () => {
- cy.mockNext(200);
- cy.mockNext(200, fakeSuccessResponse);
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.visit(
- '/set-password/fake_token?returnUrl=https://news.badsite.com&useIdapi=true',
- );
- cy.get('input[name="password"]').type(
- 'thisisalongandunbreachedpassword',
- );
- cy.wait('@breachCheck');
- cy.get('button[type="submit"]').click();
- cy.contains('Password created');
- cy.contains('Continue to the Guardian').should(
- 'have.attr',
- 'href',
- `${Cypress.env('DEFAULT_RETURN_URI')}/`,
- );
- });
- },
- );
+ context(
+ 'Valid password entered and an return url from a non-Guardian domain is specified.',
+ () => {
+ it('shows password created success screen, with a default redirect button.', () => {
+ cy.mockNext(200);
+ cy.mockNext(200, fakeSuccessResponse);
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.visit(
+ '/set-password/fake_token?returnUrl=https://news.badsite.com&useIdapi=true',
+ );
+ cy.get('input[name="password"]').type(
+ 'thisisalongandunbreachedpassword',
+ );
+ cy.wait('@breachCheck');
+ cy.get('button[type="submit"]').click();
+ cy.contains('Password created');
+ cy.contains('Continue to the Guardian').should(
+ 'have.attr',
+ 'href',
+ `${Cypress.env('DEFAULT_RETURN_URI')}/`,
+ );
+ });
+ },
+ );
- context('General IDAPI failure on token read', () => {
- it('displays the password resend page', () => {
- cy.mockNext(500);
- cy.visit('/set-password/fake_token?useIdapi=true');
- cy.contains('Link expired');
- });
- });
+ context('General IDAPI failure on token read', () => {
+ it('displays the password resend page', () => {
+ cy.mockNext(500);
+ cy.visit('/set-password/fake_token?useIdapi=true');
+ cy.contains('Link expired');
+ });
+ });
- context('General IDAPI failure on password change', () => {
- it('displays a generic error message', () => {
- cy.mockNext(200);
- cy.mockNext(500);
- cy.mockNext(200);
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.visit('/set-password/fake_token?useIdapi=true');
- cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
- cy.wait('@breachCheck');
- cy.get('button[type="submit"]').click();
- cy.contains(
- 'There was a problem changing your password, please try again.',
- );
- });
- });
+ context('General IDAPI failure on password change', () => {
+ it('displays a generic error message', () => {
+ cy.mockNext(200);
+ cy.mockNext(500);
+ cy.mockNext(200);
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.visit('/set-password/fake_token?useIdapi=true');
+ cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
+ cy.wait('@breachCheck');
+ cy.get('button[type="submit"]').click();
+ cy.contains(
+ 'There was a problem changing your password, please try again.',
+ );
+ });
+ });
});
diff --git a/cypress/integration/mocked/sign_in.2.cy.ts b/cypress/integration/mocked/sign_in.2.cy.ts
index d47cc7f4dc..9001ecc56e 100644
--- a/cypress/integration/mocked/sign_in.2.cy.ts
+++ b/cypress/integration/mocked/sign_in.2.cy.ts
@@ -1,297 +1,297 @@
import { injectAndCheckAxe } from '../../support/cypress-axe';
import { allConsents, CONSENTS_ENDPOINT } from '../../support/idapi/consent';
import {
- verifiedUserWithNoConsent,
- USER_CONSENTS_ENDPOINT,
+ verifiedUserWithNoConsent,
+ USER_CONSENTS_ENDPOINT,
} from '../../support/idapi/user';
describe('Sign in flow', () => {
- beforeEach(() => {
- cy.mockPurge();
- });
+ beforeEach(() => {
+ cy.mockPurge();
+ });
- context('A11y checks', () => {
- it('Has no detectable a11y violations on sign in page', () => {
- cy.visit('/signin?useIdapi=true');
- injectAndCheckAxe();
- });
+ context('A11y checks', () => {
+ it('Has no detectable a11y violations on sign in page', () => {
+ cy.visit('/signin?useIdapi=true');
+ injectAndCheckAxe();
+ });
- it('Has no detectable a11y violations on sign in page with error', () => {
- cy.visit('/signin?useIdapi=true');
- cy.get('input[name="email"]').type('Invalid email');
- cy.get('input[name="password"]').type('Invalid password');
- cy.mockNext(500);
- cy.get('[data-cy=main-form-submit-button]').click();
- injectAndCheckAxe();
- });
- });
+ it('Has no detectable a11y violations on sign in page with error', () => {
+ cy.visit('/signin?useIdapi=true');
+ cy.get('input[name="email"]').type('Invalid email');
+ cy.get('input[name="password"]').type('Invalid password');
+ cy.mockNext(500);
+ cy.get('[data-cy=main-form-submit-button]').click();
+ injectAndCheckAxe();
+ });
+ });
- context('Signing in', () => {
- const defaultReturnUrl = 'https://m.code.dev-theguardian.com';
- it('shows an error message when sign in fails', function () {
- cy.visit(
- '/signin?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
- );
- cy.get('input[name="email"]').type('example@example.com');
- cy.get('input[name="password"]').type('password');
- cy.mockNext(403, {
- status: 'error',
- errors: [
- {
- message: 'Invalid email or password',
- },
- ],
- });
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.contains("Email and password don't match");
- cy.get('input[name="email"]').should('have.value', 'example@example.com');
- });
+ context('Signing in', () => {
+ const defaultReturnUrl = 'https://m.code.dev-theguardian.com';
+ it('shows an error message when sign in fails', function () {
+ cy.visit(
+ '/signin?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
+ );
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.get('input[name="password"]').type('password');
+ cy.mockNext(403, {
+ status: 'error',
+ errors: [
+ {
+ message: 'Invalid email or password',
+ },
+ ],
+ });
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.contains("Email and password don't match");
+ cy.get('input[name="email"]').should('have.value', 'example@example.com');
+ });
- it('shows a generic error message when the api error response is not known', function () {
- cy.visit(
- '/signin?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
- );
- cy.get('input[name="email"]').type('example@example.com');
- cy.get('input[name="password"]').type('password');
- cy.mockNext(403, {
- status: 'error',
- errors: [
- {
- message: 'Bloopity flub',
- },
- ],
- });
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.contains('There was a problem signing in, please try again');
- });
+ it('shows a generic error message when the api error response is not known', function () {
+ cy.visit(
+ '/signin?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
+ );
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.get('input[name="password"]').type('password');
+ cy.mockNext(403, {
+ status: 'error',
+ errors: [
+ {
+ message: 'Bloopity flub',
+ },
+ ],
+ });
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.contains('There was a problem signing in, please try again');
+ });
- it('loads the returnUrl upon successful authentication', function () {
- const returnUrl = 'https://www.theguardian.com/about';
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', returnUrl, (req) => {
- req.reply(200);
- });
- cy.visit(
- `/signin?returnUrl=${encodeURIComponent(returnUrl)}&useIdapi=true`,
- );
- cy.get('input[name="email"]').type('example@example.com');
- cy.get('input[name="password"]').type('password');
- cy.mockNext(200, {
- cookies: {
- values: [{ key: 'key', value: 'value' }],
- expiresAt: new Date(Date.now() + 1800000 /* 30min */).toISOString(),
- },
- });
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.url().should('eq', returnUrl);
- });
+ it('loads the returnUrl upon successful authentication', function () {
+ const returnUrl = 'https://www.theguardian.com/about';
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', returnUrl, (req) => {
+ req.reply(200);
+ });
+ cy.visit(
+ `/signin?returnUrl=${encodeURIComponent(returnUrl)}&useIdapi=true`,
+ );
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.get('input[name="password"]').type('password');
+ cy.mockNext(200, {
+ cookies: {
+ values: [{ key: 'key', value: 'value' }],
+ expiresAt: new Date(Date.now() + 1800000 /* 30min */).toISOString(),
+ },
+ });
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.url().should('eq', returnUrl);
+ });
- it('redirects to the default url if no returnUrl given', function () {
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', 'https://m.code.dev-theguardian.com/', (req) => {
- req.reply(200);
- });
+ it('redirects to the default url if no returnUrl given', function () {
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', 'https://m.code.dev-theguardian.com/', (req) => {
+ req.reply(200);
+ });
- cy.visit('/signin?useIdapi=true');
- cy.get('input[name="email"]').type('example@example.com');
- cy.get('input[name="password"]').type('password');
- cy.mockNext(200, {
- cookies: {
- values: [{ key: 'key', value: 'value' }],
- expiresAt: new Date(Date.now() + 1800000 /* 30min */).toISOString(),
- },
- });
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.url().should('include', defaultReturnUrl);
- });
+ cy.visit('/signin?useIdapi=true');
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.get('input[name="password"]').type('password');
+ cy.mockNext(200, {
+ cookies: {
+ values: [{ key: 'key', value: 'value' }],
+ expiresAt: new Date(Date.now() + 1800000 /* 30min */).toISOString(),
+ },
+ });
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.url().should('include', defaultReturnUrl);
+ });
- it('auto-fills the email field when encryptedEmail is successfully decrypted', () => {
- cy.mockNext(200, {
- status: 'ok',
- email: 'test@test.com',
- });
- cy.visit(`/signin?encryptedEmail=bdfalrbagbgu&useIdapi=true`);
- cy.get('input[name="email"]').should('have.value', 'test@test.com');
- });
+ it('auto-fills the email field when encryptedEmail is successfully decrypted', () => {
+ cy.mockNext(200, {
+ status: 'ok',
+ email: 'test@test.com',
+ });
+ cy.visit(`/signin?encryptedEmail=bdfalrbagbgu&useIdapi=true`);
+ cy.get('input[name="email"]').should('have.value', 'test@test.com');
+ });
- it('shows recaptcha error message when reCAPTCHA token request fails', () => {
- cy.visit(
- '/signin?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
- );
- cy.get('input[name="email"]').type('placeholder@example.com');
- cy.get('input[name="password"]').type('definitelynotarealpassword');
- cy.intercept('POST', 'https://www.google.com/recaptcha/api2/**', {
- statusCode: 500,
- });
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.contains('Google reCAPTCHA verification failed. Please try again.');
- });
+ it('shows recaptcha error message when reCAPTCHA token request fails', () => {
+ cy.visit(
+ '/signin?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
+ );
+ cy.get('input[name="email"]').type('placeholder@example.com');
+ cy.get('input[name="password"]').type('definitelynotarealpassword');
+ cy.intercept('POST', 'https://www.google.com/recaptcha/api2/**', {
+ statusCode: 500,
+ });
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.contains('Google reCAPTCHA verification failed. Please try again.');
+ });
- it('shows detailed recaptcha error message when reCAPTCHA token request fails two times', () => {
- // Intercept "Report this error" link because we just check it is linked to.
- cy.intercept(
- 'GET',
- 'https://manage.theguardian.com/help-centre/contact-us',
- {
- statusCode: 200,
- },
- );
- cy.visit(
- '/signin?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
- );
- cy.get('input[name="email"]').type('placeholder@example.com');
- cy.get('input[name="password"]').type('definitelynotarealpassword');
- cy.intercept('POST', 'https://www.google.com/recaptcha/api2/**', {
- statusCode: 500,
- });
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.contains('Google reCAPTCHA verification failed. Please try again.');
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.contains('Google reCAPTCHA verification failed.');
- cy.contains('If the problem persists please try the following:');
- cy.contains('Report this error').click();
- cy.url().should(
- 'eq',
- 'https://manage.theguardian.com/help-centre/contact-us',
- );
- });
+ it('shows detailed recaptcha error message when reCAPTCHA token request fails two times', () => {
+ // Intercept "Report this error" link because we just check it is linked to.
+ cy.intercept(
+ 'GET',
+ 'https://manage.theguardian.com/help-centre/contact-us',
+ {
+ statusCode: 200,
+ },
+ );
+ cy.visit(
+ '/signin?returnUrl=https%3A%2F%2Fwww.theguardian.com%2Fabout&useIdapi=true',
+ );
+ cy.get('input[name="email"]').type('placeholder@example.com');
+ cy.get('input[name="password"]').type('definitelynotarealpassword');
+ cy.intercept('POST', 'https://www.google.com/recaptcha/api2/**', {
+ statusCode: 500,
+ });
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.contains('Google reCAPTCHA verification failed. Please try again.');
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.contains('Google reCAPTCHA verification failed.');
+ cy.contains('If the problem persists please try the following:');
+ cy.contains('Report this error').click();
+ cy.url().should(
+ 'eq',
+ 'https://manage.theguardian.com/help-centre/contact-us',
+ );
+ });
- it('redirects to homepage when user with existing valid session visits signin page', () => {
- cy.setCookie('SC_GU_U', 'sessionvalue');
- cy.setCookie('SC_GU_LA', 'la_value');
+ it('redirects to homepage when user with existing valid session visits signin page', () => {
+ cy.setCookie('SC_GU_U', 'sessionvalue');
+ cy.setCookie('SC_GU_LA', 'la_value');
- cy.request({
- url: '/signin',
- followRedirect: false,
- failOnStatusCode: false,
- }).then((response) => {
- expect(response.status).to.eq(302);
- expect(response.redirectedToUrl).to.eq(
- 'https://m.code.dev-theguardian.com/',
- );
- });
- cy.mockNext(200, {
- status: 'signedInRecently',
- emailValidated: true,
- });
- });
+ cy.request({
+ url: '/signin',
+ followRedirect: false,
+ failOnStatusCode: false,
+ }).then((response) => {
+ expect(response.status).to.eq(302);
+ expect(response.redirectedToUrl).to.eq(
+ 'https://m.code.dev-theguardian.com/',
+ );
+ });
+ cy.mockNext(200, {
+ status: 'signedInRecently',
+ emailValidated: true,
+ });
+ });
- it('redirects to /reauthenticate when user with existing invalid session visits signin page', () => {
- cy.setCookie('SC_GU_U', 'sessionvalue');
- cy.setCookie('SC_GU_LA', 'la_value');
+ it('redirects to /reauthenticate when user with existing invalid session visits signin page', () => {
+ cy.setCookie('SC_GU_U', 'sessionvalue');
+ cy.setCookie('SC_GU_LA', 'la_value');
- cy.mockNext(200, {
- status: 'signedInNotRecently',
- emailValidated: true,
- });
- cy.visit('/signin?useIdapi=true');
+ cy.mockNext(200, {
+ status: 'signedInNotRecently',
+ emailValidated: true,
+ });
+ cy.visit('/signin?useIdapi=true');
- cy.location('pathname').should('eq', '/reauthenticate');
- });
- });
+ cy.location('pathname').should('eq', '/reauthenticate');
+ });
+ });
- context('General IDAPI failure', () => {
- it('displays a generic error message', function () {
- cy.mockNext(500);
- cy.visit(
- '/signin?returnUrl=https%3A%2F%2Flocalhost%3A8861%2Fsignin&useIdapi=true',
- );
- cy.get('input[name="email"]').type('example@example.com');
- cy.get('input[name="password"]').type('password');
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.contains('There was a problem signing in, please try again');
- });
- });
+ context('General IDAPI failure', () => {
+ it('displays a generic error message', function () {
+ cy.mockNext(500);
+ cy.visit(
+ '/signin?returnUrl=https%3A%2F%2Flocalhost%3A8861%2Fsignin&useIdapi=true',
+ );
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.get('input[name="password"]').type('password');
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.contains('There was a problem signing in, please try again');
+ });
+ });
- context('Redirect to post sign-in prompt', () => {
- const defaultReturnUrl = 'https://m.code.dev-theguardian.com';
- const returnUrl = 'https://www.theguardian.com/about';
+ context('Redirect to post sign-in prompt', () => {
+ const defaultReturnUrl = 'https://m.code.dev-theguardian.com';
+ const returnUrl = 'https://www.theguardian.com/about';
- beforeEach(() => {
- cy.mockAll(200, allConsents, CONSENTS_ENDPOINT);
- cy.mockAll(
- 200,
- verifiedUserWithNoConsent.user.consents,
- USER_CONSENTS_ENDPOINT,
- );
- // Intercept the pages that we would redirect to.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', '/signin/success*', (req) => {
- req.reply(200);
- });
- cy.intercept('GET', defaultReturnUrl, (req) => {
- req.reply(200);
- });
- cy.intercept('GET', returnUrl, (req) => {
- req.reply(200);
- });
- });
+ beforeEach(() => {
+ cy.mockAll(200, allConsents, CONSENTS_ENDPOINT);
+ cy.mockAll(
+ 200,
+ verifiedUserWithNoConsent.user.consents,
+ USER_CONSENTS_ENDPOINT,
+ );
+ // Intercept the pages that we would redirect to.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', '/signin/success*', (req) => {
+ req.reply(200);
+ });
+ cy.intercept('GET', defaultReturnUrl, (req) => {
+ req.reply(200);
+ });
+ cy.intercept('GET', returnUrl, (req) => {
+ req.reply(200);
+ });
+ });
- const signIn = (returnUrl = defaultReturnUrl) => {
- cy.visit(
- `/signin?returnUrl=${encodeURIComponent(returnUrl)}&useIdapi=true`,
- );
- cy.get('input[name="email"]').type('example@example.com');
- cy.get('input[name="password"]').type('password');
- cy.mockNext(200, {
- cookies: {
- values: [{ key: 'SC_GU_U', value: 'something' }],
- expiresAt: new Date(Date.now() + 1800000 /* 30min */).toISOString(),
- },
- });
- cy.get('[data-cy=main-form-submit-button]').click();
- };
+ const signIn = (returnUrl = defaultReturnUrl) => {
+ cy.visit(
+ `/signin?returnUrl=${encodeURIComponent(returnUrl)}&useIdapi=true`,
+ );
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.get('input[name="password"]').type('password');
+ cy.mockNext(200, {
+ cookies: {
+ values: [{ key: 'SC_GU_U', value: 'something' }],
+ expiresAt: new Date(Date.now() + 1800000 /* 30min */).toISOString(),
+ },
+ });
+ cy.get('[data-cy=main-form-submit-button]').click();
+ };
- it('if all conditions met', () => {
- signIn();
- cy.url().should('include', `/signin/success`);
- cy.url().should('include', encodeURIComponent(defaultReturnUrl));
- });
+ it('if all conditions met', () => {
+ signIn();
+ cy.url().should('include', `/signin/success`);
+ cy.url().should('include', encodeURIComponent(defaultReturnUrl));
+ });
- it('unless returnUrl is not default', () => {
- signIn(returnUrl);
- cy.url().should('include', returnUrl);
- });
+ it('unless returnUrl is not default', () => {
+ signIn(returnUrl);
+ cy.url().should('include', returnUrl);
+ });
- it('unless experiment already viewed', () => {
- cy.setCookie(
- 'GU_ran_experiments',
- new URLSearchParams({
- OptInPromptPostSignIn: Date.now().toString(),
- }).toString(),
- );
- signIn();
- cy.url().should('include', defaultReturnUrl);
- });
+ it('unless experiment already viewed', () => {
+ cy.setCookie(
+ 'GU_ran_experiments',
+ new URLSearchParams({
+ OptInPromptPostSignIn: Date.now().toString(),
+ }).toString(),
+ );
+ signIn();
+ cy.url().should('include', defaultReturnUrl);
+ });
- it('if no consent information for user', () => {
- cy.mockAll(200, [], USER_CONSENTS_ENDPOINT);
- signIn();
- cy.url().should('include', `/signin/success`);
- cy.url().should('include', encodeURIComponent(defaultReturnUrl));
- });
+ it('if no consent information for user', () => {
+ cy.mockAll(200, [], USER_CONSENTS_ENDPOINT);
+ signIn();
+ cy.url().should('include', `/signin/success`);
+ cy.url().should('include', encodeURIComponent(defaultReturnUrl));
+ });
- it('unless user has already consented', () => {
- const supporterConsent = allConsents.find(({ id }) => id === 'supporter');
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- const consentData = [{ ...supporterConsent!, consented: true }];
- cy.mockAll(200, consentData, USER_CONSENTS_ENDPOINT);
- signIn();
- cy.url().should('include', defaultReturnUrl);
- });
+ it('unless user has already consented', () => {
+ const supporterConsent = allConsents.find(({ id }) => id === 'supporter');
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ const consentData = [{ ...supporterConsent!, consented: true }];
+ cy.mockAll(200, consentData, USER_CONSENTS_ENDPOINT);
+ signIn();
+ cy.url().should('include', defaultReturnUrl);
+ });
- it('unless fetching consents fails', () => {
- cy.mockAll(500, undefined, CONSENTS_ENDPOINT);
- signIn();
- cy.url().should('include', defaultReturnUrl);
- });
+ it('unless fetching consents fails', () => {
+ cy.mockAll(500, undefined, CONSENTS_ENDPOINT);
+ signIn();
+ cy.url().should('include', defaultReturnUrl);
+ });
- it('unless fetching user consents fails', () => {
- cy.mockAll(500, undefined, USER_CONSENTS_ENDPOINT);
- signIn();
- cy.url().should('include', defaultReturnUrl);
- });
- });
+ it('unless fetching user consents fails', () => {
+ cy.mockAll(500, undefined, USER_CONSENTS_ENDPOINT);
+ signIn();
+ cy.url().should('include', defaultReturnUrl);
+ });
+ });
});
diff --git a/cypress/integration/mocked/sign_out.2.cy.ts b/cypress/integration/mocked/sign_out.2.cy.ts
index 251c715217..09115be6ee 100644
--- a/cypress/integration/mocked/sign_out.2.cy.ts
+++ b/cypress/integration/mocked/sign_out.2.cy.ts
@@ -1,66 +1,66 @@
import { authCookieResponse } from '../../support/idapi/cookie';
describe('Sign out flow', () => {
- const DotComCookies = [
- 'gu_user_features_expiry',
- 'gu_paying_member',
- 'gu_recurring_contributor',
- 'gu_digital_subscriber',
- ];
+ const DotComCookies = [
+ 'gu_user_features_expiry',
+ 'gu_paying_member',
+ 'gu_recurring_contributor',
+ 'gu_digital_subscriber',
+ ];
- context('Signs a user out', () => {
- beforeEach(() => {
- cy.mockPurge();
- // Disable redirect to /signin/success by default
- cy.setCookie(
- 'GU_ran_experiments',
- new URLSearchParams({
- OptInPromptPostSignIn: Date.now().toString(),
- }).toString(),
- );
- });
+ context('Signs a user out', () => {
+ beforeEach(() => {
+ cy.mockPurge();
+ // Disable redirect to /signin/success by default
+ cy.setCookie(
+ 'GU_ran_experiments',
+ new URLSearchParams({
+ OptInPromptPostSignIn: Date.now().toString(),
+ }).toString(),
+ );
+ });
- it('Removes IDAPI log in cookies and dotcom cookies when signing out', () => {
- const returnUrl = `https://${Cypress.env('BASE_URI')}/reset-password`;
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.visit(
- `/signin?returnUrl=${encodeURIComponent(returnUrl)}&useIdapi=true`,
- );
- cy.get('input[name="email"]').type('example@example.com');
- cy.get('input[name="password"]').type('password');
- cy.mockNext(200, {
- status: 'ok',
- ...authCookieResponse,
- });
- cy.get('[data-cy=main-form-submit-button]').click();
- cy.url().should('eq', returnUrl);
+ it('Removes IDAPI log in cookies and dotcom cookies when signing out', () => {
+ const returnUrl = `https://${Cypress.env('BASE_URI')}/reset-password`;
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.visit(
+ `/signin?returnUrl=${encodeURIComponent(returnUrl)}&useIdapi=true`,
+ );
+ cy.get('input[name="email"]').type('example@example.com');
+ cy.get('input[name="password"]').type('password');
+ cy.mockNext(200, {
+ status: 'ok',
+ ...authCookieResponse,
+ });
+ cy.get('[data-cy=main-form-submit-button]').click();
+ cy.url().should('eq', returnUrl);
- cy.getCookie('SC_GU_U').should('exist');
- cy.getCookie('SC_GU_LA').should('exist');
- cy.getCookie('GU_U').should('exist');
+ cy.getCookie('SC_GU_U').should('exist');
+ cy.getCookie('SC_GU_LA').should('exist');
+ cy.getCookie('GU_U').should('exist');
- cy.mockNext(200, {
- status: 'ok',
- cookies: {
- values: [
- {
- key: 'GU_SO',
- value: 'the_GU_SO_cookie',
- },
- ],
- expiresAt: new Date(Date.now() + 1800000 /* 30min */).toISOString(),
- },
- });
+ cy.mockNext(200, {
+ status: 'ok',
+ cookies: {
+ values: [
+ {
+ key: 'GU_SO',
+ value: 'the_GU_SO_cookie',
+ },
+ ],
+ expiresAt: new Date(Date.now() + 1800000 /* 30min */).toISOString(),
+ },
+ });
- cy.visit(`/signout?returnUrl=${encodeURIComponent(returnUrl)}`);
- cy.getCookie('GU_SO').should('exist');
- cy.getCookie('SC_GU_U').should('not.exist');
- cy.getCookie('SC_GU_LA').should('not.exist');
- cy.getCookie('GU_U').should('not.exist');
- DotComCookies.forEach((cookie) => {
- cy.getCookie(cookie).should('not.exist');
- });
- });
- });
+ cy.visit(`/signout?returnUrl=${encodeURIComponent(returnUrl)}`);
+ cy.getCookie('GU_SO').should('exist');
+ cy.getCookie('SC_GU_U').should('not.exist');
+ cy.getCookie('SC_GU_LA').should('not.exist');
+ cy.getCookie('GU_U').should('not.exist');
+ DotComCookies.forEach((cookie) => {
+ cy.getCookie(cookie).should('not.exist');
+ });
+ });
+ });
});
diff --git a/cypress/integration/mocked/unsubscribe.5.cy.ts b/cypress/integration/mocked/unsubscribe.5.cy.ts
index b8cccca7e2..8fed9c3194 100644
--- a/cypress/integration/mocked/unsubscribe.5.cy.ts
+++ b/cypress/integration/mocked/unsubscribe.5.cy.ts
@@ -1,65 +1,65 @@
import { injectAndCheckAxe } from '../../support/cypress-axe';
describe('Unsubscribe newsletter/marketing email', () => {
- beforeEach(() => {
- cy.mockPurge();
- });
+ beforeEach(() => {
+ cy.mockPurge();
+ });
- context('a11y checks', () => {
- it('Has no detectable a11y violations on unsubscribe complete page', () => {
- cy.mockNext(200);
- cy.visit(
- '/unsubscribe/newsletter/pushing-buttons%3A1000000%3A1677075570/token',
- );
- injectAndCheckAxe();
- });
+ context('a11y checks', () => {
+ it('Has no detectable a11y violations on unsubscribe complete page', () => {
+ cy.mockNext(200);
+ cy.visit(
+ '/unsubscribe/newsletter/pushing-buttons%3A1000000%3A1677075570/token',
+ );
+ injectAndCheckAxe();
+ });
- it('Has no detectable a11y violations on unsubscribe error page', () => {
- cy.mockNext(400);
- cy.visit(
- '/unsubscribe/newsletter/pushing-buttons%3A1000000%3A1677075570/token',
- );
- injectAndCheckAxe();
- });
- });
+ it('Has no detectable a11y violations on unsubscribe error page', () => {
+ cy.mockNext(400);
+ cy.visit(
+ '/unsubscribe/newsletter/pushing-buttons%3A1000000%3A1677075570/token',
+ );
+ injectAndCheckAxe();
+ });
+ });
- context('unsubscribe flow', () => {
- it('should be able to unsubscribe from a newsletter', () => {
- cy.mockNext(200);
- cy.visit(
- '/unsubscribe/newsletter/pushing-buttons%3A1000000%3A1677075570/token',
- );
- cy.contains('You have been unsubscribed.');
- });
+ context('unsubscribe flow', () => {
+ it('should be able to unsubscribe from a newsletter', () => {
+ cy.mockNext(200);
+ cy.visit(
+ '/unsubscribe/newsletter/pushing-buttons%3A1000000%3A1677075570/token',
+ );
+ cy.contains('You have been unsubscribed.');
+ });
- it('should be able to unsubscribe from a marketing email', () => {
- cy.mockNext(200);
- cy.visit('/unsubscribe/marketing/supporter%3A1000000%3A1677075570/token');
- cy.contains('You have been unsubscribed.');
- });
+ it('should be able to unsubscribe from a marketing email', () => {
+ cy.mockNext(200);
+ cy.visit('/unsubscribe/marketing/supporter%3A1000000%3A1677075570/token');
+ cy.contains('You have been unsubscribed.');
+ });
- it('should be able to handle a unsubscribe error if emailType is not newsletter/marketing', () => {
- cy.visit('/unsubscribe/fake/supporter%3A1000000%3A1677075570/token');
- cy.contains('Unable to unsubscribe.');
- });
+ it('should be able to handle a unsubscribe error if emailType is not newsletter/marketing', () => {
+ cy.visit('/unsubscribe/fake/supporter%3A1000000%3A1677075570/token');
+ cy.contains('Unable to unsubscribe.');
+ });
- it('should be able to handle a unsubscribe error if data is not valid', () => {
- cy.visit(
- '/unsubscribe/newsletter/pushing-buttons%3A1000000%3A16770755abc70/token',
- );
- cy.contains('Unable to unsubscribe.');
+ it('should be able to handle a unsubscribe error if data is not valid', () => {
+ cy.visit(
+ '/unsubscribe/newsletter/pushing-buttons%3A1000000%3A16770755abc70/token',
+ );
+ cy.contains('Unable to unsubscribe.');
- cy.visit('/unsubscribe/newsletter/pushing-buttons%3A1000000%3A/token');
- cy.contains('Unable to unsubscribe.');
+ cy.visit('/unsubscribe/newsletter/pushing-buttons%3A1000000%3A/token');
+ cy.contains('Unable to unsubscribe.');
- cy.visit('/unsubscribe/newsletter/pushing-buttons-bad-data/token');
- cy.contains('Unable to unsubscribe.');
- });
+ cy.visit('/unsubscribe/newsletter/pushing-buttons-bad-data/token');
+ cy.contains('Unable to unsubscribe.');
+ });
- it('should be able to handle a unsubscribe error if api error', () => {
- cy.mockNext(400);
- cy.visit('/unsubscribe/fake/supporter%3A1000000%3A1677075570/token');
- cy.contains('Unable to unsubscribe.');
- });
- });
+ it('should be able to handle a unsubscribe error if api error', () => {
+ cy.mockNext(400);
+ cy.visit('/unsubscribe/fake/supporter%3A1000000%3A1677075570/token');
+ cy.contains('Unable to unsubscribe.');
+ });
+ });
});
diff --git a/cypress/integration/mocked/verify_email.4.cy.ts b/cypress/integration/mocked/verify_email.4.cy.ts
index eede2df06a..02f1f4abdb 100644
--- a/cypress/integration/mocked/verify_email.4.cy.ts
+++ b/cypress/integration/mocked/verify_email.4.cy.ts
@@ -5,317 +5,317 @@ import { allConsents } from '../../support/idapi/consent';
import { authCookieResponse, setAuthCookies } from '../../support/idapi/cookie';
import { verifiedUserWithNoConsent } from '../../support/idapi/user';
import {
- validationTokenExpired,
- validationTokenInvalid,
+ validationTokenExpired,
+ validationTokenInvalid,
} from '../../support/idapi/verify_email';
import VerifyEmail from '../../support/pages/verify_email';
describe('Verify email flow', () => {
- const verifyEmailFlow = new VerifyEmail();
+ const verifyEmailFlow = new VerifyEmail();
- beforeEach(() => {
- cy.mockPurge();
- cy.visit('/signin?useIdapi=true');
- });
+ beforeEach(() => {
+ cy.mockPurge();
+ cy.visit('/signin?useIdapi=true');
+ });
- context('A11y checks', () => {
- it('has no detectable a11y violations on logged out resend validation email page', () => {
- // mock token expired
- cy.mockNext(403, validationTokenExpired);
+ context('A11y checks', () => {
+ it('has no detectable a11y violations on logged out resend validation email page', () => {
+ // mock token expired
+ cy.mockNext(403, validationTokenExpired);
- // go to verify email endpont
- verifyEmailFlow.goto('expiredtoken', { failOnStatusCode: false });
+ // go to verify email endpont
+ verifyEmailFlow.goto('expiredtoken', { failOnStatusCode: false });
- injectAndCheckAxe();
- });
+ injectAndCheckAxe();
+ });
- it('has no detectable a11y violations on logged in resend validation email page', () => {
- // set logged in cookies
- setAuthCookies();
+ it('has no detectable a11y violations on logged in resend validation email page', () => {
+ // set logged in cookies
+ setAuthCookies();
- // mock token expired
- cy.mockNext(403, validationTokenExpired);
+ // mock token expired
+ cy.mockNext(403, validationTokenExpired);
- // mock user response
- cy.mockNext(200, verifiedUserWithNoConsent);
+ // mock user response
+ cy.mockNext(200, verifiedUserWithNoConsent);
- // mock user response again for sending validation email
- cy.mockNext(200, verifiedUserWithNoConsent);
+ // mock user response again for sending validation email
+ cy.mockNext(200, verifiedUserWithNoConsent);
- // mock validation email sent
- cy.mockNext(200);
+ // mock validation email sent
+ cy.mockNext(200);
- // go to verify email endpont
- verifyEmailFlow.goto('expiredtoken', { failOnStatusCode: false });
+ // go to verify email endpont
+ verifyEmailFlow.goto('expiredtoken', { failOnStatusCode: false });
- // check a11y before clicking send email
- injectAndCheckAxe();
+ // check a11y before clicking send email
+ injectAndCheckAxe();
- // click on send link button
- cy.contains(VerifyEmail.CONTENT.SEND_LINK).click();
- // check a11y after clicking send email
- injectAndCheckAxe();
- });
- });
+ // click on send link button
+ cy.contains(VerifyEmail.CONTENT.SEND_LINK).click();
+ // check a11y after clicking send email
+ injectAndCheckAxe();
+ });
+ });
- context('Verify email', () => {
- it('successfully verifies the email using a token and sets auth cookies', () => {
- // mock validation success response (200 with auth cookies)
- cy.mockNext(200, authCookieResponse);
+ context('Verify email', () => {
+ it('successfully verifies the email using a token and sets auth cookies', () => {
+ // mock validation success response (200 with auth cookies)
+ cy.mockNext(200, authCookieResponse);
- // set these cookies manually
- // TODO: can cypress set the automatically?
- setAuthCookies();
+ // set these cookies manually
+ // TODO: can cypress set the automatically?
+ setAuthCookies();
- // set successful auth using login middleware
- cy.mockNext(200, authRedirectSignInRecentlyEmailValidated);
+ // set successful auth using login middleware
+ cy.mockNext(200, authRedirectSignInRecentlyEmailValidated);
- // all newsletters mock response for first page of consents flow
- cy.mockNext(200, allConsents);
+ // all newsletters mock response for first page of consents flow
+ cy.mockNext(200, allConsents);
- // user newsletters mock response for first page of consents flow
- cy.mockNext(200, verifiedUserWithNoConsent.user.consents);
+ // user newsletters mock response for first page of consents flow
+ cy.mockNext(200, verifiedUserWithNoConsent.user.consents);
- // go to verify email endpoint
- verifyEmailFlow.goto('avalidtoken', { query: { useIdapi: 'true' } });
+ // go to verify email endpoint
+ verifyEmailFlow.goto('avalidtoken', { query: { useIdapi: 'true' } });
- // check if verified email text exists
- cy.contains(VerifyEmail.CONTENT.EMAIL_VERIFIED);
+ // check if verified email text exists
+ cy.contains(VerifyEmail.CONTENT.EMAIL_VERIFIED);
- // check if we're on the consents flow
- cy.url().should('include', '/consents');
- });
+ // check if we're on the consents flow
+ cy.url().should('include', '/consents');
+ });
- it('successfully verifies the email using a token and sets auth cookies, and preserves encoded return url', () => {
- // mock validation success response (200 with auth cookies)
- cy.mockNext(200, authCookieResponse);
+ it('successfully verifies the email using a token and sets auth cookies, and preserves encoded return url', () => {
+ // mock validation success response (200 with auth cookies)
+ cy.mockNext(200, authCookieResponse);
- // set these cookies manually
- // TODO: can cypress set the automatically?
- setAuthCookies();
+ // set these cookies manually
+ // TODO: can cypress set the automatically?
+ setAuthCookies();
- // set successful auth using login middleware
- cy.mockNext(200, authRedirectSignInRecentlyEmailValidated);
+ // set successful auth using login middleware
+ cy.mockNext(200, authRedirectSignInRecentlyEmailValidated);
- // all newsletters mock response for first page of consents flow
- cy.mockNext(200, allConsents);
+ // all newsletters mock response for first page of consents flow
+ cy.mockNext(200, allConsents);
- // user newsletters mock response for first page of consents flow
- cy.mockNext(200, verifiedUserWithNoConsent.user.consents);
+ // user newsletters mock response for first page of consents flow
+ cy.mockNext(200, verifiedUserWithNoConsent.user.consents);
- const returnUrl = encodeURIComponent(
- `https://www.theguardian.com/science/grrlscientist/2012/aug/07/3`,
- );
-
- // go to verify email endpoint
- verifyEmailFlow.goto('avalidtoken', {
- query: {
- returnUrl,
- useIdapi: 'true',
- },
- });
-
- // check if verified email text exists
- cy.contains(VerifyEmail.CONTENT.EMAIL_VERIFIED);
-
- // check if we're on the consents flow
- cy.url().should('include', '/consents');
-
- // check return url exists
- cy.url().should('include', `returnUrl=${returnUrl}`);
- });
+ const returnUrl = encodeURIComponent(
+ `https://www.theguardian.com/science/grrlscientist/2012/aug/07/3`,
+ );
+
+ // go to verify email endpoint
+ verifyEmailFlow.goto('avalidtoken', {
+ query: {
+ returnUrl,
+ useIdapi: 'true',
+ },
+ });
+
+ // check if verified email text exists
+ cy.contains(VerifyEmail.CONTENT.EMAIL_VERIFIED);
+
+ // check if we're on the consents flow
+ cy.url().should('include', '/consents');
+
+ // check return url exists
+ cy.url().should('include', `returnUrl=${returnUrl}`);
+ });
- it('successfully verifies the email using a token and sets auth cookies, and preserves and encodes return url', () => {
- // mock validation success response (200 with auth cookies)
- cy.mockNext(200, authCookieResponse);
+ it('successfully verifies the email using a token and sets auth cookies, and preserves and encodes return url', () => {
+ // mock validation success response (200 with auth cookies)
+ cy.mockNext(200, authCookieResponse);
- // set these cookies manually
- // TODO: can cypress set the automatically?
- setAuthCookies();
-
- // set successful auth using login middleware
- cy.mockNext(200, authRedirectSignInRecentlyEmailValidated);
-
- // all newsletters mock response for first page of consents flow
- cy.mockNext(200, allConsents);
-
- // user newsletters mock response for first page of consents flow
- cy.mockNext(200, verifiedUserWithNoConsent.user.consents);
-
- const returnUrl = `https://www.theguardian.com/science/grrlscientist/2012/aug/07/3`;
-
- // go to verify email endpoint
- verifyEmailFlow.goto('avalidtoken', {
- query: {
- returnUrl,
- useIdapi: 'true',
- },
- });
-
- // check if verified email text exists
- cy.contains(VerifyEmail.CONTENT.EMAIL_VERIFIED);
-
- // check if we're on the consents flow
- cy.url().should('include', '/consents');
+ // set these cookies manually
+ // TODO: can cypress set the automatically?
+ setAuthCookies();
+
+ // set successful auth using login middleware
+ cy.mockNext(200, authRedirectSignInRecentlyEmailValidated);
+
+ // all newsletters mock response for first page of consents flow
+ cy.mockNext(200, allConsents);
+
+ // user newsletters mock response for first page of consents flow
+ cy.mockNext(200, verifiedUserWithNoConsent.user.consents);
+
+ const returnUrl = `https://www.theguardian.com/science/grrlscientist/2012/aug/07/3`;
+
+ // go to verify email endpoint
+ verifyEmailFlow.goto('avalidtoken', {
+ query: {
+ returnUrl,
+ useIdapi: 'true',
+ },
+ });
+
+ // check if verified email text exists
+ cy.contains(VerifyEmail.CONTENT.EMAIL_VERIFIED);
+
+ // check if we're on the consents flow
+ cy.url().should('include', '/consents');
- // check return url exists
- cy.url().should('include', `returnUrl=${encodeURIComponent(returnUrl)}`);
- });
+ // check return url exists
+ cy.url().should('include', `returnUrl=${encodeURIComponent(returnUrl)}`);
+ });
- it('verification token is expired, logged out, shows page to sign in to resend validation email', () => {
- const signInUrl = Cypress.env('SIGN_IN_PAGE_URL');
- // mock token expired
- cy.mockNext(403, validationTokenExpired);
+ it('verification token is expired, logged out, shows page to sign in to resend validation email', () => {
+ const signInUrl = Cypress.env('SIGN_IN_PAGE_URL');
+ // mock token expired
+ cy.mockNext(403, validationTokenExpired);
- // go to verify email endpont
- verifyEmailFlow.goto('expiredtoken', {
- failOnStatusCode: false,
- query: { useIdapi: 'true' },
- });
-
- cy.contains(VerifyEmail.CONTENT.LINK_EXPIRED);
- cy.contains(VerifyEmail.CONTENT.TOKEN_EXPIRED);
-
- // check sign in link
- cy.contains('a', VerifyEmail.CONTENT.SIGN_IN)
- .should('have.attr', 'href')
- .and(
- 'include',
- `${signInUrl}?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/verify-email`,
- )}`,
- );
- });
-
- it('verification token is invalid, logged out, shows page to sign in to resend validation email', () => {
- const signInUrl = Cypress.env('SIGN_IN_PAGE_URL');
- // mock token invalid
- cy.mockNext(403, validationTokenInvalid);
-
- // go to verify email endpont
- verifyEmailFlow.goto('aninvalidtoken', {
- failOnStatusCode: false,
- query: { useIdapi: 'true' },
- });
-
- cy.contains(VerifyEmail.CONTENT.LINK_EXPIRED);
- cy.contains(VerifyEmail.CONTENT.TOKEN_EXPIRED);
-
- // check sign in link
- cy.contains('a', VerifyEmail.CONTENT.SIGN_IN)
- .should('have.attr', 'href')
- .and(
- 'include',
- `${signInUrl}?returnUrl=${encodeURIComponent(
- `https://${Cypress.env('BASE_URI')}/verify-email`,
- )}`,
- );
- });
-
- it('verification token is expired, logged in, shows page to to resend validation email', () => {
- // set logged in cookies
- setAuthCookies();
-
- // mock token expired
- cy.mockNext(403, validationTokenExpired);
-
- // mock user response
- cy.mockNext(200, verifiedUserWithNoConsent);
-
- // mock user response again for sending validation email
- cy.mockNext(200, verifiedUserWithNoConsent);
-
- // mock validation email sent
- cy.mockNext(200);
-
- // go to verify email endpont
- verifyEmailFlow.goto('expiredtoken', {
- failOnStatusCode: false,
- query: { useIdapi: 'true' },
- });
-
- cy.contains(VerifyEmail.CONTENT.VERIFY_EMAIL);
- cy.contains(VerifyEmail.CONTENT.CONFIRM_EMAIL);
- cy.contains(verifiedUserWithNoConsent.user.primaryEmailAddress);
-
- // click on send link button
- cy.contains(VerifyEmail.CONTENT.SEND_LINK).click();
-
- // expect email sent page
- cy.contains(VerifyEmail.CONTENT.EMAIL_SENT);
- });
-
- it('verification token is invalid, logged in, shows page to to resend validation email, and send email', () => {
- // set logged in cookies
- setAuthCookies();
-
- // mock token invalid
- cy.mockNext(403, validationTokenInvalid);
-
- // mock user response
- cy.mockNext(200, verifiedUserWithNoConsent);
-
- // mock user response again for sending validation email
- cy.mockNext(200, verifiedUserWithNoConsent);
-
- // mock validation email sent
- cy.mockNext(200);
-
- // go to verify email endpont
- verifyEmailFlow.goto('expiredtoken', {
- failOnStatusCode: false,
- query: { useIdapi: 'true' },
- });
-
- cy.contains(VerifyEmail.CONTENT.VERIFY_EMAIL);
- cy.contains(VerifyEmail.CONTENT.CONFIRM_EMAIL);
- cy.contains(verifiedUserWithNoConsent.user.primaryEmailAddress);
-
- // click on send link button
- cy.contains(VerifyEmail.CONTENT.SEND_LINK).click();
-
- // expect email sent page
- cy.contains(VerifyEmail.CONTENT.EMAIL_SENT);
- });
-
- it('verification token is invalid, logged in, shows page to to resend validation email and shows recaptcha error message when reCAPTCHA token request fails', () => {
- // set logged in cookies
- setAuthCookies();
-
- // mock token invalid
- cy.mockNext(403, validationTokenInvalid);
-
- // mock user response
- cy.mockNext(200, verifiedUserWithNoConsent);
-
- // mock user response again for sending validation email
- cy.mockNext(200, verifiedUserWithNoConsent);
-
- // mock validation email sent
- cy.mockNext(200);
-
- // go to verify email endpont
- verifyEmailFlow.goto('expiredtoken', {
- failOnStatusCode: false,
- query: { useIdapi: 'true' },
- });
+ // go to verify email endpont
+ verifyEmailFlow.goto('expiredtoken', {
+ failOnStatusCode: false,
+ query: { useIdapi: 'true' },
+ });
+
+ cy.contains(VerifyEmail.CONTENT.LINK_EXPIRED);
+ cy.contains(VerifyEmail.CONTENT.TOKEN_EXPIRED);
+
+ // check sign in link
+ cy.contains('a', VerifyEmail.CONTENT.SIGN_IN)
+ .should('have.attr', 'href')
+ .and(
+ 'include',
+ `${signInUrl}?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/verify-email`,
+ )}`,
+ );
+ });
+
+ it('verification token is invalid, logged out, shows page to sign in to resend validation email', () => {
+ const signInUrl = Cypress.env('SIGN_IN_PAGE_URL');
+ // mock token invalid
+ cy.mockNext(403, validationTokenInvalid);
+
+ // go to verify email endpont
+ verifyEmailFlow.goto('aninvalidtoken', {
+ failOnStatusCode: false,
+ query: { useIdapi: 'true' },
+ });
+
+ cy.contains(VerifyEmail.CONTENT.LINK_EXPIRED);
+ cy.contains(VerifyEmail.CONTENT.TOKEN_EXPIRED);
+
+ // check sign in link
+ cy.contains('a', VerifyEmail.CONTENT.SIGN_IN)
+ .should('have.attr', 'href')
+ .and(
+ 'include',
+ `${signInUrl}?returnUrl=${encodeURIComponent(
+ `https://${Cypress.env('BASE_URI')}/verify-email`,
+ )}`,
+ );
+ });
+
+ it('verification token is expired, logged in, shows page to to resend validation email', () => {
+ // set logged in cookies
+ setAuthCookies();
+
+ // mock token expired
+ cy.mockNext(403, validationTokenExpired);
+
+ // mock user response
+ cy.mockNext(200, verifiedUserWithNoConsent);
+
+ // mock user response again for sending validation email
+ cy.mockNext(200, verifiedUserWithNoConsent);
+
+ // mock validation email sent
+ cy.mockNext(200);
+
+ // go to verify email endpont
+ verifyEmailFlow.goto('expiredtoken', {
+ failOnStatusCode: false,
+ query: { useIdapi: 'true' },
+ });
+
+ cy.contains(VerifyEmail.CONTENT.VERIFY_EMAIL);
+ cy.contains(VerifyEmail.CONTENT.CONFIRM_EMAIL);
+ cy.contains(verifiedUserWithNoConsent.user.primaryEmailAddress);
+
+ // click on send link button
+ cy.contains(VerifyEmail.CONTENT.SEND_LINK).click();
+
+ // expect email sent page
+ cy.contains(VerifyEmail.CONTENT.EMAIL_SENT);
+ });
+
+ it('verification token is invalid, logged in, shows page to to resend validation email, and send email', () => {
+ // set logged in cookies
+ setAuthCookies();
+
+ // mock token invalid
+ cy.mockNext(403, validationTokenInvalid);
+
+ // mock user response
+ cy.mockNext(200, verifiedUserWithNoConsent);
+
+ // mock user response again for sending validation email
+ cy.mockNext(200, verifiedUserWithNoConsent);
+
+ // mock validation email sent
+ cy.mockNext(200);
+
+ // go to verify email endpont
+ verifyEmailFlow.goto('expiredtoken', {
+ failOnStatusCode: false,
+ query: { useIdapi: 'true' },
+ });
+
+ cy.contains(VerifyEmail.CONTENT.VERIFY_EMAIL);
+ cy.contains(VerifyEmail.CONTENT.CONFIRM_EMAIL);
+ cy.contains(verifiedUserWithNoConsent.user.primaryEmailAddress);
+
+ // click on send link button
+ cy.contains(VerifyEmail.CONTENT.SEND_LINK).click();
+
+ // expect email sent page
+ cy.contains(VerifyEmail.CONTENT.EMAIL_SENT);
+ });
+
+ it('verification token is invalid, logged in, shows page to to resend validation email and shows recaptcha error message when reCAPTCHA token request fails', () => {
+ // set logged in cookies
+ setAuthCookies();
+
+ // mock token invalid
+ cy.mockNext(403, validationTokenInvalid);
+
+ // mock user response
+ cy.mockNext(200, verifiedUserWithNoConsent);
+
+ // mock user response again for sending validation email
+ cy.mockNext(200, verifiedUserWithNoConsent);
+
+ // mock validation email sent
+ cy.mockNext(200);
+
+ // go to verify email endpont
+ verifyEmailFlow.goto('expiredtoken', {
+ failOnStatusCode: false,
+ query: { useIdapi: 'true' },
+ });
- cy.contains(VerifyEmail.CONTENT.VERIFY_EMAIL);
- cy.contains(VerifyEmail.CONTENT.CONFIRM_EMAIL);
- cy.contains(verifiedUserWithNoConsent.user.primaryEmailAddress);
+ cy.contains(VerifyEmail.CONTENT.VERIFY_EMAIL);
+ cy.contains(VerifyEmail.CONTENT.CONFIRM_EMAIL);
+ cy.contains(verifiedUserWithNoConsent.user.primaryEmailAddress);
- cy.intercept('POST', 'https://www.google.com/recaptcha/api2/**', {
- statusCode: 500,
- });
+ cy.intercept('POST', 'https://www.google.com/recaptcha/api2/**', {
+ statusCode: 500,
+ });
- cy.contains(VerifyEmail.CONTENT.SEND_LINK).click();
- cy.contains('Google reCAPTCHA verification failed. Please try again.');
+ cy.contains(VerifyEmail.CONTENT.SEND_LINK).click();
+ cy.contains('Google reCAPTCHA verification failed. Please try again.');
- // show extended reCaptcha message on the second failure
- cy.contains(VerifyEmail.CONTENT.SEND_LINK).click();
- cy.contains('Google reCAPTCHA verification failed.');
- cy.contains('If the problem persists please try the following:');
- cy.contains('userhelp@');
- });
- });
+ // show extended reCaptcha message on the second failure
+ cy.contains(VerifyEmail.CONTENT.SEND_LINK).click();
+ cy.contains('Google reCAPTCHA verification failed.');
+ cy.contains('If the problem persists please try the following:');
+ cy.contains('userhelp@');
+ });
+ });
});
diff --git a/cypress/integration/mocked/welcome.4.cy.ts b/cypress/integration/mocked/welcome.4.cy.ts
index 48d11d9e8f..ce6edee69d 100644
--- a/cypress/integration/mocked/welcome.4.cy.ts
+++ b/cypress/integration/mocked/welcome.4.cy.ts
@@ -1,329 +1,329 @@
import { injectAndCheckAxe } from '../../support/cypress-axe';
import {
- authRedirectSignInRecentlyEmailValidated,
- AUTH_REDIRECT_ENDPOINT,
+ authRedirectSignInRecentlyEmailValidated,
+ AUTH_REDIRECT_ENDPOINT,
} from '../../support/idapi/auth';
import { allConsents, CONSENTS_ENDPOINT } from '../../support/idapi/consent';
import { setAuthCookies } from '../../support/idapi/cookie';
import {
- verifiedUserWithNoConsent,
- USER_ENDPOINT,
- USER_CONSENTS_ENDPOINT,
+ verifiedUserWithNoConsent,
+ USER_ENDPOINT,
+ USER_CONSENTS_ENDPOINT,
} from '../../support/idapi/user';
import CommunicationsPage from '../../support/pages/onboarding/communications_page';
describe('Welcome and set password page', () => {
- const defaultEmail = 'someone@theguardian.com';
- const checkTokenSuccessResponse = (
- timeUntilExpiry: number | null = null,
- email = defaultEmail,
- ) => ({
- user: {
- primaryEmailAddress: email,
- },
- timeUntilExpiry,
- });
-
- const fakeCookieSuccessResponse = {
- cookies: {
- values: [
- {
- key: 'GU_U',
- value: 'FAKE_VALUE_0',
- },
- {
- key: 'SC_GU_LA',
- value: 'FAKE_VALUE_1',
- sessionCookie: true,
- },
- {
- key: 'SC_GU_U',
- value: 'FAKE_VALUE_2',
- },
- ],
- expiresAt: new Date(Date.now() + 1800000 /* 30min */).toISOString(),
- },
- };
-
- const fakeGroupAddResponse = {
- status: 'ok',
- groupCode: 'GRS',
- };
-
- const setPasswordAndSignIn = () => {
- cy.mockNext(200, checkTokenSuccessResponse());
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.mockNext(200, fakeCookieSuccessResponse);
- cy.mockAll(
- 200,
- authRedirectSignInRecentlyEmailValidated,
- AUTH_REDIRECT_ENDPOINT,
- );
- cy.mockAll(200, allConsents, CONSENTS_ENDPOINT);
- // cy.mockAll(200, verifiedUserWithNoConsent, USER_ENDPOINT);
- cy.mockAll(
- 200,
- verifiedUserWithNoConsent.user.consents,
- USER_CONSENTS_ENDPOINT,
- );
- cy.visit(`/welcome/fake_token?useIdapi=true`);
- cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
- cy.wait('@breachCheck');
- cy.get('button[type="submit"]').click();
- };
-
- beforeEach(() => {
- cy.mockPurge();
- });
-
- context('A11y checks', () => {
- it('has no detectable a11y violations on the set password page', () => {
- cy.mockNext(200, checkTokenSuccessResponse());
- cy.visit(`/welcome/fake_token?useIdapi=true`);
- injectAndCheckAxe();
- });
-
- it('has no detectable a11y violations on set password page with global error', () => {
- cy.mockNext(200, checkTokenSuccessResponse());
- cy.visit(`/welcome/fake_token?useIdapi=true`);
- cy.mockNext(500);
- cy.get('input[name="password"]').type('short');
- cy.get('button[type="submit"]').click();
- injectAndCheckAxe();
- });
-
- it('has no detectable a11y violations on the resend page', () => {
- cy.visit(`/welcome/resend?useIdapi=true`);
- injectAndCheckAxe();
- });
-
- it('has no detectable a11y violations on the resend page with global error', () => {
- cy.visit(`/welcome/resend?useIdapi=true`);
-
- cy.mockNext(500);
- cy.get('input[name="email"]').type(
- checkTokenSuccessResponse().user.primaryEmailAddress,
- );
- cy.get('button[type="submit"]').click();
- injectAndCheckAxe();
- });
-
- it('has no detectable a11y violations on the email sent page with resend box', () => {
- cy.visit(`/welcome/resend?useIdapi=true`);
-
- cy.mockNext(200);
- cy.get('input[name="email"]').type(
- checkTokenSuccessResponse().user.primaryEmailAddress,
- );
- cy.get('button[type="submit"]').click();
- injectAndCheckAxe();
- });
-
- it('has no detectable a11y violations on the email sent page without resend box', () => {
- cy.visit(`/welcome/email-sent?useIdapi=true`);
- injectAndCheckAxe();
- });
- });
-
- // successful token, set password page is displayed, redirect to consents flow if valid password
- context('A valid token is used and set password page is displayed', () => {
- it('redirects to onboarding flow if a valid password is set', () => {
- setPasswordAndSignIn();
- cy.contains('Thank you for registering');
- });
-
- it('shows a different message if the user has set a password and then clicked the back button', () => {
- setPasswordAndSignIn();
- cy.go('back');
- cy.contains(`Password already set for ${defaultEmail}`);
- cy.contains('Continue').click();
- cy.contains('Thank you for registering');
- });
-
- it('redirects to onboarding flow if valid password is set and preserves returnUrl', () => {
- const returnUrl = encodeURIComponent(
- `https://www.theguardian.com/science/grrlscientist/2012/aug/07/3`,
- );
- const query = new URLSearchParams({ returnUrl }).toString();
-
- cy.mockNext(200, checkTokenSuccessResponse());
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.mockNext(200, fakeCookieSuccessResponse);
- cy.mockAll(
- 200,
- authRedirectSignInRecentlyEmailValidated,
- AUTH_REDIRECT_ENDPOINT,
- );
- cy.mockAll(200, allConsents, CONSENTS_ENDPOINT);
- cy.mockAll(200, verifiedUserWithNoConsent, USER_ENDPOINT);
- setAuthCookies();
-
- cy.visit(`/welcome/fake_token?${query}&useIdapi=true`);
- cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
- cy.wait('@breachCheck');
- cy.get('button[type="submit"]').click();
- cy.contains('Thank you for registering');
- cy.url().should('include', CommunicationsPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
- });
-
- it('redirects to onboarding flow and adds Jobs user to the GRS group if valid password is set and preserves returnUrl', () => {
- const returnUrl = encodeURIComponent(
- `https://www.theguardian.com/science/grrlscientist/2012/aug/07/3`,
- );
- const clientId = 'jobs';
- const query = new URLSearchParams({ returnUrl, clientId }).toString();
-
- cy.mockNext(200, checkTokenSuccessResponse());
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.mockNext(200, fakeCookieSuccessResponse);
- cy.mockAll(200, fakeGroupAddResponse, '/user/me/group/GRS');
- cy.mockAll(
- 200,
- authRedirectSignInRecentlyEmailValidated,
- AUTH_REDIRECT_ENDPOINT,
- );
- cy.mockAll(200, allConsents, CONSENTS_ENDPOINT);
- cy.mockAll(200, verifiedUserWithNoConsent, USER_ENDPOINT);
- setAuthCookies();
-
- cy.visit(`/welcome/fake_token?${query}&useIdapi=true`);
- cy.get('input[name="firstName"]').type('First Name');
- cy.get('input[name="secondName"]').type('Last Name');
- cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
- cy.wait('@breachCheck');
- cy.get('button[type="submit"]').click();
- cy.contains('Thank you for registering');
- cy.url().should('include', CommunicationsPage.URL);
- cy.url().should('include', `returnUrl=${returnUrl}`);
- cy.url().should('include', `clientId=${clientId}`);
- });
-
- it('shows an error if the password is invalid', () => {
- cy.mockNext(200, checkTokenSuccessResponse());
- cy.mockNext(400, {
- status: 'error',
- errors: [
- {
- message: 'Breached password',
- },
- ],
- });
- cy.mockNext(200, checkTokenSuccessResponse());
- cy.visit(`/welcome/fake_token?useIdapi=true`);
- cy.get('input[name="password"]').type('password');
- cy.get('button[type="submit"]').click();
- cy.contains('Please use a password that is hard to guess.');
- });
-
- it('shows prompt to create password', () => {
- cy.mockNext(200, checkTokenSuccessResponse());
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.visit(`/welcome/fake_token?useIdapi=true`);
- cy.contains(`Please complete your details for ${defaultEmail}`);
- });
-
- it('shows prompt to create password without email if none exists', () => {
- cy.mockNext(200, checkTokenSuccessResponse(null, ''));
- cy.intercept({
- method: 'GET',
- url: 'https://api.pwnedpasswords.com/range/*',
- }).as('breachCheck');
- cy.visit(`/welcome/fake_token?useIdapi=true`);
- cy.contains(`Please complete your details for your new account`);
- });
- });
-
- context('An expired/invalid token is used', () => {
- it('shows the link expired page to type email, and on submit shows the email sent page, with a button to resend the email', () => {
- cy.mockNext(500, {
- status: 'error',
- errors: [
- {
- message: 'Invalid token',
- },
- ],
- });
- cy.mockNext(200);
- cy.mockNext(200);
- cy.visit(`/welcome/fake_token?useIdapi=true`);
- cy.contains('Link expired');
- cy.get('input[name="email"]').type(
- checkTokenSuccessResponse().user.primaryEmailAddress,
- );
- cy.get('button[type="submit"]').click();
- cy.contains('Check your email inbox');
- cy.contains(checkTokenSuccessResponse().user.primaryEmailAddress);
- cy.contains('Resend email');
- });
-
- it('shows the session time out page if the token expires while on the set password page', () => {
- cy.mockNext(200, checkTokenSuccessResponse(1000));
- cy.visit(`/welcome/fake_token?useIdapi=true`);
- cy.contains('Session timed out');
- });
- });
-
- context('Email sent page', () => {
- it('resends email if button exists', () => {
- cy.visit(`/welcome/resend?useIdapi=true`);
-
- cy.mockNext(200);
- cy.get('input[name="email"]').type(
- checkTokenSuccessResponse().user.primaryEmailAddress,
- );
- cy.get('button[type="submit"]').click();
-
- cy.mockNext(200);
- cy.contains('Check your email inbox');
- cy.get('button[type="submit"]').click();
- cy.contains('Check your email inbox');
- });
-
- it('fails to resend email if reCAPTCHA check is unsuccessful', () => {
- cy.visit(`/welcome/resend?useIdapi=true`);
-
- cy.mockNext(200);
-
- cy.get('input[name="email"]').type(
- checkTokenSuccessResponse().user.primaryEmailAddress,
- );
-
- cy.intercept('POST', 'https://www.google.com/recaptcha/api2/**', {
- statusCode: 500,
- });
- cy.get('button[type="submit"]').click();
- cy.contains('Google reCAPTCHA verification failed. Please try again.');
- cy.get('button[type="submit"]').click();
- cy.contains('Google reCAPTCHA verification failed.');
- cy.contains('If the problem persists please try the following:');
- cy.contains('userhelp@');
- });
-
- it('takes user back to link expired page if "Change email address" clicked', () => {
- cy.visit(`/welcome/resend?useIdapi=true`);
-
- cy.mockNext(200);
- cy.get('input[name="email"]').type(
- checkTokenSuccessResponse().user.primaryEmailAddress,
- );
- cy.get('button[type="submit"]').click();
-
- cy.contains('Change email address').click();
-
- cy.contains('Link expired');
- });
- });
+ const defaultEmail = 'someone@theguardian.com';
+ const checkTokenSuccessResponse = (
+ timeUntilExpiry: number | null = null,
+ email = defaultEmail,
+ ) => ({
+ user: {
+ primaryEmailAddress: email,
+ },
+ timeUntilExpiry,
+ });
+
+ const fakeCookieSuccessResponse = {
+ cookies: {
+ values: [
+ {
+ key: 'GU_U',
+ value: 'FAKE_VALUE_0',
+ },
+ {
+ key: 'SC_GU_LA',
+ value: 'FAKE_VALUE_1',
+ sessionCookie: true,
+ },
+ {
+ key: 'SC_GU_U',
+ value: 'FAKE_VALUE_2',
+ },
+ ],
+ expiresAt: new Date(Date.now() + 1800000 /* 30min */).toISOString(),
+ },
+ };
+
+ const fakeGroupAddResponse = {
+ status: 'ok',
+ groupCode: 'GRS',
+ };
+
+ const setPasswordAndSignIn = () => {
+ cy.mockNext(200, checkTokenSuccessResponse());
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.mockNext(200, fakeCookieSuccessResponse);
+ cy.mockAll(
+ 200,
+ authRedirectSignInRecentlyEmailValidated,
+ AUTH_REDIRECT_ENDPOINT,
+ );
+ cy.mockAll(200, allConsents, CONSENTS_ENDPOINT);
+ // cy.mockAll(200, verifiedUserWithNoConsent, USER_ENDPOINT);
+ cy.mockAll(
+ 200,
+ verifiedUserWithNoConsent.user.consents,
+ USER_CONSENTS_ENDPOINT,
+ );
+ cy.visit(`/welcome/fake_token?useIdapi=true`);
+ cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
+ cy.wait('@breachCheck');
+ cy.get('button[type="submit"]').click();
+ };
+
+ beforeEach(() => {
+ cy.mockPurge();
+ });
+
+ context('A11y checks', () => {
+ it('has no detectable a11y violations on the set password page', () => {
+ cy.mockNext(200, checkTokenSuccessResponse());
+ cy.visit(`/welcome/fake_token?useIdapi=true`);
+ injectAndCheckAxe();
+ });
+
+ it('has no detectable a11y violations on set password page with global error', () => {
+ cy.mockNext(200, checkTokenSuccessResponse());
+ cy.visit(`/welcome/fake_token?useIdapi=true`);
+ cy.mockNext(500);
+ cy.get('input[name="password"]').type('short');
+ cy.get('button[type="submit"]').click();
+ injectAndCheckAxe();
+ });
+
+ it('has no detectable a11y violations on the resend page', () => {
+ cy.visit(`/welcome/resend?useIdapi=true`);
+ injectAndCheckAxe();
+ });
+
+ it('has no detectable a11y violations on the resend page with global error', () => {
+ cy.visit(`/welcome/resend?useIdapi=true`);
+
+ cy.mockNext(500);
+ cy.get('input[name="email"]').type(
+ checkTokenSuccessResponse().user.primaryEmailAddress,
+ );
+ cy.get('button[type="submit"]').click();
+ injectAndCheckAxe();
+ });
+
+ it('has no detectable a11y violations on the email sent page with resend box', () => {
+ cy.visit(`/welcome/resend?useIdapi=true`);
+
+ cy.mockNext(200);
+ cy.get('input[name="email"]').type(
+ checkTokenSuccessResponse().user.primaryEmailAddress,
+ );
+ cy.get('button[type="submit"]').click();
+ injectAndCheckAxe();
+ });
+
+ it('has no detectable a11y violations on the email sent page without resend box', () => {
+ cy.visit(`/welcome/email-sent?useIdapi=true`);
+ injectAndCheckAxe();
+ });
+ });
+
+ // successful token, set password page is displayed, redirect to consents flow if valid password
+ context('A valid token is used and set password page is displayed', () => {
+ it('redirects to onboarding flow if a valid password is set', () => {
+ setPasswordAndSignIn();
+ cy.contains('Thank you for registering');
+ });
+
+ it('shows a different message if the user has set a password and then clicked the back button', () => {
+ setPasswordAndSignIn();
+ cy.go('back');
+ cy.contains(`Password already set for ${defaultEmail}`);
+ cy.contains('Continue').click();
+ cy.contains('Thank you for registering');
+ });
+
+ it('redirects to onboarding flow if valid password is set and preserves returnUrl', () => {
+ const returnUrl = encodeURIComponent(
+ `https://www.theguardian.com/science/grrlscientist/2012/aug/07/3`,
+ );
+ const query = new URLSearchParams({ returnUrl }).toString();
+
+ cy.mockNext(200, checkTokenSuccessResponse());
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.mockNext(200, fakeCookieSuccessResponse);
+ cy.mockAll(
+ 200,
+ authRedirectSignInRecentlyEmailValidated,
+ AUTH_REDIRECT_ENDPOINT,
+ );
+ cy.mockAll(200, allConsents, CONSENTS_ENDPOINT);
+ cy.mockAll(200, verifiedUserWithNoConsent, USER_ENDPOINT);
+ setAuthCookies();
+
+ cy.visit(`/welcome/fake_token?${query}&useIdapi=true`);
+ cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
+ cy.wait('@breachCheck');
+ cy.get('button[type="submit"]').click();
+ cy.contains('Thank you for registering');
+ cy.url().should('include', CommunicationsPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
+ });
+
+ it('redirects to onboarding flow and adds Jobs user to the GRS group if valid password is set and preserves returnUrl', () => {
+ const returnUrl = encodeURIComponent(
+ `https://www.theguardian.com/science/grrlscientist/2012/aug/07/3`,
+ );
+ const clientId = 'jobs';
+ const query = new URLSearchParams({ returnUrl, clientId }).toString();
+
+ cy.mockNext(200, checkTokenSuccessResponse());
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.mockNext(200, fakeCookieSuccessResponse);
+ cy.mockAll(200, fakeGroupAddResponse, '/user/me/group/GRS');
+ cy.mockAll(
+ 200,
+ authRedirectSignInRecentlyEmailValidated,
+ AUTH_REDIRECT_ENDPOINT,
+ );
+ cy.mockAll(200, allConsents, CONSENTS_ENDPOINT);
+ cy.mockAll(200, verifiedUserWithNoConsent, USER_ENDPOINT);
+ setAuthCookies();
+
+ cy.visit(`/welcome/fake_token?${query}&useIdapi=true`);
+ cy.get('input[name="firstName"]').type('First Name');
+ cy.get('input[name="secondName"]').type('Last Name');
+ cy.get('input[name="password"]').type('thisisalongandunbreachedpassword');
+ cy.wait('@breachCheck');
+ cy.get('button[type="submit"]').click();
+ cy.contains('Thank you for registering');
+ cy.url().should('include', CommunicationsPage.URL);
+ cy.url().should('include', `returnUrl=${returnUrl}`);
+ cy.url().should('include', `clientId=${clientId}`);
+ });
+
+ it('shows an error if the password is invalid', () => {
+ cy.mockNext(200, checkTokenSuccessResponse());
+ cy.mockNext(400, {
+ status: 'error',
+ errors: [
+ {
+ message: 'Breached password',
+ },
+ ],
+ });
+ cy.mockNext(200, checkTokenSuccessResponse());
+ cy.visit(`/welcome/fake_token?useIdapi=true`);
+ cy.get('input[name="password"]').type('password');
+ cy.get('button[type="submit"]').click();
+ cy.contains('Please use a password that is hard to guess.');
+ });
+
+ it('shows prompt to create password', () => {
+ cy.mockNext(200, checkTokenSuccessResponse());
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.visit(`/welcome/fake_token?useIdapi=true`);
+ cy.contains(`Please complete your details for ${defaultEmail}`);
+ });
+
+ it('shows prompt to create password without email if none exists', () => {
+ cy.mockNext(200, checkTokenSuccessResponse(null, ''));
+ cy.intercept({
+ method: 'GET',
+ url: 'https://api.pwnedpasswords.com/range/*',
+ }).as('breachCheck');
+ cy.visit(`/welcome/fake_token?useIdapi=true`);
+ cy.contains(`Please complete your details for your new account`);
+ });
+ });
+
+ context('An expired/invalid token is used', () => {
+ it('shows the link expired page to type email, and on submit shows the email sent page, with a button to resend the email', () => {
+ cy.mockNext(500, {
+ status: 'error',
+ errors: [
+ {
+ message: 'Invalid token',
+ },
+ ],
+ });
+ cy.mockNext(200);
+ cy.mockNext(200);
+ cy.visit(`/welcome/fake_token?useIdapi=true`);
+ cy.contains('Link expired');
+ cy.get('input[name="email"]').type(
+ checkTokenSuccessResponse().user.primaryEmailAddress,
+ );
+ cy.get('button[type="submit"]').click();
+ cy.contains('Check your email inbox');
+ cy.contains(checkTokenSuccessResponse().user.primaryEmailAddress);
+ cy.contains('Resend email');
+ });
+
+ it('shows the session time out page if the token expires while on the set password page', () => {
+ cy.mockNext(200, checkTokenSuccessResponse(1000));
+ cy.visit(`/welcome/fake_token?useIdapi=true`);
+ cy.contains('Session timed out');
+ });
+ });
+
+ context('Email sent page', () => {
+ it('resends email if button exists', () => {
+ cy.visit(`/welcome/resend?useIdapi=true`);
+
+ cy.mockNext(200);
+ cy.get('input[name="email"]').type(
+ checkTokenSuccessResponse().user.primaryEmailAddress,
+ );
+ cy.get('button[type="submit"]').click();
+
+ cy.mockNext(200);
+ cy.contains('Check your email inbox');
+ cy.get('button[type="submit"]').click();
+ cy.contains('Check your email inbox');
+ });
+
+ it('fails to resend email if reCAPTCHA check is unsuccessful', () => {
+ cy.visit(`/welcome/resend?useIdapi=true`);
+
+ cy.mockNext(200);
+
+ cy.get('input[name="email"]').type(
+ checkTokenSuccessResponse().user.primaryEmailAddress,
+ );
+
+ cy.intercept('POST', 'https://www.google.com/recaptcha/api2/**', {
+ statusCode: 500,
+ });
+ cy.get('button[type="submit"]').click();
+ cy.contains('Google reCAPTCHA verification failed. Please try again.');
+ cy.get('button[type="submit"]').click();
+ cy.contains('Google reCAPTCHA verification failed.');
+ cy.contains('If the problem persists please try the following:');
+ cy.contains('userhelp@');
+ });
+
+ it('takes user back to link expired page if "Change email address" clicked', () => {
+ cy.visit(`/welcome/resend?useIdapi=true`);
+
+ cy.mockNext(200);
+ cy.get('input[name="email"]').type(
+ checkTokenSuccessResponse().user.primaryEmailAddress,
+ );
+ cy.get('button[type="submit"]').click();
+
+ cy.contains('Change email address').click();
+
+ cy.contains('Link expired');
+ });
+ });
});
diff --git a/cypress/integration/shared/sign_in.shared.ts b/cypress/integration/shared/sign_in.shared.ts
index e9d33410b2..73614d8c69 100644
--- a/cypress/integration/shared/sign_in.shared.ts
+++ b/cypress/integration/shared/sign_in.shared.ts
@@ -1,487 +1,487 @@
const returnUrl =
- 'https://www.theguardian.com/world/2013/jun/09/edward-snowden-nsa-whistleblower-surveillance';
+ 'https://www.theguardian.com/world/2013/jun/09/edward-snowden-nsa-whistleblower-surveillance';
export const beforeEach = () => {
- // Disable redirect to /signin/success by default
- cy.setCookie(
- 'GU_ran_experiments',
- new URLSearchParams({
- OptInPromptPostSignIn: Date.now().toString(),
- }).toString(),
- );
+ // Disable redirect to /signin/success by default
+ cy.setCookie(
+ 'GU_ran_experiments',
+ new URLSearchParams({
+ OptInPromptPostSignIn: Date.now().toString(),
+ }).toString(),
+ );
};
export const linksToTheGoogleTermsOfServicePage = (isIdapi = false) => {
- return [
- 'links to the Google terms of service page',
- () => {
- const googleTermsUrl = 'https://policies.google.com/terms';
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', googleTermsUrl, (req) => {
- req.reply(200);
- });
- const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
- cy.visit(visitUrl);
- cy.contains('terms of service').click();
- cy.url().should('eq', googleTermsUrl);
- },
- ] as const;
+ return [
+ 'links to the Google terms of service page',
+ () => {
+ const googleTermsUrl = 'https://policies.google.com/terms';
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', googleTermsUrl, (req) => {
+ req.reply(200);
+ });
+ const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
+ cy.visit(visitUrl);
+ cy.contains('terms of service').click();
+ cy.url().should('eq', googleTermsUrl);
+ },
+ ] as const;
};
export const linksToTheGooglePrivacyPolicyPage = (isIdapi = false) => {
- return [
- 'links to the Google privacy policy page',
- () => {
- const googlePrivacyPolicyUrl = 'https://policies.google.com/privacy';
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', googlePrivacyPolicyUrl, (req) => {
- req.reply(200);
- });
- const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
- cy.visit(visitUrl);
- cy.contains('This service is protected by reCAPTCHA and the Google')
- .contains('privacy policy')
- .click();
- cy.url().should('eq', googlePrivacyPolicyUrl);
- },
- ] as const;
+ return [
+ 'links to the Google privacy policy page',
+ () => {
+ const googlePrivacyPolicyUrl = 'https://policies.google.com/privacy';
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', googlePrivacyPolicyUrl, (req) => {
+ req.reply(200);
+ });
+ const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
+ cy.visit(visitUrl);
+ cy.contains('This service is protected by reCAPTCHA and the Google')
+ .contains('privacy policy')
+ .click();
+ cy.url().should('eq', googlePrivacyPolicyUrl);
+ },
+ ] as const;
};
export const linksToTheGuardianTermsAndConditionsPage = (isIdapi = false) => {
- return [
- 'links to the Guardian terms and conditions page',
- () => {
- const guardianTermsOfServiceUrl =
- 'https://www.theguardian.com/help/terms-of-service';
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', guardianTermsOfServiceUrl, (req) => {
- req.reply(200);
- });
- const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
- cy.visit(visitUrl);
- cy.contains('terms & conditions').click();
- cy.url().should('eq', guardianTermsOfServiceUrl);
- },
- ] as const;
+ return [
+ 'links to the Guardian terms and conditions page',
+ () => {
+ const guardianTermsOfServiceUrl =
+ 'https://www.theguardian.com/help/terms-of-service';
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', guardianTermsOfServiceUrl, (req) => {
+ req.reply(200);
+ });
+ const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
+ cy.visit(visitUrl);
+ cy.contains('terms & conditions').click();
+ cy.url().should('eq', guardianTermsOfServiceUrl);
+ },
+ ] as const;
};
export const linksToTheGuardianPrivacyPolicyPage = (isIdapi = false) => {
- return [
- 'links to the Guardian privacy policy page',
- () => {
- const guardianPrivacyPolicyUrl =
- 'https://www.theguardian.com/help/privacy-policy';
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', guardianPrivacyPolicyUrl, (req) => {
- req.reply(200);
- });
- const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
- cy.visit(visitUrl);
- cy.contains('For information about how we use your data')
- .contains('privacy policy')
- .click();
- cy.url().should('eq', guardianPrivacyPolicyUrl);
- },
- ] as const;
+ return [
+ 'links to the Guardian privacy policy page',
+ () => {
+ const guardianPrivacyPolicyUrl =
+ 'https://www.theguardian.com/help/privacy-policy';
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', guardianPrivacyPolicyUrl, (req) => {
+ req.reply(200);
+ });
+ const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
+ cy.visit(visitUrl);
+ cy.contains('For information about how we use your data')
+ .contains('privacy policy')
+ .click();
+ cy.url().should('eq', guardianPrivacyPolicyUrl);
+ },
+ ] as const;
};
export const linksToTheGuardianJobsTermsAndConditionsPageWhenJobsClientIdSet = (
- isIdapi = false,
+ isIdapi = false,
) => {
- return [
- 'links to the Guardian jobs terms and conditions page when jobs clientId set',
- () => {
- const guardianJobsTermsOfServiceUrl =
- 'https://jobs.theguardian.com/terms-and-conditions/';
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', guardianJobsTermsOfServiceUrl, (req) => {
- req.reply(200);
- });
- const visitUrl = isIdapi
- ? '/signin?clientId=jobs&useIdapi=true'
- : '/signin?clientId=jobs';
- cy.visit(visitUrl);
- cy.contains('Guardian Jobs terms & conditions').click();
- cy.url().should('eq', guardianJobsTermsOfServiceUrl);
- },
- ] as const;
+ return [
+ 'links to the Guardian jobs terms and conditions page when jobs clientId set',
+ () => {
+ const guardianJobsTermsOfServiceUrl =
+ 'https://jobs.theguardian.com/terms-and-conditions/';
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', guardianJobsTermsOfServiceUrl, (req) => {
+ req.reply(200);
+ });
+ const visitUrl = isIdapi
+ ? '/signin?clientId=jobs&useIdapi=true'
+ : '/signin?clientId=jobs';
+ cy.visit(visitUrl);
+ cy.contains('Guardian Jobs terms & conditions').click();
+ cy.url().should('eq', guardianJobsTermsOfServiceUrl);
+ },
+ ] as const;
};
export const linksToTheGuardianJobsPrivacyPolicyPageWhenJobsClientIdSet = (
- isIdapi = false,
+ isIdapi = false,
) => {
- return [
- 'links to the Guardian jobs privacy policy page when jobs clientId set',
- () => {
- const guardianJobsPrivacyPolicyUrl =
- 'https://jobs.theguardian.com/privacy-policy/';
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', guardianJobsPrivacyPolicyUrl, (req) => {
- req.reply(200);
- });
- const visitUrl = isIdapi
- ? '/signin?clientId=jobs&useIdapi=true'
- : '/signin?clientId=jobs';
- cy.visit(visitUrl);
- cy.contains('For information about how we use your data')
- .contains('Guardian Jobs privacy policy')
- .click();
- cy.url().should('eq', guardianJobsPrivacyPolicyUrl);
- },
- ] as const;
+ return [
+ 'links to the Guardian jobs privacy policy page when jobs clientId set',
+ () => {
+ const guardianJobsPrivacyPolicyUrl =
+ 'https://jobs.theguardian.com/privacy-policy/';
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', guardianJobsPrivacyPolicyUrl, (req) => {
+ req.reply(200);
+ });
+ const visitUrl = isIdapi
+ ? '/signin?clientId=jobs&useIdapi=true'
+ : '/signin?clientId=jobs';
+ cy.visit(visitUrl);
+ cy.contains('For information about how we use your data')
+ .contains('Guardian Jobs privacy policy')
+ .click();
+ cy.url().should('eq', guardianJobsPrivacyPolicyUrl);
+ },
+ ] as const;
};
export const persistsTheClientIdWhenNavigatingAway = (isIdapi = false) => {
- return [
- 'persists the clientId when navigating away',
- () => {
- const visitUrl = isIdapi
- ? '/signin?clientId=jobs&useIdapi=true'
- : '/signin?clientId=jobs';
- cy.visit(visitUrl);
- cy.contains('Register').click();
- cy.url().should('contain', 'clientId=jobs');
- },
- ] as const;
+ return [
+ 'persists the clientId when navigating away',
+ () => {
+ const visitUrl = isIdapi
+ ? '/signin?clientId=jobs&useIdapi=true'
+ : '/signin?clientId=jobs';
+ cy.visit(visitUrl);
+ cy.contains('Register').click();
+ cy.url().should('contain', 'clientId=jobs');
+ },
+ ] as const;
};
export const appliesFormValidationToEmailAndPasswordInputFields = (
- isIdapi = false,
+ isIdapi = false,
) => {
- return [
- 'applies form validation to email and password input fields',
- () => {
- const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
- cy.visit(visitUrl);
-
- cy.get('form').within(() => {
- cy.get('input:invalid').should('have.length', 2);
- cy.get('input[name=email]').type('not an email');
- cy.get('input:invalid').should('have.length', 2);
- cy.get('input[name=email]').type('emailaddress@inavalidformat.com');
- cy.get('input:invalid').should('have.length', 1);
- cy.get('input[name=password]').type('password');
- cy.get('input:invalid').should('have.length', 0);
- });
- },
- ] as const;
+ return [
+ 'applies form validation to email and password input fields',
+ () => {
+ const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
+ cy.visit(visitUrl);
+
+ cy.get('form').within(() => {
+ cy.get('input:invalid').should('have.length', 2);
+ cy.get('input[name=email]').type('not an email');
+ cy.get('input:invalid').should('have.length', 2);
+ cy.get('input[name=email]').type('emailaddress@inavalidformat.com');
+ cy.get('input:invalid').should('have.length', 1);
+ cy.get('input[name=password]').type('password');
+ cy.get('input:invalid').should('have.length', 0);
+ });
+ },
+ ] as const;
};
export const showsAMessageWhenCredentialsAreInvalid = (isIdapi = false) => {
- return [
- 'shows a message when credentials are invalid',
- () => {
- const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
- cy.visit(visitUrl);
- cy.get('input[name=email]').type('invalid@doesnotexist.com');
- cy.get('input[name=password]').type('password');
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.contains("Email and password don't match");
- },
- ] as const;
+ return [
+ 'shows a message when credentials are invalid',
+ () => {
+ const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
+ cy.visit(visitUrl);
+ cy.get('input[name=email]').type('invalid@doesnotexist.com');
+ cy.get('input[name=password]').type('password');
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.contains("Email and password don't match");
+ },
+ ] as const;
};
export const correctlySignsInAnExistingUser = (isIdapi = false) => {
- return [
- 'correctly signs in an existing user',
- () => {
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', 'https://m.code.dev-theguardian.com/', (req) => {
- req.reply(200);
- });
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress, finalPassword }) => {
- const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
- cy.visit(visitUrl);
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', 'https://m.code.dev-theguardian.com/');
- });
- },
- ] as const;
+ return [
+ 'correctly signs in an existing user',
+ () => {
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', 'https://m.code.dev-theguardian.com/', (req) => {
+ req.reply(200);
+ });
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress, finalPassword }) => {
+ const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
+ cy.visit(visitUrl);
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', 'https://m.code.dev-theguardian.com/');
+ });
+ },
+ ] as const;
};
export const navigatesToResetPassword = (isIdapi = false) => {
- return [
- 'navigates to reset password',
- () => {
- const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
- cy.visit(visitUrl);
- cy.contains('Reset password').click();
- cy.contains('Forgot password');
- },
- ] as const;
+ return [
+ 'navigates to reset password',
+ () => {
+ const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
+ cy.visit(visitUrl);
+ cy.contains('Reset password').click();
+ cy.contains('Forgot password');
+ },
+ ] as const;
};
export const navigatesToRegistration = (isIdapi = false) => {
- return [
- 'navigates to registration',
- () => {
- const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
- cy.visit(visitUrl);
- cy.contains('Register').click();
- cy.get('[data-cy="main-form-submit-button"]').should('be.visible');
- },
- ] as const;
+ return [
+ 'navigates to registration',
+ () => {
+ const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
+ cy.visit(visitUrl);
+ cy.contains('Register').click();
+ cy.get('[data-cy="main-form-submit-button"]').should('be.visible');
+ },
+ ] as const;
};
export const respectsTheReturnUrlQueryParam = (isIdapi = false) => {
- return [
- 'respects the returnUrl query param',
- () => {
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', returnUrl, (req) => {
- req.reply(200);
- });
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress, finalPassword }) => {
- const visitUrl = isIdapi
- ? `/signin?returnUrl=${encodeURIComponent(returnUrl)}&useIdapi=true`
- : `/signin?returnUrl=${encodeURIComponent(returnUrl)}`;
- cy.visit(visitUrl);
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('eq', returnUrl);
- });
- },
- ] as const;
+ return [
+ 'respects the returnUrl query param',
+ () => {
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', returnUrl, (req) => {
+ req.reply(200);
+ });
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress, finalPassword }) => {
+ const visitUrl = isIdapi
+ ? `/signin?returnUrl=${encodeURIComponent(returnUrl)}&useIdapi=true`
+ : `/signin?returnUrl=${encodeURIComponent(returnUrl)}`;
+ cy.visit(visitUrl);
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('eq', returnUrl);
+ });
+ },
+ ] as const;
};
export const redirectsCorrectlyForSocialSignIn = (isIdapi = false) => {
- return [
- 'redirects correctly for social sign in',
- () => {
- const visitUrl = isIdapi
- ? `/signin?returnUrl=${encodeURIComponent(returnUrl)}&useIdapi=true`
- : `/signin?returnUrl=${encodeURIComponent(returnUrl)}`;
- cy.visit(visitUrl);
- cy.get('[data-cy="google-sign-in-button"]').should(
- 'have.attr',
- 'href',
- `/signin/google?returnUrl=${encodeURIComponent(returnUrl)}${
- isIdapi ? '&useIdapi=true' : ''
- }`,
- );
- cy.get('[data-cy="apple-sign-in-button"]').should(
- 'have.attr',
- 'href',
- `/signin/apple?returnUrl=${encodeURIComponent(returnUrl)}${
- isIdapi ? '&useIdapi=true' : ''
- }`,
- );
- },
- ] as const;
+ return [
+ 'redirects correctly for social sign in',
+ () => {
+ const visitUrl = isIdapi
+ ? `/signin?returnUrl=${encodeURIComponent(returnUrl)}&useIdapi=true`
+ : `/signin?returnUrl=${encodeURIComponent(returnUrl)}`;
+ cy.visit(visitUrl);
+ cy.get('[data-cy="google-sign-in-button"]').should(
+ 'have.attr',
+ 'href',
+ `/signin/google?returnUrl=${encodeURIComponent(returnUrl)}${
+ isIdapi ? '&useIdapi=true' : ''
+ }`,
+ );
+ cy.get('[data-cy="apple-sign-in-button"]').should(
+ 'have.attr',
+ 'href',
+ `/signin/apple?returnUrl=${encodeURIComponent(returnUrl)}${
+ isIdapi ? '&useIdapi=true' : ''
+ }`,
+ );
+ },
+ ] as const;
};
export const removesEncryptedEmailParameterFromQueryString = (
- isIdapi = false,
+ isIdapi = false,
) => {
- return [
- 'removes encryptedEmail parameter from query string',
- () => {
- const encryptedEmailParam = 'encryptedEmail=bhvlabgflbgyil';
- const visitUrl = isIdapi
- ? `/signin?${encryptedEmailParam}&useIdapi=true`
- : `/signin?${encryptedEmailParam}`;
- cy.visit(visitUrl);
-
- cy.location('search').should('not.contain', encryptedEmailParam);
- },
- ] as const;
+ return [
+ 'removes encryptedEmail parameter from query string',
+ () => {
+ const encryptedEmailParam = 'encryptedEmail=bhvlabgflbgyil';
+ const visitUrl = isIdapi
+ ? `/signin?${encryptedEmailParam}&useIdapi=true`
+ : `/signin?${encryptedEmailParam}`;
+ cy.visit(visitUrl);
+
+ cy.location('search').should('not.contain', encryptedEmailParam);
+ },
+ ] as const;
};
export const removesEncryptedEmailParameterAndPreservesAllOtherValidParameters =
- (isIdapi = false) => {
- return [
- 'removes encryptedEmail parameter and preserves all other valid parameters',
- () => {
- const encryptedEmailParam = 'encryptedEmail=bhvlabgflbgyil';
- const visitUrl = isIdapi
- ? `/signin?returnUrl=${encodeURIComponent(
- returnUrl,
- )}&${encryptedEmailParam}&refViewId=12345&useIdapi=true`
- : `/signin?returnUrl=${encodeURIComponent(
- returnUrl,
- )}&${encryptedEmailParam}&refViewId=12345`;
- cy.visit(visitUrl);
-
- cy.location('search').should('not.contain', encryptedEmailParam);
- cy.location('search').should('contain', 'refViewId=12345');
- cy.location('search').should('contain', encodeURIComponent(returnUrl));
- },
- ] as const;
- };
+ (isIdapi = false) => {
+ return [
+ 'removes encryptedEmail parameter and preserves all other valid parameters',
+ () => {
+ const encryptedEmailParam = 'encryptedEmail=bhvlabgflbgyil';
+ const visitUrl = isIdapi
+ ? `/signin?returnUrl=${encodeURIComponent(
+ returnUrl,
+ )}&${encryptedEmailParam}&refViewId=12345&useIdapi=true`
+ : `/signin?returnUrl=${encodeURIComponent(
+ returnUrl,
+ )}&${encryptedEmailParam}&refViewId=12345`;
+ cy.visit(visitUrl);
+
+ cy.location('search').should('not.contain', encryptedEmailParam);
+ cy.location('search').should('contain', 'refViewId=12345');
+ cy.location('search').should('contain', encodeURIComponent(returnUrl));
+ },
+ ] as const;
+ };
export const hitsAccessTokenRateLimitAndRecoversTokenAfterTimeout = (
- isIdapi = false,
+ isIdapi = false,
) => {
- return [
- 'hits access token rate limit and recovers token after timeout',
- () => {
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', 'https://m.code.dev-theguardian.com/', (req) => {
- req.reply(200);
- });
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress, finalPassword }) => {
- const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
- cy.visit(visitUrl);
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', 'https://m.code.dev-theguardian.com/');
-
- // We visit reauthenticate here because if we visit /signin or
- // /register, the logged in user guard will redirect us away before
- // the ratelimiter has a chance to work
- const reauthUrl = isIdapi
- ? '/reauthenticate?useIdapi=true'
- : '/reauthenticate';
- cy.visit(reauthUrl);
- cy.contains('Sign');
- Cypress._.times(6, () => cy.reload());
- cy.contains('Rate limit exceeded');
- });
- },
- ] as const;
+ return [
+ 'hits access token rate limit and recovers token after timeout',
+ () => {
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', 'https://m.code.dev-theguardian.com/', (req) => {
+ req.reply(200);
+ });
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress, finalPassword }) => {
+ const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
+ cy.visit(visitUrl);
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', 'https://m.code.dev-theguardian.com/');
+
+ // We visit reauthenticate here because if we visit /signin or
+ // /register, the logged in user guard will redirect us away before
+ // the ratelimiter has a chance to work
+ const reauthUrl = isIdapi
+ ? '/reauthenticate?useIdapi=true'
+ : '/reauthenticate';
+ cy.visit(reauthUrl);
+ cy.contains('Sign');
+ Cypress._.times(6, () => cy.reload());
+ cy.contains('Rate limit exceeded');
+ });
+ },
+ ] as const;
};
export const showsAnErrorMessageAndInformationParagraphWhenAccountLinkingRequiredErrorParameterIsPresent =
- (isIdapi = false) => {
- return [
- 'shows an error message and information paragraph when accountLinkingRequired error parameter is present',
- () => {
- const visitUrl = isIdapi
- ? '/signin?error=accountLinkingRequired&useIdapi=true'
- : '/signin?error=accountLinkingRequired';
- cy.visit(visitUrl);
- cy.contains(
- 'We cannot sign you in with your social account credentials. Please enter your account password below to sign in.',
- );
- cy.contains('Account already exists');
- },
- ] as const;
- };
+ (isIdapi = false) => {
+ return [
+ 'shows an error message and information paragraph when accountLinkingRequired error parameter is present',
+ () => {
+ const visitUrl = isIdapi
+ ? '/signin?error=accountLinkingRequired&useIdapi=true'
+ : '/signin?error=accountLinkingRequired';
+ cy.visit(visitUrl);
+ cy.contains(
+ 'We cannot sign you in with your social account credentials. Please enter your account password below to sign in.',
+ );
+ cy.contains('Account already exists');
+ },
+ ] as const;
+ };
export const doesNotDisplaySocialButtonsWhenAccountLinkingRequiredErrorParameterIsPresent =
- (isIdapi = false) => {
- return [
- 'does not display social buttons when accountLinkingRequired error parameter is present',
- () => {
- const visitUrl = isIdapi
- ? '/signin?error=accountLinkingRequired&useIdapi=true'
- : '/signin?error=accountLinkingRequired';
- cy.visit(visitUrl);
- cy.get('[data-cy="google-sign-in-button"]').should('not.exist');
- cy.get('[data-cy="apple-sign-in-button"]').should('not.exist');
- },
- ] as const;
- };
+ (isIdapi = false) => {
+ return [
+ 'does not display social buttons when accountLinkingRequired error parameter is present',
+ () => {
+ const visitUrl = isIdapi
+ ? '/signin?error=accountLinkingRequired&useIdapi=true'
+ : '/signin?error=accountLinkingRequired';
+ cy.visit(visitUrl);
+ cy.get('[data-cy="google-sign-in-button"]').should('not.exist');
+ cy.get('[data-cy="apple-sign-in-button"]').should('not.exist');
+ },
+ ] as const;
+ };
export const showsRecaptchaErrorsWhenTheUserTriesToSignInOfflineAndAllowsSignInWhenBackOnline =
- (isIdapi = false) => {
- return [
- 'shows reCAPTCHA errors when the user tries to sign in offline and allows sign in when back online',
- () => {
- // Intercept the external redirect page.
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', 'https://m.code.dev-theguardian.com/', (req) => {
- req.reply(200);
- });
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress, finalPassword }) => {
- const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
- cy.visit(visitUrl);
-
- // Simulate going offline by failing to reCAPTCHA POST request.
- cy.intercept({
- method: 'POST',
- url: 'https://www.google.com/recaptcha/api2/**',
- times: 1,
- });
-
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.contains(
- 'Google reCAPTCHA verification failed. Please try again.',
- );
-
- // On second click, an expanded error is shown.
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains('Google reCAPTCHA verification failed.');
- cy.contains('Report this error').should(
- 'have.attr',
- 'href',
- 'https://manage.theguardian.com/help-centre/contact-us',
- );
- cy.contains('If the problem persists please try the following:');
-
- cy.get('[data-cy="main-form-submit-button"]').click();
-
- cy.contains(
- 'Google reCAPTCHA verification failed. Please try again.',
- ).should('not.exist');
-
- cy.url().should('include', 'https://m.code.dev-theguardian.com/');
- });
- },
- ] as const;
- };
+ (isIdapi = false) => {
+ return [
+ 'shows reCAPTCHA errors when the user tries to sign in offline and allows sign in when back online',
+ () => {
+ // Intercept the external redirect page.
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', 'https://m.code.dev-theguardian.com/', (req) => {
+ req.reply(200);
+ });
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress, finalPassword }) => {
+ const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
+ cy.visit(visitUrl);
+
+ // Simulate going offline by failing to reCAPTCHA POST request.
+ cy.intercept({
+ method: 'POST',
+ url: 'https://www.google.com/recaptcha/api2/**',
+ times: 1,
+ });
+
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.contains(
+ 'Google reCAPTCHA verification failed. Please try again.',
+ );
+
+ // On second click, an expanded error is shown.
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains('Google reCAPTCHA verification failed.');
+ cy.contains('Report this error').should(
+ 'have.attr',
+ 'href',
+ 'https://manage.theguardian.com/help-centre/contact-us',
+ );
+ cy.contains('If the problem persists please try the following:');
+
+ cy.get('[data-cy="main-form-submit-button"]').click();
+
+ cy.contains(
+ 'Google reCAPTCHA verification failed. Please try again.',
+ ).should('not.exist');
+
+ cy.url().should('include', 'https://m.code.dev-theguardian.com/');
+ });
+ },
+ ] as const;
+ };
export const redirectsToOptInPrompt = (isIdapi = false) => {
- return [
- 'redirects user to prompt if they are not a supporter',
- () => {
- // Intercept the prompt page
- // We just want to check that the redirect happens, not that the page loads.
- cy.intercept('GET', '/signin/success*', (req) => {
- req.reply(200);
- });
- // Enable the opt in prompt "experiment"
- cy.clearCookie('GU_ran_experiments');
- cy
- .createTestUser({
- isUserEmailValidated: true,
- })
- ?.then(({ emailAddress, finalPassword }) => {
- const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
- cy.visit(visitUrl);
- cy.get('input[name=email]').type(emailAddress);
- cy.get('input[name=password]').type(finalPassword);
- cy.get('[data-cy="main-form-submit-button"]').click();
- cy.url().should('include', `/signin/success`);
- cy.url().should(
- 'include',
- `returnUrl=${encodeURIComponent(
- 'https://m.code.dev-theguardian.com/',
- )}`,
- );
- });
- },
- ] as const;
+ return [
+ 'redirects user to prompt if they are not a supporter',
+ () => {
+ // Intercept the prompt page
+ // We just want to check that the redirect happens, not that the page loads.
+ cy.intercept('GET', '/signin/success*', (req) => {
+ req.reply(200);
+ });
+ // Enable the opt in prompt "experiment"
+ cy.clearCookie('GU_ran_experiments');
+ cy
+ .createTestUser({
+ isUserEmailValidated: true,
+ })
+ ?.then(({ emailAddress, finalPassword }) => {
+ const visitUrl = isIdapi ? '/signin?useIdapi=true' : '/signin';
+ cy.visit(visitUrl);
+ cy.get('input[name=email]').type(emailAddress);
+ cy.get('input[name=password]').type(finalPassword);
+ cy.get('[data-cy="main-form-submit-button"]').click();
+ cy.url().should('include', `/signin/success`);
+ cy.url().should(
+ 'include',
+ `returnUrl=${encodeURIComponent(
+ 'https://m.code.dev-theguardian.com/',
+ )}`,
+ );
+ });
+ },
+ ] as const;
};
diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts
index b25a46461c..b3cd1c6d74 100644
--- a/cypress/support/commands.ts
+++ b/cypress/support/commands.ts
@@ -12,30 +12,30 @@ import { lastPayloadIs } from './commands/lastPayloadIs';
import { lastPayloadsAre } from './commands/lastPayloadsAre';
import { checkForEmailAndGetDetails } from './commands/getEmailDetails';
import {
- disableCMP,
- enableCMP,
- acceptCMP,
- declineCMP,
+ disableCMP,
+ enableCMP,
+ acceptCMP,
+ declineCMP,
} from './commands/manageCmp';
import {
- getTestOktaUser,
- activateTestOktaUser,
- createTestUser,
- resetOktaUserPassword,
- expireOktaUserPassword,
- suspendOktaUser,
- addOktaUserToGroup,
- findEmailValidatedOktaGroupId,
- getOktaUserGroups,
- getTestUserDetails,
- addToGRS,
- updateTestUser,
- updateOktaTestUserProfile,
- getCurrentOktaSession,
- closeCurrentOktaSession,
- subscribeToNewsletter,
- subscribeToMarketingConsent,
- sendConsentEmail,
+ getTestOktaUser,
+ activateTestOktaUser,
+ createTestUser,
+ resetOktaUserPassword,
+ expireOktaUserPassword,
+ suspendOktaUser,
+ addOktaUserToGroup,
+ findEmailValidatedOktaGroupId,
+ getOktaUserGroups,
+ getTestUserDetails,
+ addToGRS,
+ updateTestUser,
+ updateOktaTestUserProfile,
+ getCurrentOktaSession,
+ closeCurrentOktaSession,
+ subscribeToNewsletter,
+ subscribeToMarketingConsent,
+ sendConsentEmail,
} from './commands/testUser';
Cypress.Commands.add('mockNext', mockNext);
@@ -61,8 +61,8 @@ Cypress.Commands.add('expireOktaUserPassword', expireOktaUserPassword);
Cypress.Commands.add('suspendOktaUser', suspendOktaUser);
Cypress.Commands.add('addOktaUserToGroup', addOktaUserToGroup);
Cypress.Commands.add(
- 'findEmailValidatedOktaGroupId',
- findEmailValidatedOktaGroupId,
+ 'findEmailValidatedOktaGroupId',
+ findEmailValidatedOktaGroupId,
);
Cypress.Commands.add('getOktaUserGroups', getOktaUserGroups);
Cypress.Commands.add('getTestUserDetails', getTestUserDetails);
@@ -73,7 +73,7 @@ Cypress.Commands.add('getCurrentOktaSession', getCurrentOktaSession);
Cypress.Commands.add('closeCurrentOktaSession', closeCurrentOktaSession);
Cypress.Commands.add('subscribeToNewsletter', subscribeToNewsletter);
Cypress.Commands.add(
- 'subscribeToMarketingConsent',
- subscribeToMarketingConsent,
+ 'subscribeToMarketingConsent',
+ subscribeToMarketingConsent,
);
Cypress.Commands.add('sendConsentEmail', sendConsentEmail);
diff --git a/cypress/support/commands/getEmailDetails.ts b/cypress/support/commands/getEmailDetails.ts
index d6eb1ff97c..0ff5de19ee 100644
--- a/cypress/support/commands/getEmailDetails.ts
+++ b/cypress/support/commands/getEmailDetails.ts
@@ -1,11 +1,11 @@
import { Link, Message } from 'cypress-mailosaur';
declare global {
- // eslint-disable-next-line @typescript-eslint/no-namespace
- namespace Cypress {
- interface Chainable {
- checkForEmailAndGetDetails: typeof checkForEmailAndGetDetails;
- }
- }
+ // eslint-disable-next-line @typescript-eslint/no-namespace
+ namespace Cypress {
+ interface Chainable {
+ checkForEmailAndGetDetails: typeof checkForEmailAndGetDetails;
+ }
+ }
}
/**
@@ -18,34 +18,34 @@ declare global {
* @returns The email details.
*/
export const checkForEmailAndGetDetails = (
- sentTo: string,
- receivedAfter?: Date,
- tokenMatcher?: RegExp,
- deleteAfter = true,
+ sentTo: string,
+ receivedAfter?: Date,
+ tokenMatcher?: RegExp,
+ deleteAfter = true,
) => {
- return cy
- .mailosaurGetMessage(
- Cypress.env('MAILOSAUR_SERVER_ID'),
- { sentTo },
- {
- receivedAfter,
- },
- )
- .then((message: Message) => {
- return getEmailDetails(message, tokenMatcher).then((details) => {
- if (deleteAfter) {
- cy.mailosaurDeleteMessage(details.id);
- }
- return cy.wrap(details);
- });
- });
+ return cy
+ .mailosaurGetMessage(
+ Cypress.env('MAILOSAUR_SERVER_ID'),
+ { sentTo },
+ {
+ receivedAfter,
+ },
+ )
+ .then((message: Message) => {
+ return getEmailDetails(message, tokenMatcher).then((details) => {
+ if (deleteAfter) {
+ cy.mailosaurDeleteMessage(details.id);
+ }
+ return cy.wrap(details);
+ });
+ });
};
type EmailDetails = {
- id: string;
- body: string;
- token?: string;
- links: Link[];
+ id: string;
+ body: string;
+ token?: string;
+ links: Link[];
};
/**
@@ -56,22 +56,22 @@ type EmailDetails = {
* @returns The email details.
*/
const getEmailDetails = (email: Message, tokenMatcher?: RegExp) => {
- const { id, html } = email;
- const { body, links } = html || {};
- if (id === undefined || body === undefined || links === undefined) {
- throw new Error('Email details not found');
- }
- // eslint-disable-next-line functional/no-let
- let token = undefined;
- if (tokenMatcher) {
- const match = body.match(tokenMatcher);
- if (match === null) {
- throw new Error(
- 'Unable to find token in the email body with the given regex',
- );
- }
- token = match[1];
- }
+ const { id, html } = email;
+ const { body, links } = html || {};
+ if (id === undefined || body === undefined || links === undefined) {
+ throw new Error('Email details not found');
+ }
+ // eslint-disable-next-line functional/no-let
+ let token = undefined;
+ if (tokenMatcher) {
+ const match = body.match(tokenMatcher);
+ if (match === null) {
+ throw new Error(
+ 'Unable to find token in the email body with the given regex',
+ );
+ }
+ token = match[1];
+ }
- return cy.wrap({ id, body, token, links });
+ return cy.wrap({ id, body, token, links });
};
diff --git a/cypress/support/commands/lastPayloadIs.ts b/cypress/support/commands/lastPayloadIs.ts
index 1ad6590229..4a6ed87ffb 100644
--- a/cypress/support/commands/lastPayloadIs.ts
+++ b/cypress/support/commands/lastPayloadIs.ts
@@ -3,12 +3,12 @@
*/
declare global {
- // eslint-disable-next-line @typescript-eslint/no-namespace
- namespace Cypress {
- interface Chainable {
- lastPayloadIs: typeof lastPayloadIs;
- }
- }
+ // eslint-disable-next-line @typescript-eslint/no-namespace
+ namespace Cypress {
+ interface Chainable {
+ lastPayloadIs: typeof lastPayloadIs;
+ }
+ }
}
/**
@@ -17,9 +17,9 @@ declare global {
* @returns A chainable cypress command.
*/
export const lastPayloadIs = (expectedPayload: Array
- }
- />,
- );
+ return renderMJMLComponent(
+