From b64f24cf6a9d37887355be3948b12d68736ed5af Mon Sep 17 00:00:00 2001 From: Clara Youdale Date: Fri, 7 Jun 2024 14:03:10 -0300 Subject: [PATCH 1/6] Create citeEdit.spec.ts --- site/gatsby-site/playwright/e2e/citeEdit.spec.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 site/gatsby-site/playwright/e2e/citeEdit.spec.ts diff --git a/site/gatsby-site/playwright/e2e/citeEdit.spec.ts b/site/gatsby-site/playwright/e2e/citeEdit.spec.ts new file mode 100644 index 0000000000..beb8669a54 --- /dev/null +++ b/site/gatsby-site/playwright/e2e/citeEdit.spec.ts @@ -0,0 +1,5 @@ +import { test } from '@playwright/test'; + +test.describe('Edit report', () => { + +}); \ No newline at end of file From 111f9a226c5c8f47f01ab828fc79570ad3f47431 Mon Sep 17 00:00:00 2001 From: Clara Youdale Date: Tue, 11 Jun 2024 11:27:51 -0300 Subject: [PATCH 2/6] Add "Should delete incident report" and "Should link a report to another incident" test --- .../playwright/e2e/citeEdit.spec.ts | 720 +++++++++++++++++- .../reports/issueWithTranslations.json | 50 ++ .../playwright/fixtures/reports/report.json | 37 + .../reports/reportWithTranslations.json | 44 ++ .../fixtures/reports/updateOneReport.json | 26 + .../reports/updateOneReportTranslation.json | 10 + site/gatsby-site/playwright/utils.ts | 23 + 7 files changed, 909 insertions(+), 1 deletion(-) create mode 100644 site/gatsby-site/playwright/fixtures/reports/issueWithTranslations.json create mode 100644 site/gatsby-site/playwright/fixtures/reports/report.json create mode 100644 site/gatsby-site/playwright/fixtures/reports/reportWithTranslations.json create mode 100644 site/gatsby-site/playwright/fixtures/reports/updateOneReport.json create mode 100644 site/gatsby-site/playwright/fixtures/reports/updateOneReportTranslation.json diff --git a/site/gatsby-site/playwright/e2e/citeEdit.spec.ts b/site/gatsby-site/playwright/e2e/citeEdit.spec.ts index beb8669a54..f16330d6d5 100644 --- a/site/gatsby-site/playwright/e2e/citeEdit.spec.ts +++ b/site/gatsby-site/playwright/e2e/citeEdit.spec.ts @@ -1,5 +1,723 @@ -import { test } from '@playwright/test'; +import { conditionalIntercept, waitForRequest, query, login, maybeIt, setEditorText, getEditorText } from '../utils'; +import { format, getUnixTime } from 'date-fns'; +import { gql } from '@apollo/client'; +import { test, expect } from '@playwright/test'; +import config from '../config'; +import reportWithTranslations from '../fixtures/reports/reportWithTranslations.json'; +import report10 from '../fixtures/reports/report.json'; +import updateOneReport from '../fixtures/reports/updateOneReport.json'; +import updateOneReportTranslation from '../fixtures/reports/updateOneReportTranslation.json'; +import issueWithTranslations from '../fixtures/reports/issueWithTranslations.json'; +import assert from 'assert'; test.describe('Edit report', () => { + const url = '/cite/edit?report_number=10'; + + let user; + + test.beforeAll(async () => { + const response = await query({ + query: gql` + { + user(query: { first_name: "Test", last_name: "User" }) { + userId + first_name + last_name + } + } + `, + }); + user = response.data.user; + }); + + test('Successfully loads', async ({ page }) => { + await page.goto(url); + await page.evaluate(() => { + document.querySelectorAll('*').forEach(el => { + el.style.scrollBehavior = 'auto'; + }); + }); + }); + + maybeIt('Should load and update report values', async ({ page }) => { + await login(page, config.E2E_ADMIN_USERNAME, config.E2E_ADMIN_PASSWORD); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindReportWithTranslations', + reportWithTranslations, + 'FindReportWithTranslations' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindReport', + report10, + 'FindReport' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindIncidents', + { + data: { + incidents: [ + { + _typename: 'Incident', + incident_id: 1, + title: 'Incident 1', + }, + ], + }, + }, + 'FindIncidents' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindIncidentsTitles', + { + data: { + incidents: [ + { + _typename: 'Incident', + incident_id: 1, + title: 'Incident 1', + }, + { + _typename: 'Incident', + incident_id: 2, + title: 'Incident 2', + }, + ], + }, + }, + 'FindIncidentsTitles' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'logReportHistory', + { + data: { + logReportHistory: { + report_number: 10, + }, + }, + }, + 'logReportHistory' + ); + + await page.goto(url); + + await Promise.all([ + waitForRequest('FindReportWithTranslations'), + waitForRequest('FindIncidents'), + waitForRequest('FindReport') + ]); + + [ + 'authors', + 'date_downloaded', + 'date_published', + 'image_url', + 'submitters', + 'title', + 'editor_notes', + ].forEach(async (key) => { + const locator = page.locator(`[name=${key}]`); + await expect(locator).toHaveValue(reportWithTranslations.data.report[key].toString()); + }); + + + + // await expect(page.locator('[data-cy="text"] .CodeMirror')).toHaveText(reportWithTranslations.data.report.text); + let editorText = await getEditorText(page); + await expect(editorText).toBe(reportWithTranslations.data.report.text); + + await expect(page.locator('label:has-text("Incident IDs") + * [data-cy="token"]:has-text("Incident 1")')).toBeVisible(); + + + await expect(page.locator('.submit-report-tags [option="Test Tag"]')).toHaveCount(1); + + await expect(page.locator('[data-cy="translation-es"] [type="text"]')).toHaveValue(reportWithTranslations.data.report.translations_es.title); + + editorText = await getEditorText(page, '[data-cy="translation-es"] .CodeMirror'); + await expect(editorText).toBe(reportWithTranslations.data.report.translations_es.text); + + const updates = { + authors: 'Test Author', + date_downloaded: '2022-01-01', + date_published: '2022-02-02', + image_url: 'https://test.com/test.jpg', + submitters: 'Test Submitter', + title: 'Test Title', + url: 'https://www.test.com/test', + editor_notes: 'Pro iustitia tantum', + }; + + for (const [key, value] of Object.entries(updates)) { + const locator = page.locator(`[name=${key}]`); + await locator.fill(''); + await locator.fill(value); + } + + await page.locator(`[name="quiet"]`).click(); + + await setEditorText(page, '## This is text in English\n\nthat is longer that eighty characters, yes eighty characters!'); + + await page.locator('[id^=submit-report-tags]').fill('New Tag'); + await page.locator('a[aria-label="New Tag"]').click(); + + await page.locator('[data-cy="translation-es"] [type="text"]').fill('Este es un titulo en Espanol!'); + + await setEditorText(page, '## Este es texto en espanol\n\nque es mas largo que ochenta caracters, si ochenta caracteres!', '[data-cy="translation-es"] .CodeMirror'); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'UpdateReport', + updateOneReport, + 'updateReport' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'UpdateReportTranslation', + updateOneReportTranslation, + 'updateOneReportTranslation' + ); + + const now = new Date(); + await page.context().addInitScript(`{ + const now = ${now.getTime()}; + Date.now = () => now; + const originalDate = Date; + globalThis.Date = class extends originalDate { + constructor(...args) { + if (args.length === 0) { + super(now); + } else { + super(...args); + } + } + } + }`); + + await page.locator('button:has-text("Submit")').click(); + + const updateReportRequest = await waitForRequest('updateReport'); + const variables = updateReportRequest.postDataJSON().variables; + + const expectedReport = { + authors: ['Test Author'], + cloudinary_id: 'reports/test.com/test.jpg', + date_downloaded: new Date('2022-01-01').toISOString(), + date_modified: format(now, 'yyyy-MM-dd'), + date_published: new Date('2022-02-02').toISOString(), + epoch_date_modified: getUnixTime(now), + epoch_date_published: 1643760000, + flag: null, + image_url: 'https://test.com/test.jpg', + report_number: 10, + submitters: ['Test Submitter'], + tags: ['Test Tag', 'New Tag'], + text: '## This is text in English\n\nthat is longer that eighty characters, yes eighty characters!', + plain_text: + 'This is text in English\n\nthat is longer that eighty characters, yes eighty characters!\n', + title: 'Test Title', + url: 'https://www.test.com/test', + source_domain: 'test.com', + editor_notes: 'Pro iustitia tantum', + language: 'en', + quiet: true, + }; + + expect(variables.query.report_number).toBe(10); + + const expectedResult = { + ...expectedReport, + date_modified: format(new Date(variables.set.date_modified), 'yyyy-MM-dd') + } + + expect({ + ...variables.set, + date_modified: format(new Date(variables.set.date_modified), 'yyyy-MM-dd') + } + ).toEqual(expectedResult); + + const logReportHistoryRequest = await waitForRequest('logReportHistory'); + const input = logReportHistoryRequest.postDataJSON().variables.input; + const expectedReportResult = { + ...report10.data.report, + ...expectedReport, + modifiedBy: user.userId, + user: report10.data.report.user.userId, + date_modified: input.date_modified, + }; + + expect(input).toEqual(expectedReportResult); + + const updateOneReportTranslationRequest = await waitForRequest('updateOneReportTranslation'); + const translationVariables = updateOneReportTranslationRequest.postDataJSON().variables.input; + expect(translationVariables.language).toBe('es'); + expect(translationVariables.report_number).toBe(10); + expect(translationVariables.text).toBe('## Este es texto en espanol\n\nque es mas largo que ochenta caracters, si ochenta caracteres!'); + expect(translationVariables.plain_text).toBe('Este es texto en espanol\n\nque es mas largo que ochenta caracters, si ochenta caracteres!\n'); + expect(translationVariables.title).toBe('Este es un titulo en Espanol!'); + + await expect(page.locator('.tw-toast:has-text("Incident report 10 updated successfully.")')).toBeVisible(); + }); + + test('Should load and update Issue values', async ({ page }) => { + await login(page, config.E2E_ADMIN_USERNAME, config.E2E_ADMIN_PASSWORD); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindReportWithTranslations', + issueWithTranslations, + 'FindReportWithTranslations' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindReport', + report10, + 'FindReport' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindIncidents', + { data: { incidents: [] } }, + 'FindIncidents' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindIncidentsTitles', + { data: { incidents: [{ _typename: 'Incident', incident_id: 1, title: 'Incident 1' }] } }, + 'FindIncidentsTitles' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'logReportHistory', + { data: { logReportHistory: { report_number: 10 } } }, + 'logReportHistory' + ); + + await page.goto(url); + + await Promise.all([ + waitForRequest('FindReportWithTranslations'), + waitForRequest('FindIncidents'), + waitForRequest('FindReport') + ]); + + for (const key of ['authors', 'date_downloaded', 'date_published', 'image_url', 'submitters', 'title', 'editor_notes']) { + await expect(page.locator(`[name=${key}]`)).toHaveValue(reportWithTranslations.data.report[key].toString()); + } + + const text = await getEditorText(page); + expect(text).toBe(reportWithTranslations.data.report.text); + + await expect(page.locator(`[name="incident_id"]`)).not.toBeVisible(); + + await expect(page.locator('.submit-report-tags [option="Test Tag"]')).toHaveCount(1); + + await expect(page.locator('[data-cy="translation-es"] [type="text"]')).toHaveValue(reportWithTranslations.data.report.translations_es.title); + + const esText = await getEditorText(page, '[data-cy="translation-es"] .CodeMirror'); + expect(esText).toBe(reportWithTranslations.data.report.translations_es.text); + + const updates = { + authors: 'Test Author', + date_downloaded: '2022-01-01', + date_published: '2022-02-02', + image_url: 'https://test.com/test.jpg', + submitters: 'Test Submitter', + title: 'Test Title', + url: 'https://www.test.com/test', + editor_notes: 'Pro iustitia tantum' + }; + + for (const [key, value] of Object.entries(updates)) { + await page.locator(`[name=${key}]`).fill(value); + } + + await setEditorText(page, '## This is text in English\n\nthat is longer that eighty characters, yes eighty characters!', '[data-cy="text"] .CodeMirror'); + + await page.locator('[id^=submit-report-tags]').fill('New Tag'); + await page.locator('a[aria-label="New Tag"]').click(); + + await page.locator('[data-cy="translation-es"] [type="text"]').fill('Este es un titulo en Espanol!'); + + await setEditorText(page, '## Este es texto en espanol\n\nque es mas largo que ochenta caracters, si ochenta caracteres!', '[data-cy="translation-es"] .CodeMirror'); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'UpdateReport', + updateOneReport, + 'updateReport' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'UpdateReportTranslation', + updateOneReportTranslation, + 'updateOneReportTranslation' + ); + + const now = new Date(); + await page.context().addInitScript(`Date = class extends Date { constructor() { super("${now.toISOString()}"); } }`); + + await page.locator('button:has-text("Submit")').click(); + + const expectedReport = { + authors: ['Test Author'], + cloudinary_id: 'reports/test.com/test.jpg', + date_downloaded: new Date('2022-01-01').toISOString(), + date_modified: format(now, 'yyyy-MM-dd'), + date_published: new Date('2022-02-02').toISOString(), + epoch_date_modified: getUnixTime(now), + epoch_date_published: 1643760000, + flag: null, + image_url: 'https://test.com/test.jpg', + report_number: 10, + submitters: ['Test Submitter'], + tags: ['Test Tag', 'New Tag'], + text: '## This is text in English\n\nthat is longer that eighty characters, yes eighty characters!', + plain_text: 'This is text in English\n\nthat is longer that eighty characters, yes eighty characters!\n', + title: 'Test Title', + url: 'https://www.test.com/test', + source_domain: 'test.com', + editor_notes: 'Pro iustitia tantum', + language: 'en' + }; + + const updateReportRequest = await waitForRequest('updateReport'); + const variables = updateReportRequest.postDataJSON().variables; + expect(variables.query.report_number).toBe(10); + expect({ ...variables.set, date_modified: format(new Date(variables.set.date_modified), 'yyyy-MM-dd') }).toEqual(expectedReport); + + const logReportHistoryRequest = await waitForRequest('logReportHistory'); + const input = logReportHistoryRequest.postDataJSON().variables.input; + const expectedResult = { ...report10.data.report, ...expectedReport, modifiedBy: user.userId, user: report10.data.report.user.userId, date_modified: input.date_modified }; + expect(input).toEqual(expectedResult); + + const updateOneReportTranslationRequest = await waitForRequest('updateOneReportTranslation'); + const translationVariables = updateOneReportTranslationRequest.postDataJSON().variables.input; + expect(translationVariables.language).toBe('es'); + expect(translationVariables.report_number).toBe(10); + expect(translationVariables.text).toBe('## Este es texto en espanol\n\nque es mas largo que ochenta caracters, si ochenta caracteres!'); + expect(translationVariables.plain_text).toBe('Este es texto en espanol\n\nque es mas largo que ochenta caracters, si ochenta caracteres!\n'); + expect(translationVariables.title).toBe('Este es un titulo en Espanol!'); + + await expect(page.locator('[data-cy="toast"]:has-text("Issue 10 updated successfully")')).toBeVisible(); + }); + + maybeIt('Should delete incident report', async ({ page }) => { + await login(page, config.E2E_ADMIN_USERNAME, config.E2E_ADMIN_PASSWORD); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindReportWithTranslations', + issueWithTranslations, + 'FindReportWithTranslations' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindIncidents', + { data: { incidents: [] } }, + 'FindIncidents' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindIncidentsTitles', + { + data: { + incidents: [ + { _typename: 'Incident', incident_id: 1, title: 'Incident 1' } + ] + } + }, + 'FindIncidentsTitles' + ); + + await page.goto(url); + + await Promise.all([ + waitForRequest('FindIncidents'), + waitForRequest('FindIncidentsTitles'), + waitForRequest('FindReportWithTranslations') + ]); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'DeleteOneReport', + { data: { deleteOneReport: { __typename: 'Report', report_number: 10 } } }, + 'DeleteReport' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'LinkReportsToIncidents', + { data: { linkReportsToIncidents: [] } }, + 'LinkReportsToIncidents' + ); + + // Set up the dialog event listener before triggering the click action + page.once('dialog', async dialog => { + await dialog.accept(); + + const deleteRequest = await waitForRequest('DeleteReport'); + expect(deleteRequest.postDataJSON().variables.query).toEqual({ report_number: 10 }); + + const linkReportsToIncidentsRequest = await waitForRequest('LinkReportsToIncidents'); + expect(linkReportsToIncidentsRequest.postDataJSON().variables.input).toEqual({ + incident_ids: [], + report_numbers: [10] + }); + + await expect(page.locator('[data-cy="toast"]:has-text("Incident report 10 deleted successfully")')).toBeVisible(); + }); + + await page.locator('button:has-text("Delete this report")').click(); + + await page.waitForTimeout(2000); // Needed to wait for the dialog to be accepted + }); + + maybeIt('Should link a report to another incident', async ({ page }) => { + await login(page, config.E2E_ADMIN_USERNAME, config.E2E_ADMIN_PASSWORD); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindReport', + report10, + 'FindReport' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'ProbablyRelatedReports', + { data: { reports: [] } }, + 'ProbablyRelatedReports' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'ProbablyRelatedIncidents', + { data: { incidents: [] } }, + 'ProbablyRelatedIncidents' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindReportWithTranslations', + reportWithTranslations, + 'FindReportWithTranslations' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindIncidents', + { + data: { + incidents: [ + { + __typename: 'Incident', + incident_id: 1, + title: 'Incident 1', + }, + ], + }, + }, + 'FindIncidents' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindIncidentsTitles', + { + data: { + incidents: [ + { + _typename: 'Incident', + incident_id: 1, + title: 'Incident 1', + }, + { + _typename: 'Incident', + incident_id: 2, + title: 'Incident 2', + }, + ], + }, + }, + 'FindIncidentsTitles' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'logReportHistory', + { + data: { + logReportHistory: { + report_number: 10, + }, + }, + }, + 'logReportHistory' + ); + + await page.goto(`/cite/edit?report_number=23`); + + await Promise.all([ + waitForRequest('FindReportWithTranslations'), + waitForRequest('FindIncidents'), + waitForRequest('FindIncidentsTitles') + ]); + + await expect(page.locator('form[data-cy="report"]')).toBeVisible(); + + await page.locator('div:has-text("Incident 1")'); + // .locator('xpath=following-sibling::*[1]').click(); + + await page.locator('[name="incident_ids"]').fill('2'); + + await page.locator('[id="incident_ids-item-0"]').click(); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'UpdateReportTranslation', + updateOneReportTranslation, + 'updateOneReportTranslation' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'UpdateReport', + updateOneReport, + 'UpdateReport' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'LinkReportsToIncidents', + { data: { linkReportsToIncidents: [] } }, + 'LinkReportsToIncidents' + ); + + const now = new Date(); + await page.context().addInitScript({ content: `Date = function() { return new Date(${now.getTime()}); }` }); + + await page.locator('button:has-text("Submit")').click(); + + const expectedReport = { + authors: ['Marco Acevedo'], + cloudinary_id: 'reports/assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975', + date_downloaded: new Date('2019-04-13').toISOString(), + date_modified: format(now, 'yyyy-MM-dd'), + date_published: new Date('2015-07-11').toISOString(), + editor_notes: '', + epoch_date_modified: getUnixTime(now), + epoch_date_published: 1436572800, + flag: null, + image_url: 'https://assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975', + language: 'en', + plain_text: 'Video still of a reproduced version of Minnie Mouse\n\nWhich appeared on the now-suspended Simple Fun channel Simple Fun.\n', + report_number: 10, + source_domain: 'change.org', + submitters: ['Roman Yampolskiy'], + tags: ['Test Tag'], + text: '## Video still of a reproduced version of Minnie Mouse\n\nWhich appeared on the now-suspended Simple Fun channel Simple Fun.', + title: 'Remove YouTube Kids app until it eliminates its inappropriate content', + url: 'https://www.change.org/p/remove-youtube-kids-app-until-it-eliminates-its-inappropriate-content', + }; + + const updateReportRequest = await waitForRequest('UpdateReport'); + const variables = updateReportRequest.postDataJSON().variables; + expect(variables.query.report_number).toBe(23); + expect({ + ...variables.set, + date_modified: format(new Date(variables.set.date_modified), 'yyyy-MM-dd'), + }).toEqual(expectedReport); + + const logReportHistoryRequest = await waitForRequest('logReportHistory'); + const input = logReportHistoryRequest.postDataJSON().variables.input; + const expectedResult = { + ...report10.data.report, + ...expectedReport, + modifiedBy: user.userId, + user: report10.data.report.user.userId, + date_modified: input.date_modified, + }; + expect(input).toEqual(expectedResult); + + const updateOneReportTranslationRequest1 = await waitForRequest('updateOneReportTranslation'); + let translationVariables = updateOneReportTranslationRequest1.postDataJSON().variables; + expect(translationVariables.input.title).toBe('Este es el Título en español'); + expect(translationVariables.input.text).toBe('Este es un texto de prueba que tiene un largo mayor a ochenta caracteres (en español)'); + expect(translationVariables.input.language).toBe('es'); + expect(translationVariables.input.report_number).toBe(23); + expect(translationVariables.input.plain_text).toBe('Este es un texto de prueba que tiene un largo mayor a ochenta caracteres (en español)\n'); + + const updateOneReportTranslationRequest2 = await waitForRequest('updateOneReportTranslation'); + translationVariables = updateOneReportTranslationRequest2.postDataJSON().variables; + expect(translationVariables.input.title).toBe(`C'est le Titre en français`); + expect(translationVariables.input.text).toBe(`Il s'agit d'un texte de test de plus de quatre-vingts caractères - lorem ipsum (en français)`); + expect(translationVariables.input.language).toBe('fr'); + expect(translationVariables.input.report_number).toBe(23); + expect(translationVariables.input.plain_text).toBe(`Il s'agit d'un texte de test de plus de quatre-vingts caractères - lorem ipsum (en français)\n`); + + const updateOneReportTranslationRequest3 = await waitForRequest('updateOneReportTranslation'); + translationVariables = updateOneReportTranslationRequest3.postDataJSON().variables; + expect(translationVariables.input.title).toBe('これは日本語でのタイトルです'); + expect(translationVariables.input.text).toBe('解サオライ協立なーづ民手ぶみドに即記朝ぐ奥置ぱで地更トるあて栄厚ぜづを祭屋ん来派どてゃ読速ヘ誌約カタシネ原39業理る。外ヒヱフ社第むせゆ由更混ソエ夕野しりすよ顔飛リの兆基う公言や置17謝后嘘5供フキヌア星集ヘラ辞勘壇崇さびわ。(日本語で)'); + expect(translationVariables.input.language).toBe('ja'); + expect(translationVariables.input.report_number).toBe(23); + expect(translationVariables.input.plain_text).toBe('解サオライ協立なーづ民手ぶみドに即記朝ぐ奥置ぱで地更トるあて栄厚ぜづを祭屋ん来派どてゃ読速ヘ誌約カタシネ原39業理る。外ヒヱフ社第むせゆ由更混ソエ夕野しりすよ顔飛リの兆基う公言や置17謝后嘘5供フキヌア星集ヘラ辞勘壇崇さびわ。(日本語で)\n'); + + const linkReportsToIncidentsRequest = await waitForRequest('LinkReportsToIncidents'); + expect(linkReportsToIncidentsRequest.postDataJSON().variables.input).toEqual({ + incident_ids: [2], + report_numbers: [23], + }); + + await expect(page.locator('[data-cy="toast"]')).toContainText('Incident report 23 updated successfully'); +}); + + }); \ No newline at end of file diff --git a/site/gatsby-site/playwright/fixtures/reports/issueWithTranslations.json b/site/gatsby-site/playwright/fixtures/reports/issueWithTranslations.json new file mode 100644 index 0000000000..a304a6f318 --- /dev/null +++ b/site/gatsby-site/playwright/fixtures/reports/issueWithTranslations.json @@ -0,0 +1,50 @@ +{ + "data": { + "report": { + "authors": [ + "Marco Acevedo" + ], + "date_downloaded": "2019-04-13", + "date_published": "2015-07-11", + "flag": null, + "image_url": "https://assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975", + "report_number": 10, + "submitters": [ + "Roman Yampolskiy" + ], + "tags": [ + "Test Tag" + ], + "text": "## Video still of a reproduced version of Minnie Mouse\n\nWhich appeared on the now-suspended Simple Fun channel Simple Fun.", + "plain_text": "Video still of a reproduced version of Minnie Mouse\n\nWhich appeared on the now-suspended Simple Fun channel Simple Fun.", + "title": "Remove YouTube Kids app until it eliminates its inappropriate content", + "description": "Description Remove YouTube Kids app until it eliminates its inappropriate content", + "url": "https://www.change.org/p/remove-youtube-kids-app-until-it-eliminates-its-inappropriate-content", + "editor_notes": "", + "language": "en", + "translations_es": { + "__typename": "ReportTranslation", + "title": "Este es el Título en español", + "text": "Este es un texto de prueba que tiene un largo mayor a ochenta caracteres (en español)" + }, + "translations_en": { + "__typename": "ReportTranslation", + "title": "", + "text": "" + }, + "translations_fr": { + "__typename": "ReportTranslation", + "title": "C'est le Titre en français", + "text": "Il s'agit d'un texte de test de plus de quatre-vingts caractères - lorem ipsum (en français)" + }, + "translations_ja": { + "__typename": "ReportTranslation", + "title": "これは日本語でのタイトルです", + "text": "解サオライ協立なーづ民手ぶみドに即記朝ぐ奥置ぱで地更トるあて栄厚ぜづを祭屋ん来派どてゃ読速ヘ誌約カタシネ原39業理る。外ヒヱフ社第むせゆ由更混ソエ夕野しりすよ顔飛リの兆基う公言や置17謝后嘘5供フキヌア星集ヘラ辞勘壇崇さびわ。(日本語で)" + }, + "date_modified": "2023-01-01", + "epoch_date_modified": 1672531200, + "is_incident_report": false + } + } +} \ No newline at end of file diff --git a/site/gatsby-site/playwright/fixtures/reports/report.json b/site/gatsby-site/playwright/fixtures/reports/report.json new file mode 100644 index 0000000000..1ae223f554 --- /dev/null +++ b/site/gatsby-site/playwright/fixtures/reports/report.json @@ -0,0 +1,37 @@ +{ + "data": { + "report": { + "authors": ["Marco Acevedo"], + "cloudinary_id": "reports/assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975", + "date_downloaded": "2019-04-13", + "date_modified": "2020-06-14", + "date_published": "2015-07-11", + "date_submitted": "2019-06-01", + "editor_notes": "", + "embedding": { + "from_text_hash": "12256b4f3816b968a2224017eac1bf7d5c6b98e5", + "vector": [-0.09368586540222168, 0.02987837791442871, 0.03945714980363846] + }, + "epoch_date_downloaded": 1555113600, + "epoch_date_modified": 1592092800, + "epoch_date_published": 1436572800, + "epoch_date_submitted": 1559347200, + "flag": null, + "image_url": "https://assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975", + "is_incident_report": true, + "language": "en", + "plain_text": "Videos filled with profanity, sexually explicit material, alcohol, smoking, and drug references - this is what parents are finding on Google’s YouTube Kids app. That’s right - its kids app. Now, parents across the country are calling on Google to remove the app until it can guarantee the total elimination of this inappropriate content.\n\nWhen my neighbors told me about the horrible adult content popping up on the Youtube Kids app, I thought there must be a mistake. Why would Google market an app as “a family-friendly place to explore” and not have proper safeguards in place? Unfortunately, it turned out to be true. And I’ve since learned of the numerous complaints filed to the Federal Trade Commission about this very problem.\n\nEven worse, Google’s response has been laughable. They tell parents to simply flag inappropriate material or set new filters. As a father of two, it makes me angry when a large company like Google doesn’t take responsibility for its kids’ products. Parents are being sold on an app built for kids 5 and under that is supposed to keep them safe from adult content. Parents like myself are joining forces to hold Google accountable.\n\nTell Google to remove the YouTube Kids app until it can live up to its marketing.\n\nThe solution is simple: only allow content pre-approved for ages 5 and under to appear on the app, and don’t allow ads clearly meant for adults. Unless it can live up to expectations, the app should be removed.\n\nParents are not the only ones outraged. The media has blasted Google’s app, calling it “the most anti-family idea ever to come out of Silicon Valley,\" and reporting that it “ignores basic protections for children.”\n\nWith your support, we can get Google to remove YouTube Kids until the proper protections are in place.\n\nThese are examples of videos encountered on YouTube Kids:\n\nA graphic lecture discussing hardcore pornography by Cindy Gallop:\n\nhttps://www.youtube.com/watch?v=EgtcEq7jpAk\n\nHow to make chlorine gas with household products (chemical weapon used in Syria):\n\nhttps://www.youtube.com/watch?v=DF2CXHvh8uI\n\nHow to tie a noose:\n\nhttps://www.youtube.com/watch?v=TpAA2itjI34\n\nHow to throw knives:\n\nhttps://www.youtube.com/watch?v=NGgzn1haQ-E\n\nA guy tasting battery acid:\n\nhttps://www.youtube.com/watch?v=gif-OWNjJSw\n\nHow to use a chainsaw:\n\nhttps://www.youtube.com/watch?v=Kk28thdgCEU\n\nA “Sesame Street” episode dubbed with long strings of expletives:\n\nhttps://www.youtube.com/watch?v=kVkqzE-iiEY\n\nReferences to pedophilia in a homemade video reviewing a “My Little Pony” episode:\n\nhttps://www.youtube.com/watch?v=7K9uH4d-HnU\n\nA DIY video on conducting illegal piracy, featuring pictures of marijuana leaves:\n\nhttps://www.youtube.com/watch?v=dZDF5uqORA0", + "report_number": 10, + "source_domain": "change.org", + "submitters": ["Roman Yampolskiy"], + "tags": [], + "text": "Videos filled with profanity, sexually explicit material, alcohol, smoking, and drug references - this is what parents are finding on Google’s YouTube Kids app. That’s right - its kids app. Now, parents across the country are calling on Google to remove the app until it can guarantee the total elimination of this inappropriate content.\n\nWhen my neighbors told me about the horrible adult content popping up on the Youtube Kids app, I thought there must be a mistake. Why would Google market an app as “a family-friendly place to explore” and not have proper safeguards in place? Unfortunately, it turned out to be true. And I’ve since learned of the numerous complaints filed to the Federal Trade Commission about this very problem.\n\nEven worse, Google’s response has been laughable. They tell parents to simply flag inappropriate material or set new filters. As a father of two, it makes me angry when a large company like Google doesn’t take responsibility for its kids’ products. Parents are being sold on an app built for kids 5 and under that is supposed to keep them safe from adult content. Parents like myself are joining forces to hold Google accountable.\n\nTell Google to remove the YouTube Kids app until it can live up to its marketing.\n\nThe solution is simple: only allow content pre-approved for ages 5 and under to appear on the app, and don’t allow ads clearly meant for adults. Unless it can live up to expectations, the app should be removed.\n\nParents are not the only ones outraged. The media has blasted Google’s app, calling it “the most anti-family idea ever to come out of Silicon Valley,\" and reporting that it “ignores basic protections for children.”\n\nWith your support, we can get Google to remove YouTube Kids until the proper protections are in place.\n\nThese are examples of videos encountered on YouTube Kids:\n\nA graphic lecture discussing hardcore pornography by Cindy Gallop:\n\nhttps://www.youtube.com/watch?v=EgtcEq7jpAk\n\nHow to make chlorine gas with household products (chemical weapon used in Syria):\n\nhttps://www.youtube.com/watch?v=DF2CXHvh8uI\n\nHow to tie a noose:\n\nhttps://www.youtube.com/watch?v=TpAA2itjI34\n\nHow to throw knives:\n\nhttps://www.youtube.com/watch?v=NGgzn1haQ-E\n\nA guy tasting battery acid:\n\nhttps://www.youtube.com/watch?v=gif-OWNjJSw\n\nHow to use a chainsaw:\n\nhttps://www.youtube.com/watch?v=Kk28thdgCEU\n\nA “Sesame Street” episode dubbed with long strings of expletives:\n\nhttps://www.youtube.com/watch?v=kVkqzE-iiEY\n\nReferences to pedophilia in a homemade video reviewing a “My Little Pony” episode:\n\nhttps://www.youtube.com/watch?v=7K9uH4d-HnU\n\nA DIY video on conducting illegal piracy, featuring pictures of marijuana leaves:\n\nhttps://www.youtube.com/watch?v=dZDF5uqORA0", + "title": "Remove YouTube Kids app until it eliminates its inappropriate content", + "description": "Description Remove YouTube Kids app until it eliminates its inappropriate content", + "url": "https://www.change.org/p/remove-youtube-kids-app-until-it-eliminates-its-inappropriate-content", + "user": { + "userId": "63320ce63ec803072c9f529c" + } + } + } +} diff --git a/site/gatsby-site/playwright/fixtures/reports/reportWithTranslations.json b/site/gatsby-site/playwright/fixtures/reports/reportWithTranslations.json new file mode 100644 index 0000000000..9cdcfb4a55 --- /dev/null +++ b/site/gatsby-site/playwright/fixtures/reports/reportWithTranslations.json @@ -0,0 +1,44 @@ +{ + "data": { + "report": { + "authors": ["Marco Acevedo"], + "date_downloaded": "2019-04-13", + "date_published": "2015-07-11", + "flag": null, + "image_url": "https://assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975", + "report_number": 10, + "submitters": ["Roman Yampolskiy"], + "tags": ["Test Tag"], + "text": "## Video still of a reproduced version of Minnie Mouse\n\nWhich appeared on the now-suspended Simple Fun channel Simple Fun.", + "plain_text": "Video still of a reproduced version of Minnie Mouse\n\nWhich appeared on the now-suspended Simple Fun channel Simple Fun.", + "title": "Remove YouTube Kids app until it eliminates its inappropriate content", + "description": "Description YouTube Kids app until it eliminates its inappropriate content", + "url": "https://www.change.org/p/remove-youtube-kids-app-until-it-eliminates-its-inappropriate-content", + "editor_notes": "", + "language": "en", + "translations_es": { + "__typename": "ReportTranslation", + "text": "Este es un texto de prueba que tiene un largo mayor a ochenta caracteres (en español)", + "title": "Este es el Título en español" + }, + "translations_en": { + "__typename": "ReportTranslation", + "text": "", + "title": "" + }, + "translations_fr": { + "__typename": "ReportTranslation", + "text": "Il s'agit d'un texte de test de plus de quatre-vingts caractères - lorem ipsum (en français)", + "title": "C'est le Titre en français" + }, + "translations_ja": { + "__typename": "ReportTranslation", + "text": "解サオライ協立なーづ民手ぶみドに即記朝ぐ奥置ぱで地更トるあて栄厚ぜづを祭屋ん来派どてゃ読速ヘ誌約カタシネ原39業理る。外ヒヱフ社第むせゆ由更混ソエ夕野しりすよ顔飛リの兆基う公言や置17謝后嘘5供フキヌア星集ヘラ辞勘壇崇さびわ。(日本語で)", + "title": "これは日本語でのタイトルです" + }, + "date_modified": "2023-01-01", + "epoch_date_modified": 1672531200, + "is_incident_report": true + } + } +} diff --git a/site/gatsby-site/playwright/fixtures/reports/updateOneReport.json b/site/gatsby-site/playwright/fixtures/reports/updateOneReport.json new file mode 100644 index 0000000000..f2d3d2328e --- /dev/null +++ b/site/gatsby-site/playwright/fixtures/reports/updateOneReport.json @@ -0,0 +1,26 @@ +{ + "data": { + "updateOneReport": { + "__typename": "Report", + "authors": ["Marco Acevedo"], + "date_downloaded": "2019-04-13", + "date_modified": "2022-08-29", + "date_published": "2015-07-11", + "editor_notes": "", + "epoch_date_downloaded": 1555113600, + "epoch_date_modified": 1661731200, + "epoch_date_published": 1436572800, + "flag": null, + "image_url": "https://assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975", + "language": "en", + "plain_text": "Videos filled with profanity, sexually explicit material, alcohol, smoking, and drug references - this is what parents are finding on Google’s YouTube Kids app. That’s right - its kids app. Now, parents across the country are calling on Google to remove the app until it can guarantee the total elimination of this inappropriate content.\n\nWhen my neighbors told me about the horrible adult content popping up on the Youtube Kids app, I thought there must be a mistake. Why would Google market an app as “a family-friendly place to explore” and not have proper safeguards in place? Unfortunately, it turned out to be true. And I’ve since learned of the numerous complaints filed to the Federal Trade Commission about this very problem.\n\nEven worse, Google’s response has been laughable. They tell parents to simply flag inappropriate material or set new filters. As a father of two, it makes me angry when a large company like Google doesn’t take responsibility for its kids’ products. Parents are being sold on an app built for kids 5 and under that is supposed to keep them safe from adult content. Parents like myself are joining forces to hold Google accountable.\n\nTell Google to remove the YouTube Kids app until it can live up to its marketing.\n\nThe solution is simple: only allow content pre-approved for ages 5 and under to appear on the app, and don’t allow ads clearly meant for adults. Unless it can live up to expectations, the app should be removed.\n\nParents are not the only ones outraged. The media has blasted Google’s app, calling it “the most anti-family idea ever to come out of Silicon Valley,\" and reporting that it “ignores basic protections for children.”\n\nWith your support, we can get Google to remove YouTube Kids until the proper protections are in place.\n\nThese are examples of videos encountered on YouTube Kids:\n\nA graphic lecture discussing hardcore pornography by Cindy Gallop:\n\nhttps://www.youtube.com/watch?v=EgtcEq7jpAk\n\nHow to make chlorine gas with household products (chemical weapon used in Syria):\n\nhttps://www.youtube.com/watch?v=DF2CXHvh8uI\n\nHow to tie a noose:\n\nhttps://www.youtube.com/watch?v=TpAA2itjI34\n\nHow to throw knives:\n\nhttps://www.youtube.com/watch?v=NGgzn1haQ-E\n\nA guy tasting battery acid:\n\nhttps://www.youtube.com/watch?v=gif-OWNjJSw\n\nHow to use a chainsaw:\n\nhttps://www.youtube.com/watch?v=Kk28thdgCEU\n\nA “Sesame Street” episode dubbed with long strings of expletives:\n\nhttps://www.youtube.com/watch?v=kVkqzE-iiEY\n\nReferences to pedophilia in a homemade video reviewing a “My Little Pony” episode:\n\nhttps://www.youtube.com/watch?v=7K9uH4d-HnU\n\nA DIY video on conducting illegal piracy, featuring pictures of marijuana leaves:\n\nhttps://www.youtube.com/watch?v=dZDF5uqORA0\n", + "report_number": 10, + "submitters": ["Roman Yampolskiy"], + "tags": [], + "text": "Videos filled with profanity, sexually explicit material, alcohol, smoking, and drug references - this is what parents are finding on Google’s YouTube Kids app. That’s right - its kids app. Now, parents across the country are calling on Google to remove the app until it can guarantee the total elimination of this inappropriate content.\n\nWhen my neighbors told me about the horrible adult content popping up on the Youtube Kids app, I thought there must be a mistake. Why would Google market an app as “a family-friendly place to explore” and not have proper safeguards in place? Unfortunately, it turned out to be true. And I’ve since learned of the numerous complaints filed to the Federal Trade Commission about this very problem.\n\nEven worse, Google’s response has been laughable. They tell parents to simply flag inappropriate material or set new filters. As a father of two, it makes me angry when a large company like Google doesn’t take responsibility for its kids’ products. Parents are being sold on an app built for kids 5 and under that is supposed to keep them safe from adult content. Parents like myself are joining forces to hold Google accountable.\n\nTell Google to remove the YouTube Kids app until it can live up to its marketing.\n\nThe solution is simple: only allow content pre-approved for ages 5 and under to appear on the app, and don’t allow ads clearly meant for adults. Unless it can live up to expectations, the app should be removed.\n\nParents are not the only ones outraged. The media has blasted Google’s app, calling it “the most anti-family idea ever to come out of Silicon Valley,\" and reporting that it “ignores basic protections for children.”\n\nWith your support, we can get Google to remove YouTube Kids until the proper protections are in place.\n\nThese are examples of videos encountered on YouTube Kids:\n\nA graphic lecture discussing hardcore pornography by Cindy Gallop:\n\nhttps://www.youtube.com/watch?v=EgtcEq7jpAk\n\nHow to make chlorine gas with household products (chemical weapon used in Syria):\n\nhttps://www.youtube.com/watch?v=DF2CXHvh8uI\n\nHow to tie a noose:\n\nhttps://www.youtube.com/watch?v=TpAA2itjI34\n\nHow to throw knives:\n\nhttps://www.youtube.com/watch?v=NGgzn1haQ-E\n\nA guy tasting battery acid:\n\nhttps://www.youtube.com/watch?v=gif-OWNjJSw\n\nHow to use a chainsaw:\n\nhttps://www.youtube.com/watch?v=Kk28thdgCEU\n\nA “Sesame Street” episode dubbed with long strings of expletives:\n\nhttps://www.youtube.com/watch?v=kVkqzE-iiEY\n\nReferences to pedophilia in a homemade video reviewing a “My Little Pony” episode:\n\nhttps://www.youtube.com/watch?v=7K9uH4d-HnU\n\nA DIY video on conducting illegal piracy, featuring pictures of marijuana leaves:\n\nhttps://www.youtube.com/watch?v=dZDF5uqORA0", + "title": "Remove YouTube Kids app until it eliminates its inappropriate content", + "description": "Description Remove YouTube Kids app until it eliminates its inappropriate content", + "url": "https://www.change.org/p/remove-youtube-kids-app-until-it-eliminates-its-inappropriate-content" + } + } +} diff --git a/site/gatsby-site/playwright/fixtures/reports/updateOneReportTranslation.json b/site/gatsby-site/playwright/fixtures/reports/updateOneReportTranslation.json new file mode 100644 index 0000000000..37906edb16 --- /dev/null +++ b/site/gatsby-site/playwright/fixtures/reports/updateOneReportTranslation.json @@ -0,0 +1,10 @@ +{ + "data": { + "updateOneReportTranslation": { + "__typename": "Report", + "report_number": 10, + "text": "Videos filled with profanity, sexually explicit material, alcohol, smoking, and drug references - this is what parents are finding on Google’s YouTube Kids app. That’s right - its kids app. Now, parents across the country are calling on Google to remove the app until it can guarantee the total elimination of this inappropriate content.\n\nWhen my neighbors told me about the horrible adult content popping up on the Youtube Kids app, I thought there must be a mistake. Why would Google market an app as “a family-friendly place to explore” and not have proper safeguards in place? Unfortunately, it turned out to be true. And I’ve since learned of the numerous complaints filed to the Federal Trade Commission about this very problem.\n\nEven worse, Google’s response has been laughable. They tell parents to simply flag inappropriate material or set new filters. As a father of two, it makes me angry when a large company like Google doesn’t take responsibility for its kids’ products. Parents are being sold on an app built for kids 5 and under that is supposed to keep them safe from adult content. Parents like myself are joining forces to hold Google accountable.\n\nTell Google to remove the YouTube Kids app until it can live up to its marketing.\n\nThe solution is simple: only allow content pre-approved for ages 5 and under to appear on the app, and don’t allow ads clearly meant for adults. Unless it can live up to expectations, the app should be removed.\n\nParents are not the only ones outraged. The media has blasted Google’s app, calling it “the most anti-family idea ever to come out of Silicon Valley,\" and reporting that it “ignores basic protections for children.”\n\nWith your support, we can get Google to remove YouTube Kids until the proper protections are in place.\n\nThese are examples of videos encountered on YouTube Kids:\n\nA graphic lecture discussing hardcore pornography by Cindy Gallop:\n\nhttps://www.youtube.com/watch?v=EgtcEq7jpAk\n\nHow to make chlorine gas with household products (chemical weapon used in Syria):\n\nhttps://www.youtube.com/watch?v=DF2CXHvh8uI\n\nHow to tie a noose:\n\nhttps://www.youtube.com/watch?v=TpAA2itjI34\n\nHow to throw knives:\n\nhttps://www.youtube.com/watch?v=NGgzn1haQ-E\n\nA guy tasting battery acid:\n\nhttps://www.youtube.com/watch?v=gif-OWNjJSw\n\nHow to use a chainsaw:\n\nhttps://www.youtube.com/watch?v=Kk28thdgCEU\n\nA “Sesame Street” episode dubbed with long strings of expletives:\n\nhttps://www.youtube.com/watch?v=kVkqzE-iiEY\n\nReferences to pedophilia in a homemade video reviewing a “My Little Pony” episode:\n\nhttps://www.youtube.com/watch?v=7K9uH4d-HnU\n\nA DIY video on conducting illegal piracy, featuring pictures of marijuana leaves:\n\nhttps://www.youtube.com/watch?v=dZDF5uqORA0", + "title": "Remove YouTube Kids app until it eliminates its inappropriate content" + } + } +} \ No newline at end of file diff --git a/site/gatsby-site/playwright/utils.ts b/site/gatsby-site/playwright/utils.ts index e1708ed652..37e71991a6 100644 --- a/site/gatsby-site/playwright/utils.ts +++ b/site/gatsby-site/playwright/utils.ts @@ -141,3 +141,26 @@ export async function login(page: Page, email: string, password: string, options } } +export async function setEditorText(page: Page, value: string, selector: string = '.CodeMirror') { + await page.locator(selector).first().click(); + await page.evaluate( + ({ selector, value }) => { + const editor = document.querySelector(selector) as HTMLElement & { CodeMirror?: any }; + if (editor?.CodeMirror) { + editor.CodeMirror.setValue(value); + } + }, + { selector, value } + ); +} + +export async function getEditorText(page: Page, selector: string = '.CodeMirror'): Promise { + return await page.evaluate( + (selector) => { + const editor = document.querySelector(selector) as HTMLElement & { CodeMirror?: any }; + return editor?.CodeMirror ? editor.CodeMirror.getValue() : ''; + }, + selector + ); +} + From bb220a89685f00929be06937aa75cd8bc9eb5353 Mon Sep 17 00:00:00 2001 From: Clara Youdale Date: Wed, 12 Jun 2024 14:47:56 -0300 Subject: [PATCH 3/6] Add "Should convert an incident report to an issue" and "Should display the report image" tests --- .../playwright/e2e/citeEdit.spec.ts | 470 +++++++++++++----- 1 file changed, 338 insertions(+), 132 deletions(-) diff --git a/site/gatsby-site/playwright/e2e/citeEdit.spec.ts b/site/gatsby-site/playwright/e2e/citeEdit.spec.ts index f16330d6d5..1023f84903 100644 --- a/site/gatsby-site/playwright/e2e/citeEdit.spec.ts +++ b/site/gatsby-site/playwright/e2e/citeEdit.spec.ts @@ -432,7 +432,7 @@ test.describe('Edit report', () => { maybeIt('Should delete incident report', async ({ page }) => { await login(page, config.E2E_ADMIN_USERNAME, config.E2E_ADMIN_PASSWORD); - + await conditionalIntercept( page, '**/graphql', @@ -440,7 +440,7 @@ test.describe('Edit report', () => { issueWithTranslations, 'FindReportWithTranslations' ); - + await conditionalIntercept( page, '**/graphql', @@ -448,7 +448,7 @@ test.describe('Edit report', () => { { data: { incidents: [] } }, 'FindIncidents' ); - + await conditionalIntercept( page, '**/graphql', @@ -462,15 +462,15 @@ test.describe('Edit report', () => { }, 'FindIncidentsTitles' ); - + await page.goto(url); - + await Promise.all([ waitForRequest('FindIncidents'), waitForRequest('FindIncidentsTitles'), waitForRequest('FindReportWithTranslations') ]); - + await conditionalIntercept( page, '**/graphql', @@ -478,7 +478,7 @@ test.describe('Edit report', () => { { data: { deleteOneReport: { __typename: 'Report', report_number: 10 } } }, 'DeleteReport' ); - + await conditionalIntercept( page, '**/graphql', @@ -486,25 +486,25 @@ test.describe('Edit report', () => { { data: { linkReportsToIncidents: [] } }, 'LinkReportsToIncidents' ); - + // Set up the dialog event listener before triggering the click action page.once('dialog', async dialog => { await dialog.accept(); - + const deleteRequest = await waitForRequest('DeleteReport'); expect(deleteRequest.postDataJSON().variables.query).toEqual({ report_number: 10 }); - + const linkReportsToIncidentsRequest = await waitForRequest('LinkReportsToIncidents'); expect(linkReportsToIncidentsRequest.postDataJSON().variables.input).toEqual({ incident_ids: [], report_numbers: [10] }); - + await expect(page.locator('[data-cy="toast"]:has-text("Incident report 10 deleted successfully")')).toBeVisible(); }); - + await page.locator('button:has-text("Delete this report")').click(); - + await page.waitForTimeout(2000); // Needed to wait for the dialog to be accepted }); @@ -512,181 +512,204 @@ test.describe('Edit report', () => { await login(page, config.E2E_ADMIN_USERNAME, config.E2E_ADMIN_PASSWORD); await conditionalIntercept( - page, - '**/graphql', - (req) => req.postDataJSON().operationName == 'FindReport', - report10, - 'FindReport' + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindReport', + report10, + 'FindReport' ); await conditionalIntercept( - page, - '**/graphql', - (req) => req.postDataJSON().operationName == 'ProbablyRelatedReports', - { data: { reports: [] } }, - 'ProbablyRelatedReports' + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'ProbablyRelatedReports', + { data: { reports: [] } }, + 'ProbablyRelatedReports' ); await conditionalIntercept( - page, - '**/graphql', - (req) => req.postDataJSON().operationName == 'ProbablyRelatedIncidents', - { data: { incidents: [] } }, - 'ProbablyRelatedIncidents' + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'ProbablyRelatedIncidents', + { data: { incidents: [] } }, + 'ProbablyRelatedIncidents' ); await conditionalIntercept( - page, - '**/graphql', - (req) => req.postDataJSON().operationName == 'FindReportWithTranslations', - reportWithTranslations, - 'FindReportWithTranslations' + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindReportWithTranslations', + reportWithTranslations, + 'FindReportWithTranslations' ); await conditionalIntercept( - page, - '**/graphql', - (req) => req.postDataJSON().operationName == 'FindIncidents', - { - data: { - incidents: [ - { - __typename: 'Incident', - incident_id: 1, - title: 'Incident 1', - }, - ], + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindIncidents', + { + data: { + incidents: [ + { + __typename: 'Incident', + incident_id: 1, + title: 'Incident 1', }, + ], }, - 'FindIncidents' + }, + 'FindIncidents' ); await conditionalIntercept( - page, - '**/graphql', - (req) => req.postDataJSON().operationName == 'FindIncidentsTitles', - { - data: { - incidents: [ - { - _typename: 'Incident', - incident_id: 1, - title: 'Incident 1', - }, - { - _typename: 'Incident', - incident_id: 2, - title: 'Incident 2', - }, - ], + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindIncidentsTitles', + { + data: { + incidents: [ + { + _typename: 'Incident', + incident_id: 1, + title: 'Incident 1', + }, + { + _typename: 'Incident', + incident_id: 2, + title: 'Incident 2', }, + ], }, - 'FindIncidentsTitles' + }, + 'FindIncidentsTitles' ); await conditionalIntercept( - page, - '**/graphql', - (req) => req.postDataJSON().operationName == 'logReportHistory', - { - data: { - logReportHistory: { - report_number: 10, - }, - }, + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'logReportHistory', + { + data: { + logReportHistory: { + report_number: 10, + }, }, - 'logReportHistory' + }, + 'logReportHistory' ); await page.goto(`/cite/edit?report_number=23`); await Promise.all([ - waitForRequest('FindReportWithTranslations'), - waitForRequest('FindIncidents'), - waitForRequest('FindIncidentsTitles') + waitForRequest('FindReportWithTranslations'), + waitForRequest('FindIncidents'), + waitForRequest('FindIncidentsTitles') ]); await expect(page.locator('form[data-cy="report"]')).toBeVisible(); - await page.locator('div:has-text("Incident 1")'); - - // .locator('xpath=following-sibling::*[1]').click(); + const incidentDiv = await page.locator('div:has-text("Incident 1")'); + + await incidentDiv.locator('xpath=following-sibling::button').click(); await page.locator('[name="incident_ids"]').fill('2'); await page.locator('[id="incident_ids-item-0"]').click(); await conditionalIntercept( - page, - '**/graphql', - (req) => req.postDataJSON().operationName == 'UpdateReportTranslation', - updateOneReportTranslation, - 'updateOneReportTranslation' + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'UpdateReportTranslation', + updateOneReportTranslation, + 'updateOneReportTranslationSpanish' ); - await conditionalIntercept( - page, - '**/graphql', - (req) => req.postDataJSON().operationName == 'UpdateReport', - updateOneReport, - 'UpdateReport' + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'UpdateReportTranslation' && req.postDataJSON().variables.input.language === 'fr', + updateOneReportTranslation, + 'updateOneReportTranslationFrench' + ); + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'UpdateReportTranslation' && req.postDataJSON().variables.input.language === 'ja', + updateOneReportTranslation, + 'updateOneReportTranslationJapanese' ); await conditionalIntercept( - page, - '**/graphql', - (req) => req.postDataJSON().operationName == 'LinkReportsToIncidents', - { data: { linkReportsToIncidents: [] } }, - 'LinkReportsToIncidents' + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'UpdateReport', + updateOneReport, + 'UpdateReport' ); - const now = new Date(); - await page.context().addInitScript({ content: `Date = function() { return new Date(${now.getTime()}); }` }); + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'LinkReportsToIncidents', + { data: { linkReportsToIncidents: [] } }, + 'LinkReportsToIncidents' + ); await page.locator('button:has-text("Submit")').click(); + let now = new Date(); + await page.addInitScript(`{ + Date.now = () => ${now.getTime()}; + }`); + const expectedReport = { - authors: ['Marco Acevedo'], - cloudinary_id: 'reports/assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975', - date_downloaded: new Date('2019-04-13').toISOString(), - date_modified: format(now, 'yyyy-MM-dd'), - date_published: new Date('2015-07-11').toISOString(), - editor_notes: '', - epoch_date_modified: getUnixTime(now), - epoch_date_published: 1436572800, - flag: null, - image_url: 'https://assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975', - language: 'en', - plain_text: 'Video still of a reproduced version of Minnie Mouse\n\nWhich appeared on the now-suspended Simple Fun channel Simple Fun.\n', - report_number: 10, - source_domain: 'change.org', - submitters: ['Roman Yampolskiy'], - tags: ['Test Tag'], - text: '## Video still of a reproduced version of Minnie Mouse\n\nWhich appeared on the now-suspended Simple Fun channel Simple Fun.', - title: 'Remove YouTube Kids app until it eliminates its inappropriate content', - url: 'https://www.change.org/p/remove-youtube-kids-app-until-it-eliminates-its-inappropriate-content', + authors: ['Marco Acevedo'], + cloudinary_id: 'reports/assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975', + date_downloaded: new Date('2019-04-13').toISOString(), + date_modified: format(now, 'yyyy-MM-dd'), + date_published: new Date('2015-07-11').toISOString(), + editor_notes: '', + epoch_date_published: 1436572800, + flag: null, + image_url: 'https://assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975', + language: 'en', + plain_text: 'Video still of a reproduced version of Minnie Mouse\n\nWhich appeared on the now-suspended Simple Fun channel Simple Fun.\n', + report_number: 10, + source_domain: 'change.org', + submitters: ['Roman Yampolskiy'], + tags: ['Test Tag'], + text: '## Video still of a reproduced version of Minnie Mouse\n\nWhich appeared on the now-suspended Simple Fun channel Simple Fun.', + title: 'Remove YouTube Kids app until it eliminates its inappropriate content', + url: 'https://www.change.org/p/remove-youtube-kids-app-until-it-eliminates-its-inappropriate-content', + epoch_date_modified: null, }; + now = new Date(); const updateReportRequest = await waitForRequest('UpdateReport'); const variables = updateReportRequest.postDataJSON().variables; expect(variables.query.report_number).toBe(23); + expect({ - ...variables.set, - date_modified: format(new Date(variables.set.date_modified), 'yyyy-MM-dd'), - }).toEqual(expectedReport); + ...variables.set, + date_modified: format(new Date(variables.set.date_modified), 'yyyy-MM-dd'), + }).toEqual({ + ...expectedReport, + epoch_date_modified: getUnixTime(now), + }); + const expectedNow = new Date(); const logReportHistoryRequest = await waitForRequest('logReportHistory'); const input = logReportHistoryRequest.postDataJSON().variables.input; const expectedResult = { - ...report10.data.report, - ...expectedReport, - modifiedBy: user.userId, - user: report10.data.report.user.userId, - date_modified: input.date_modified, + ...report10.data.report, + ...expectedReport, + modifiedBy: user.userId, + user: report10.data.report.user.userId, + date_modified: input.date_modified, + epoch_date_modified: getUnixTime(now), }; expect(input).toEqual(expectedResult); - const updateOneReportTranslationRequest1 = await waitForRequest('updateOneReportTranslation'); + const updateOneReportTranslationRequest1 = await waitForRequest('updateOneReportTranslationSpanish'); let translationVariables = updateOneReportTranslationRequest1.postDataJSON().variables; expect(translationVariables.input.title).toBe('Este es el Título en español'); expect(translationVariables.input.text).toBe('Este es un texto de prueba que tiene un largo mayor a ochenta caracteres (en español)'); @@ -694,7 +717,7 @@ test.describe('Edit report', () => { expect(translationVariables.input.report_number).toBe(23); expect(translationVariables.input.plain_text).toBe('Este es un texto de prueba que tiene un largo mayor a ochenta caracteres (en español)\n'); - const updateOneReportTranslationRequest2 = await waitForRequest('updateOneReportTranslation'); + const updateOneReportTranslationRequest2 = await waitForRequest('updateOneReportTranslationFrench'); translationVariables = updateOneReportTranslationRequest2.postDataJSON().variables; expect(translationVariables.input.title).toBe(`C'est le Titre en français`); expect(translationVariables.input.text).toBe(`Il s'agit d'un texte de test de plus de quatre-vingts caractères - lorem ipsum (en français)`); @@ -702,7 +725,7 @@ test.describe('Edit report', () => { expect(translationVariables.input.report_number).toBe(23); expect(translationVariables.input.plain_text).toBe(`Il s'agit d'un texte de test de plus de quatre-vingts caractères - lorem ipsum (en français)\n`); - const updateOneReportTranslationRequest3 = await waitForRequest('updateOneReportTranslation'); + const updateOneReportTranslationRequest3 = await waitForRequest('updateOneReportTranslationJapanese'); translationVariables = updateOneReportTranslationRequest3.postDataJSON().variables; expect(translationVariables.input.title).toBe('これは日本語でのタイトルです'); expect(translationVariables.input.text).toBe('解サオライ協立なーづ民手ぶみドに即記朝ぐ奥置ぱで地更トるあて栄厚ぜづを祭屋ん来派どてゃ読速ヘ誌約カタシネ原39業理る。外ヒヱフ社第むせゆ由更混ソエ夕野しりすよ顔飛リの兆基う公言や置17謝后嘘5供フキヌア星集ヘラ辞勘壇崇さびわ。(日本語で)'); @@ -712,12 +735,195 @@ test.describe('Edit report', () => { const linkReportsToIncidentsRequest = await waitForRequest('LinkReportsToIncidents'); expect(linkReportsToIncidentsRequest.postDataJSON().variables.input).toEqual({ - incident_ids: [2], - report_numbers: [23], + incident_ids: [2], + report_numbers: [23], }); await expect(page.locator('[data-cy="toast"]')).toContainText('Incident report 23 updated successfully'); -}); + }); + + maybeIt('Should convert an incident report to an issue', async ({ page }) => { + await login(page, config.E2E_ADMIN_USERNAME, config.E2E_ADMIN_PASSWORD); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindReport', + report10, + 'FindReport' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'ProbablyRelatedReports', + { data: { reports: [] } }, + 'ProbablyRelatedReports' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'ProbablyRelatedIncidents', + { data: { incidents: [] } }, + 'ProbablyRelatedIncidents' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindReportWithTranslations', + reportWithTranslations, + 'FindReportWithTranslations' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindIncidents', + { + data: { + incidents: [ + { + _typename: 'Incident', + incident_id: 1, + title: 'Incident 1', + }, + ], + }, + }, + 'FindIncidents' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'FindIncidentsTitles', + { + data: { + incidents: [ + { _typename: 'Incident', incident_id: 1, title: 'Incident 1' }, + { _typename: 'Incident', incident_id: 2, title: 'Incident 2' }, + ], + }, + }, + 'FindIncidentsTitles' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'logReportHistory', + { data: { logReportHistory: { report_number: 10 } } }, + 'logReportHistory' + ); + + await page.goto(`/cite/edit?report_number=23`); + + await page.locator('form[data-cy="report"]').waitFor(); + + const incidentDiv = await page.locator('div:has-text("Incident 1")'); + + await incidentDiv.locator('xpath=following-sibling::button').click(); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'UpdateReport', + updateOneReport, + 'UpdateReport' + ); - + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'UpdateReportTranslation', + updateOneReportTranslation, + 'UpdateReportTranslation' + ); + + await conditionalIntercept( + page, + '**/graphql', + (req) => req.postDataJSON().operationName == 'LinkReportsToIncidents', + { data: { linkReportsToIncidents: [] } }, + 'LinkReportsToIncidents' + ); + + await page.evaluate(() => window.confirm = () => true); + + const now = new Date(); + + await page.addInitScript(`{ + Date.now = () => ${now.getTime()}; + }`); + + await page.locator('button:has-text("Submit")').click(); + + const expectedReport = { + authors: ['Marco Acevedo'], + cloudinary_id: + 'reports/assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975', + date_downloaded: new Date('2019-04-13').toISOString(), + date_published: new Date('2015-07-11').toISOString(), + flag: null, + image_url: + 'https://assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975', + report_number: 10, + submitters: ['Roman Yampolskiy'], + tags: ['Test Tag'], + text: '## Video still of a reproduced version of Minnie Mouse\n\nWhich appeared on the now-suspended Simple Fun channel Simple Fun.', + plain_text: + 'Video still of a reproduced version of Minnie Mouse\n\nWhich appeared on the now-suspended Simple Fun channel Simple Fun.\n', + title: 'Remove YouTube Kids app until it eliminates its inappropriate content', + url: 'https://www.change.org/p/remove-youtube-kids-app-until-it-eliminates-its-inappropriate-content', + editor_notes: '', + language: 'en', + source_domain: 'change.org', + epoch_date_published: 1436572800, + date_modified: format(now, 'yyyy-MM-dd'), + epoch_date_modified: getUnixTime(now), + }; + + const updateReportRequest = await waitForRequest('UpdateReport'); + const variables = updateReportRequest.postDataJSON().variables; + expect(variables.query.report_number).toBe(23); + expect({ + ...variables.set, + date_modified: format(new Date(variables.set.date_modified), 'yyyy-MM-dd'), + }).toEqual(expectedReport); + + const logReportHistoryRequest = await waitForRequest('logReportHistory'); + const input = logReportHistoryRequest.postDataJSON().variables.input; + const expectedResult = { + ...report10.data.report, + ...expectedReport, + modifiedBy: user.userId, + user: report10.data.report.user.userId, + date_modified: input.date_modified, + }; + + expect(input).toEqual(expectedResult); + + await waitForRequest('UpdateReportTranslation'); + await waitForRequest('UpdateReportTranslation'); + + const linkReportsToIncidentsRequest = await waitForRequest('LinkReportsToIncidents'); + expect(linkReportsToIncidentsRequest.postDataJSON().variables.input).toEqual({ + incident_ids: [], + report_numbers: [23], + }); + + await page.locator('[data-cy="toast"]:has-text("Issue 23 updated successfully")', { timeout: 8000 }).waitFor(); + }); + + test('Should display the report image', async ({ page }) => { + await login(page, config.E2E_ADMIN_USERNAME, config.E2E_ADMIN_PASSWORD); + + await page.goto(url); + + await page.locator('[data-cy="image-preview-figure"] img').waitFor(); + const imgSrc = await page.locator('[data-cy="image-preview-figure"] img').getAttribute('src'); + expect(imgSrc).toBe('https://res.cloudinary.com/pai/image/upload/f_auto/q_auto/v1/reports/assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975'); + }); }); \ No newline at end of file From 7d1b36b83b4ae4054a55a898675d70279430393f Mon Sep 17 00:00:00 2001 From: Clara Youdale Date: Fri, 14 Jun 2024 16:01:50 -0300 Subject: [PATCH 4/6] Delete citeEdit.cy.js --- .../cypress/e2e/integration/citeEdit.cy.js | 1228 ----------------- 1 file changed, 1228 deletions(-) delete mode 100644 site/gatsby-site/cypress/e2e/integration/citeEdit.cy.js diff --git a/site/gatsby-site/cypress/e2e/integration/citeEdit.cy.js b/site/gatsby-site/cypress/e2e/integration/citeEdit.cy.js deleted file mode 100644 index dff0592ca8..0000000000 --- a/site/gatsby-site/cypress/e2e/integration/citeEdit.cy.js +++ /dev/null @@ -1,1228 +0,0 @@ -import { maybeIt } from '../../support/utils'; -import updateOneReport from '../../fixtures/reports/updateOneReport.json'; -import updateOneReportTranslation from '../../fixtures/reports/updateOneReportTranslation.json'; -import { format, getUnixTime } from 'date-fns'; -import reportWithTranslations from '../../fixtures/reports/reportWithTranslations.json'; -import issueWithTranslations from '../../fixtures/reports/issueWithTranslations.json'; -import report10 from '../../fixtures/reports/report.json'; -const { gql } = require('@apollo/client'); - -describe('Edit report', () => { - const url = '/cite/edit?report_number=10'; - - let user; - - before('before', () => { - cy.query({ - query: gql` - { - user(query: { first_name: "Test", last_name: "User" }) { - userId - first_name - last_name - } - } - `, - }).then(({ data: { user: userData } }) => { - user = userData; - }); - }); - - it('Successfully loads', () => { - cy.visit(url); - - cy.disableSmoothScroll(); - }); - - maybeIt('Should load and update report values', () => { - cy.login(Cypress.env('e2eUsername'), Cypress.env('e2ePassword')); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindReportWithTranslations', - 'FindReportWithTranslations', - reportWithTranslations - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindReport', - 'FindReport', - report10 - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindIncidents', - 'FindIncidents', - { - data: { - incidents: [ - { - _typename: 'Incident', - incident_id: 1, - title: 'Incident 1', - }, - ], - }, - } - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindIncidentsTitles', - 'FindIncidentsTitles', - { - data: { - incidents: [ - { - _typename: 'Incident', - incident_id: 1, - title: 'Incident 1', - }, - { - _typename: 'Incident', - incident_id: 2, - title: 'Incident 2', - }, - ], - }, - } - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'logReportHistory', - 'logReportHistory', - { - data: { - logReportHistory: { - report_number: 10, - }, - }, - } - ); - - cy.visit(url); - - cy.wait(['@FindReportWithTranslations', '@FindIncidents', '@FindReport']); - - [ - 'authors', - 'date_downloaded', - 'date_published', - 'image_url', - 'submitters', - 'title', - 'editor_notes', - ].forEach((key) => { - cy.get(`[name=${key}]`).should( - 'have.value', - reportWithTranslations.data.report[key].toString() - ); - }); - - cy.getEditorText().should('eq', reportWithTranslations.data.report.text); - - cy.contains('label', 'Incident IDs') - .next() - .contains('[data-cy="token"]', 'Incident 1') - .should('be.visible'); - - cy.get('.submit-report-tags [option="Test Tag"]').should('have.length', 1); - - cy.get('[data-cy="translation-es"] [type="text"]').should( - 'have.value', - reportWithTranslations.data.report.translations_es.title - ); - - cy.getEditorText('[data-cy="translation-es"] .CodeMirror').should( - 'eq', - reportWithTranslations.data.report.translations_es.text - ); - - const updates = { - authors: 'Test Author', - date_downloaded: '2022-01-01', - date_published: '2022-02-02', - image_url: 'https://test.com/test.jpg', - submitters: 'Test Submitter', - title: 'Test Title', - url: 'https://www.test.com/test', - editor_notes: 'Pro iustitia tantum', - }; - - Object.keys(updates).forEach((key) => { - cy.get(`[name=${key}]`).clear().type(updates[key]); - }); - - cy.get(`[name="quiet"]`).click(); - - cy.setEditorText( - '## This is text in English\n\nthat is longer that eighty characters, yes eighty characters!', - '[data-cy="text"] .CodeMirror' - ); - - cy.get('[id^=submit-report-tags]').type('New Tag'); - - cy.get('a[aria-label="New Tag"]').click(); - - cy.get('[data-cy="translation-es"] [type="text"]') - .clear() - .type('Este es un titulo en Espanol!'); - - cy.setEditorText( - '## Este es texto en espanol\n\nque es mas largo que ochenta caracters, si ochenta caracteres!', - '[data-cy="translation-es"] .CodeMirror' - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'UpdateReport', - 'updateReport', - updateOneReport - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'UpdateReportTranslation', - 'updateOneReportTranslation', - updateOneReportTranslation - ); - - const now = new Date(); - - cy.clock(now); - - cy.contains('button', 'Submit').click(); - - const expectedReport = { - authors: ['Test Author'], - cloudinary_id: 'reports/test.com/test.jpg', - date_downloaded: new Date('2022-01-01').toISOString(), - date_modified: format(now, 'yyyy-MM-dd'), - date_published: new Date('2022-02-02').toISOString(), - epoch_date_modified: getUnixTime(now), - epoch_date_published: 1643760000, - flag: null, - image_url: 'https://test.com/test.jpg', - report_number: 10, - submitters: ['Test Submitter'], - tags: ['Test Tag', 'New Tag'], - text: '## This is text in English\n\nthat is longer that eighty characters, yes eighty characters!', - plain_text: - 'This is text in English\n\nthat is longer that eighty characters, yes eighty characters!\n', - title: 'Test Title', - url: 'https://www.test.com/test', - source_domain: 'test.com', - editor_notes: 'Pro iustitia tantum', - language: 'en', - quiet: true, - }; - - cy.wait('@updateReport').then((xhr) => { - expect(xhr.request.body.variables.query.report_number).eq(expectedReport.report_number); - expect({ - ...xhr.request.body.variables.set, - date_modified: format(new Date(xhr.request.body.variables.set.date_modified), 'yyyy-MM-dd'), - }).to.deep.eq(expectedReport); - }); - - cy.wait('@logReportHistory') - .its('request.body.variables.input') - .then((input) => { - const expectedResult = { - ...report10.data.report, - ...expectedReport, - modifiedBy: user.userId, - user: report10.data.report.user.userId, - date_modified: input.date_modified, - }; - - expect(input).to.deep.eq(expectedResult); - }); - - cy.wait('@updateOneReportTranslation').then((xhr) => { - expect(xhr.request.body.variables.input.language).eq('es'); - expect(xhr.request.body.variables.input.report_number).eq(10); - expect(xhr.request.body.variables.input.text).eq( - '## Este es texto en espanol\n\nque es mas largo que ochenta caracters, si ochenta caracteres!' - ); - expect(xhr.request.body.variables.input.plain_text).eq( - 'Este es texto en espanol\n\nque es mas largo que ochenta caracters, si ochenta caracteres!\n' - ); - expect(xhr.request.body.variables.input.title).eq('Este es un titulo en Espanol!'); - }); - - cy.get('.tw-toast').contains('Incident report 10 updated successfully.').should('exist'); - }); - - maybeIt('Should load and update Issue values', () => { - cy.login(Cypress.env('e2eUsername'), Cypress.env('e2ePassword')); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindReportWithTranslations', - 'FindReportWithTranslations', - issueWithTranslations - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindReport', - 'FindReport', - report10 - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindIncidents', - 'FindIncidents', - { - data: { - incidents: [], - }, - } - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindIncidentsTitles', - 'FindIncidentsTitles', - { - data: { - incidents: [ - { - _typename: 'Incident', - incident_id: 1, - title: 'Incident 1', - }, - ], - }, - } - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'logReportHistory', - 'logReportHistory', - { - data: { - logReportHistory: { - report_number: 10, - }, - }, - } - ); - - cy.visit(url); - - cy.wait(['@FindReportWithTranslations', '@FindIncidents', '@FindReport']); - - [ - 'authors', - 'date_downloaded', - 'date_published', - 'image_url', - 'submitters', - 'title', - 'editor_notes', - ].forEach((key) => { - cy.get(`[name=${key}]`).should( - 'have.value', - reportWithTranslations.data.report[key].toString() - ); - }); - - cy.getEditorText().should('eq', reportWithTranslations.data.report.text); - - cy.get(`[name="incident_id"]`).should('not.exist'); - - cy.get('.submit-report-tags [option="Test Tag"]').should('have.length', 1); - - cy.get('[data-cy="translation-es"] [type="text"]').should( - 'have.value', - reportWithTranslations.data.report.translations_es.title - ); - - cy.getEditorText('[data-cy="translation-es"] .CodeMirror').should( - 'eq', - reportWithTranslations.data.report.translations_es.text - ); - - const updates = { - authors: 'Test Author', - date_downloaded: '2022-01-01', - date_published: '2022-02-02', - image_url: 'https://test.com/test.jpg', - submitters: 'Test Submitter', - title: 'Test Title', - url: 'https://www.test.com/test', - editor_notes: 'Pro iustitia tantum', - }; - - Object.keys(updates).forEach((key) => { - cy.get(`[name=${key}]`).clear().type(updates[key]); - }); - - cy.setEditorText( - '## This is text in English\n\nthat is longer that eighty characters, yes eighty characters!', - '[data-cy="text"] .CodeMirror' - ); - - cy.get('[id^=submit-report-tags]').type('New Tag'); - - cy.get('a[aria-label="New Tag"]').click(); - - cy.get('[data-cy="translation-es"] [type="text"]') - .clear() - .type('Este es un titulo en Espanol!'); - - cy.setEditorText( - '## Este es texto en espanol\n\nque es mas largo que ochenta caracters, si ochenta caracteres!', - '[data-cy="translation-es"] .CodeMirror' - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'UpdateReport', - 'updateReport', - updateOneReport - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'UpdateReportTranslation', - 'updateOneReportTranslation', - updateOneReportTranslation - ); - - const now = new Date(); - - cy.clock(now); - - cy.contains('button', 'Submit').click(); - - const expectedReport = { - authors: ['Test Author'], - cloudinary_id: 'reports/test.com/test.jpg', - date_downloaded: new Date('2022-01-01').toISOString(), - date_modified: format(now, 'yyyy-MM-dd'), - date_published: new Date('2022-02-02').toISOString(), - epoch_date_modified: getUnixTime(now), - epoch_date_published: 1643760000, - flag: null, - image_url: 'https://test.com/test.jpg', - report_number: 10, - submitters: ['Test Submitter'], - tags: ['Test Tag', 'New Tag'], - text: '## This is text in English\n\nthat is longer that eighty characters, yes eighty characters!', - plain_text: - 'This is text in English\n\nthat is longer that eighty characters, yes eighty characters!\n', - title: 'Test Title', - url: 'https://www.test.com/test', - source_domain: 'test.com', - editor_notes: 'Pro iustitia tantum', - language: 'en', - }; - - cy.wait('@updateReport').then((xhr) => { - expect(xhr.request.body.variables.query.report_number).eq(10); - expect({ - ...xhr.request.body.variables.set, - date_modified: format(new Date(xhr.request.body.variables.set.date_modified), 'yyyy-MM-dd'), - }).to.deep.eq(expectedReport); - }); - - cy.wait('@logReportHistory') - .its('request.body.variables.input') - .then((input) => { - const expectedResult = { - ...report10.data.report, - ...expectedReport, - modifiedBy: user.userId, - user: report10.data.report.user.userId, - date_modified: input.date_modified, - }; - - expect(input).to.deep.eq(expectedResult); - }); - - cy.wait('@updateOneReportTranslation').then((xhr) => { - expect(xhr.request.body.variables.input.language).eq('es'); - expect(xhr.request.body.variables.input.report_number).eq(10); - expect(xhr.request.body.variables.input.text).eq( - '## Este es texto en espanol\n\nque es mas largo que ochenta caracters, si ochenta caracteres!' - ); - expect(xhr.request.body.variables.input.plain_text).eq( - 'Este es texto en espanol\n\nque es mas largo que ochenta caracters, si ochenta caracteres!\n' - ); - expect(xhr.request.body.variables.input.title).eq('Este es un titulo en Espanol!'); - }); - - cy.contains('[data-cy="toast"]', 'Issue 10 updated successfully').should('exist'); - }); - - maybeIt('Should delete incident report', () => { - cy.login(Cypress.env('e2eUsername'), Cypress.env('e2ePassword')); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindReportWithTranslations', - 'FindReportWithTranslations', - issueWithTranslations - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindIncidents', - 'FindIncidents', - { - data: { - incidents: [], - }, - } - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindIncidentsTitles', - 'FindIncidentsTitles', - { - data: { - incidents: [ - { - _typename: 'Incident', - incident_id: 1, - title: 'Incident 1', - }, - ], - }, - } - ); - - cy.visit(url); - - cy.wait(['@FindIncidents', '@FindIncidentsTitles', '@FindReportWithTranslations']); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'DeleteOneReport', - 'delete', - { data: { deleteOneReport: { __typename: 'Report', report_number: 10 } } } - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'LinkReportsToIncidents', - 'LinkReportsToIncidents', - { - data: { - linkReportsToIncidents: [], - }, - } - ); - - cy.contains('button', 'Delete this report').click(); - - cy.wait('@delete').then((xhr) => { - expect(xhr.request.body.variables.query).to.deep.eq({ report_number: 10 }); - }); - - cy.wait('@LinkReportsToIncidents').then((xhr) => { - expect(xhr.request.body.variables.input).to.deep.eq({ - incident_ids: [], - report_numbers: [10], - }); - }); - - cy.contains('[data-cy="toast"]', 'Incident report 10 deleted successfully').should('exist'); - }); - - maybeIt('Should link a report to another incident', () => { - cy.login(Cypress.env('e2eUsername'), Cypress.env('e2ePassword')); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindReport', - 'FindReport', - report10 - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'ProbablyRelatedReports', - 'ProbablyRelatedReports', - { - data: { reports: [] }, - } - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'ProbablyRelatedIncidents', - 'ProbablyRelatedIncidents', - { - data: { incidents: [] }, - } - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindReportWithTranslations', - 'FindReportWithTranslations', - reportWithTranslations - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindIncidents', - 'FindIncidents', - { - data: { - incidents: [ - { - __typename: 'Incident', - incident_id: 1, - title: 'Incident 1', - }, - ], - }, - } - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindIncidentsTitles', - 'FindIncidentsTitles', - { - data: { - incidents: [ - { - _typename: 'Incident', - incident_id: 1, - title: 'Incident 1', - }, - { - _typename: 'Incident', - incident_id: 2, - title: 'Incident 2', - }, - ], - }, - } - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'logReportHistory', - 'logReportHistory', - { - data: { - logReportHistory: { - report_number: 10, - }, - }, - } - ); - - cy.visit(`/cite/edit?report_number=23`); - - cy.wait(['@FindReportWithTranslations', '@FindIncidents', '@FindIncidentsTitles']); - - cy.get('form[data-cy="report"]').should('be.visible'); - - cy.contains('div', 'Incident 1').next().click(); - - cy.get('[name="incident_ids"]').type('2'); - - cy.get('[id="incident_ids-item-0"]').click(); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'UpdateReportTranslation', - 'updateOneReportTranslation', - updateOneReportTranslation - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'UpdateReport', - 'UpdateReport', - updateOneReport - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'LinkReportsToIncidents', - 'LinkReportsToIncidents', - { - data: { - linkReportsToIncidents: [], - }, - } - ); - - const now = new Date(); - - cy.clock(now); - - cy.contains('button', 'Submit').click(); - - const expectedReport = { - authors: ['Marco Acevedo'], - cloudinary_id: - 'reports/assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975', - date_downloaded: new Date('2019-04-13').toISOString(), - date_modified: format(now, 'yyyy-MM-dd'), - date_published: new Date('2015-07-11').toISOString(), - editor_notes: '', - epoch_date_modified: getUnixTime(now), - epoch_date_published: 1436572800, - flag: null, - image_url: - 'https://assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975', - language: 'en', - plain_text: - 'Video still of a reproduced version of Minnie Mouse\n\nWhich appeared on the now-suspended Simple Fun channel Simple Fun.\n', - report_number: 10, - source_domain: 'change.org', - submitters: ['Roman Yampolskiy'], - tags: ['Test Tag'], - text: '## Video still of a reproduced version of Minnie Mouse\n\nWhich appeared on the now-suspended Simple Fun channel Simple Fun.', - title: 'Remove YouTube Kids app until it eliminates its inappropriate content', - url: 'https://www.change.org/p/remove-youtube-kids-app-until-it-eliminates-its-inappropriate-content', - }; - - cy.wait('@UpdateReport') - .its('request.body.variables') - .then((variables) => { - expect(variables.query.report_number).to.equal(23); - expect({ - ...variables.set, - date_modified: format(new Date(variables.set.date_modified), 'yyyy-MM-dd'), - }).deep.eq(expectedReport); - }); - - cy.wait('@logReportHistory') - .its('request.body.variables.input') - .then((input) => { - const expectedResult = { - ...report10.data.report, - ...expectedReport, - modifiedBy: user.userId, - user: report10.data.report.user.userId, - date_modified: input.date_modified, - }; - - expect(input).to.deep.eq(expectedResult); - }); - - cy.wait('@updateOneReportTranslation') - .its('request.body.variables') - .then((variables) => { - expect(variables.input.title).to.eq('Este es el Título en español'); - expect(variables.input.text).to.eq( - 'Este es un texto de prueba que tiene un largo mayor a ochenta caracteres (en español)' - ); - expect(variables.input.language).to.eq('es'); - expect(variables.input.report_number).to.eq(23); - expect(variables.input.plain_text).to.eq( - 'Este es un texto de prueba que tiene un largo mayor a ochenta caracteres (en español)\n' - ); - }); - - cy.wait('@updateOneReportTranslation') - .its('request.body.variables') - .then((variables) => { - expect(variables.input.title).to.eq(`C'est le Titre en français`); - expect(variables.input.text).to.eq( - `Il s'agit d'un texte de test de plus de quatre-vingts caractères - lorem ipsum (en français)` - ); - expect(variables.input.language).to.eq('fr'); - expect(variables.input.report_number).to.eq(23); - expect(variables.input.plain_text).to.eq( - `Il s'agit d'un texte de test de plus de quatre-vingts caractères - lorem ipsum (en français)\n` - ); - }); - - cy.wait('@updateOneReportTranslation') - .its('request.body.variables') - .then((variables) => { - expect(variables.input.title).to.eq('これは日本語でのタイトルです'); - expect(variables.input.text).to.eq( - '解サオライ協立なーづ民手ぶみドに即記朝ぐ奥置ぱで地更トるあて栄厚ぜづを祭屋ん来派どてゃ読速ヘ誌約カタシネ原39業理る。外ヒヱフ社第むせゆ由更混ソエ夕野しりすよ顔飛リの兆基う公言や置17謝后嘘5供フキヌア星集ヘラ辞勘壇崇さびわ。(日本語で)' - ); - expect(variables.input.language).to.eq('ja'); - expect(variables.input.report_number).to.eq(23); - expect(variables.input.plain_text).to.eq( - '解サオライ協立なーづ民手ぶみドに即記朝ぐ奥置ぱで地更トるあて栄厚ぜづを祭屋ん来派どてゃ読速ヘ誌約カタシネ原39業理る。外ヒヱフ社第むせゆ由更混ソエ夕野しりすよ顔飛リの兆基う公言や置17謝后嘘5供フキヌア星集ヘラ辞勘壇崇さびわ。(日本語で)\n' - ); - }); - - cy.wait('@LinkReportsToIncidents').then((xhr) => { - expect(xhr.request.body.variables.input).to.deep.eq({ - incident_ids: [2], - report_numbers: [23], - }); - }); - - cy.contains('[data-cy="toast"]', 'Incident report 23 updated successfully', { timeout: 8000 }); - }); - - maybeIt('Should display an error message if data is missing', () => { - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindReportWithTranslations', - 'findReportWithTranslations', - reportWithTranslations - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'ProbablyRelatedReports', - 'ProbablyRelatedReports', - { - data: { reports: [] }, - } - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'ProbablyRelatedIncidents', - 'ProbablyRelatedIncidents', - { - data: { incidents: [] }, - } - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindIncidents', - 'FindIncidents', - { data: { incidents: [] } } - ); - - cy.visit(`/cite/edit?report_number=23`); - - cy.wait('@findReportWithTranslations'); - - cy.get('form[data-cy="report"]').should('be.visible'); - - cy.get('[name="title"]').clear(); - - cy.contains('Please review report. Some data is missing.').should('exist'); - - cy.contains('button', 'Submit').should('be.disabled'); - - cy.get('[name="title"]').type( - 'Remove YouTube Kids app until it eliminates its inappropriate content' - ); - - cy.contains('button', 'Submit').should('not.be.disabled'); - }); - - maybeIt('Should convert an issue to a incident report', () => { - cy.login(Cypress.env('e2eUsername'), Cypress.env('e2ePassword')); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindReport', - 'FindReport', - report10 - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'ProbablyRelatedReports', - 'ProbablyRelatedReports', - { - data: { reports: [] }, - } - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'ProbablyRelatedIncidents', - 'ProbablyRelatedIncidents', - { - data: { incidents: [] }, - } - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindReportWithTranslations', - 'FindReportWithTranslations', - issueWithTranslations - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindIncidents', - 'FindIncidents', - { data: { incidents: [] } } - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindIncidentsTitles', - 'FindIncidentsTitles', - { - data: { - incidents: [ - { - _typename: 'Incident', - incident_id: 1, - title: 'Incident 1', - }, - { - _typename: 'Incident', - incident_id: 2, - title: 'Incident 2', - }, - ], - }, - } - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'logReportHistory', - 'logReportHistory', - { - data: { - logReportHistory: { - report_number: 10, - }, - }, - } - ); - - cy.visit(`/cite/edit?report_number=23`); - - cy.wait('@FindIncidents'); - - cy.wait('@FindReportWithTranslations'); - - cy.wait('@FindIncidentsTitles'); - - cy.get('form[data-cy="report"]').should('be.visible'); - - cy.get('[name="incident_ids"]').type('1'); - - cy.get('[id="incident_ids-item-0"]').click(); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'UpdateReport', - 'UpdateReport', - updateOneReport - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'UpdateReportTranslation', - 'UpdateReportTranslation', - updateOneReportTranslation - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'LinkReportsToIncidents', - 'LinkReportsToIncidents', - { - data: { - linkReportsToIncidents: [ - { - __typename: 'Incident', - incident_id: 1, - reports: [{ __typename: 'Report', report_number: 23 }], - }, - ], - }, - } - ); - - cy.window().then((win) => cy.stub(win, 'confirm').as('confirm').returns(true)); - - const now = new Date(); - - cy.clock(now); - - cy.contains('button', 'Submit').click(); - - cy.get('@confirm').should('have.been.calledOnce').invoke('restore'); - - const expectedReport = { - authors: ['Marco Acevedo'], - cloudinary_id: - 'reports/assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975', - date_downloaded: new Date('2019-04-13').toISOString(), - date_published: new Date('2015-07-11').toISOString(), - flag: null, - image_url: - 'https://assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975', - report_number: 10, - submitters: ['Roman Yampolskiy'], - tags: ['Test Tag'], - text: '## Video still of a reproduced version of Minnie Mouse\n\nWhich appeared on the now-suspended Simple Fun channel Simple Fun.', - plain_text: - 'Video still of a reproduced version of Minnie Mouse\n\nWhich appeared on the now-suspended Simple Fun channel Simple Fun.\n', - title: 'Remove YouTube Kids app until it eliminates its inappropriate content', - url: 'https://www.change.org/p/remove-youtube-kids-app-until-it-eliminates-its-inappropriate-content', - editor_notes: '', - language: 'en', - source_domain: 'change.org', - epoch_date_published: 1436572800, - date_modified: format(now, 'yyyy-MM-dd'), - epoch_date_modified: getUnixTime(now), - }; - - cy.wait('@UpdateReport') - .its('request.body.variables') - .then((variables) => { - expect(variables.query.report_number).to.equal(23); - expect({ - ...variables.set, - date_modified: format(new Date(variables.set.date_modified), 'yyyy-MM-dd'), - }).deep.eq(expectedReport); - }); - - cy.wait('@logReportHistory') - .its('request.body.variables.input') - .then((input) => { - const expectedResult = { - ...report10.data.report, - ...expectedReport, - modifiedBy: user.userId, - user: report10.data.report.user.userId, - date_modified: input.date_modified, - }; - - expect(input).to.deep.eq(expectedResult); - }); - - cy.wait('@UpdateReportTranslation'); - - cy.wait('@UpdateReportTranslation'); - - cy.wait('@LinkReportsToIncidents').then((xhr) => { - expect(xhr.request.body.variables.input).to.deep.eq({ - incident_ids: [1], - report_numbers: [23], - }); - }); - - cy.contains('[data-cy="toast"]', 'Incident report 23 updated successfully.', { timeout: 8000 }); - }); - - maybeIt('Should convert an incident report to an issue', () => { - cy.login(Cypress.env('e2eUsername'), Cypress.env('e2ePassword')); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindReport', - 'FindReport', - report10 - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'ProbablyRelatedReports', - 'ProbablyRelatedReports', - { - data: { reports: [] }, - } - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'ProbablyRelatedIncidents', - 'ProbablyRelatedIncidents', - { - data: { incidents: [] }, - } - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindReportWithTranslations', - 'FindReportWithTranslations', - reportWithTranslations - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindIncidents', - 'FindIncidents', - { - data: { - incidents: [ - { - _typename: 'Incident', - incident_id: 1, - title: 'Incident 1', - }, - ], - }, - } - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'FindIncidentsTitles', - 'FindIncidentsTitles', - { - data: { - incidents: [ - { - _typename: 'Incident', - incident_id: 1, - title: 'Incident 1', - }, - { - _typename: 'Incident', - incident_id: 2, - title: 'Incident 2', - }, - ], - }, - } - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'logReportHistory', - 'logReportHistory', - { - data: { - logReportHistory: { - report_number: 10, - }, - }, - } - ); - - cy.visit(`/cite/edit?report_number=23`); - - cy.wait('@FindIncidents'); - - cy.wait('@FindReportWithTranslations'); - - cy.wait('@FindIncidentsTitles'); - - cy.get('form[data-cy="report"]').should('be.visible'); - - cy.contains('div', 'Incident 1').next().click(); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'UpdateReport', - 'UpdateReport', - updateOneReport - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'UpdateReportTranslation', - 'UpdateReportTranslation', - updateOneReportTranslation - ); - - cy.conditionalIntercept( - '**/graphql', - (req) => req.body.operationName == 'LinkReportsToIncidents', - 'LinkReportsToIncidents', - { - data: { - linkReportsToIncidents: [], - }, - } - ); - - cy.window().then((win) => cy.stub(win, 'confirm').as('confirm').returns(true)); - - const now = new Date(); - - cy.clock(now); - - cy.contains('button', 'Submit').click(); - - cy.get('@confirm').should('have.been.calledOnce').invoke('restore'); - - const expectedReport = { - authors: ['Marco Acevedo'], - cloudinary_id: - 'reports/assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975', - date_downloaded: new Date('2019-04-13').toISOString(), - date_published: new Date('2015-07-11').toISOString(), - flag: null, - image_url: - 'https://assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975', - report_number: 10, - submitters: ['Roman Yampolskiy'], - tags: ['Test Tag'], - text: '## Video still of a reproduced version of Minnie Mouse\n\nWhich appeared on the now-suspended Simple Fun channel Simple Fun.', - plain_text: - 'Video still of a reproduced version of Minnie Mouse\n\nWhich appeared on the now-suspended Simple Fun channel Simple Fun.\n', - title: 'Remove YouTube Kids app until it eliminates its inappropriate content', - url: 'https://www.change.org/p/remove-youtube-kids-app-until-it-eliminates-its-inappropriate-content', - editor_notes: '', - language: 'en', - source_domain: 'change.org', - epoch_date_published: 1436572800, - date_modified: format(now, 'yyyy-MM-dd'), - epoch_date_modified: getUnixTime(now), - }; - - cy.wait('@UpdateReport') - .its('request.body.variables') - .then((variables) => { - expect(variables.query.report_number).to.equal(23); - expect({ - ...variables.set, - date_modified: format(new Date(variables.set.date_modified), 'yyyy-MM-dd'), - }).deep.eq(expectedReport); - }); - - cy.wait('@logReportHistory') - .its('request.body.variables.input') - .then((input) => { - const expectedResult = { - ...report10.data.report, - ...expectedReport, - modifiedBy: user.userId, - user: report10.data.report.user.userId, - date_modified: input.date_modified, - }; - - expect(input).to.deep.eq(expectedResult); - }); - - cy.wait('@UpdateReportTranslation'); - - cy.wait('@UpdateReportTranslation'); - - cy.wait('@LinkReportsToIncidents').then((xhr) => { - expect(xhr.request.body.variables.input).to.deep.eq({ - incident_ids: [], - report_numbers: [23], - }); - }); - - cy.contains('[data-cy="toast"]', 'Issue 23 updated successfully', { timeout: 8000 }); - }); - - it.skip('Should display the report image', () => { - cy.login(Cypress.env('e2eUsername'), Cypress.env('e2ePassword')); - - cy.visit(url); - - cy.get('[data-cy="image-preview-figure"] img', { timeout: 15000 }).should( - 'have.attr', - 'src', - 'https://res.cloudinary.com/pai/image/upload/d_fallback.jpg/f_auto/q_auto/v1/reports/assets.change.org/photos/0/yb/id/eYyBIdJOMHpqcty-1600x900-noPad.jpg?1523726975' - ); - }); -}); From 79bc1668a79477a8429e6ac16b77c2401a8cefac Mon Sep 17 00:00:00 2001 From: Clara Youdale Date: Mon, 17 Jun 2024 10:27:04 -0300 Subject: [PATCH 5/6] Remove comment --- site/gatsby-site/playwright/e2e/citeEdit.spec.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/site/gatsby-site/playwright/e2e/citeEdit.spec.ts b/site/gatsby-site/playwright/e2e/citeEdit.spec.ts index 1023f84903..d2172ab056 100644 --- a/site/gatsby-site/playwright/e2e/citeEdit.spec.ts +++ b/site/gatsby-site/playwright/e2e/citeEdit.spec.ts @@ -133,10 +133,7 @@ test.describe('Edit report', () => { const locator = page.locator(`[name=${key}]`); await expect(locator).toHaveValue(reportWithTranslations.data.report[key].toString()); }); - - - - // await expect(page.locator('[data-cy="text"] .CodeMirror')).toHaveText(reportWithTranslations.data.report.text); + let editorText = await getEditorText(page); await expect(editorText).toBe(reportWithTranslations.data.report.text); From fea4abe53042b20327a3fdb1d3d76049c2764444 Mon Sep 17 00:00:00 2001 From: Clara Youdale Date: Tue, 18 Jun 2024 16:21:22 -0300 Subject: [PATCH 6/6] Update citeEdit.spec with latest utils changes --- .../playwright/e2e/citeEdit.spec.ts | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/site/gatsby-site/playwright/e2e/citeEdit.spec.ts b/site/gatsby-site/playwright/e2e/citeEdit.spec.ts index d2172ab056..364979ea9b 100644 --- a/site/gatsby-site/playwright/e2e/citeEdit.spec.ts +++ b/site/gatsby-site/playwright/e2e/citeEdit.spec.ts @@ -1,14 +1,13 @@ -import { conditionalIntercept, waitForRequest, query, login, maybeIt, setEditorText, getEditorText } from '../utils'; +import { conditionalIntercept, waitForRequest, query, setEditorText, getEditorText, test } from '../utils'; import { format, getUnixTime } from 'date-fns'; import { gql } from '@apollo/client'; -import { test, expect } from '@playwright/test'; +import { expect } from '@playwright/test'; import config from '../config'; import reportWithTranslations from '../fixtures/reports/reportWithTranslations.json'; import report10 from '../fixtures/reports/report.json'; import updateOneReport from '../fixtures/reports/updateOneReport.json'; import updateOneReportTranslation from '../fixtures/reports/updateOneReportTranslation.json'; import issueWithTranslations from '../fixtures/reports/issueWithTranslations.json'; -import assert from 'assert'; test.describe('Edit report', () => { const url = '/cite/edit?report_number=10'; @@ -39,8 +38,8 @@ test.describe('Edit report', () => { }); }); - maybeIt('Should load and update report values', async ({ page }) => { - await login(page, config.E2E_ADMIN_USERNAME, config.E2E_ADMIN_PASSWORD); + test('Should load and update report values', async ({ page, login }) => { + await login(config.E2E_ADMIN_USERNAME, config.E2E_ADMIN_PASSWORD); await conditionalIntercept( page, @@ -133,7 +132,7 @@ test.describe('Edit report', () => { const locator = page.locator(`[name=${key}]`); await expect(locator).toHaveValue(reportWithTranslations.data.report[key].toString()); }); - + let editorText = await getEditorText(page); await expect(editorText).toBe(reportWithTranslations.data.report.text); @@ -207,7 +206,7 @@ test.describe('Edit report', () => { } }`); - await page.locator('button:has-text("Submit")').click(); + await page.getByRole('button', { name: 'Submit' }).click(); const updateReportRequest = await waitForRequest('updateReport'); const variables = updateReportRequest.postDataJSON().variables; @@ -269,11 +268,11 @@ test.describe('Edit report', () => { expect(translationVariables.plain_text).toBe('Este es texto en espanol\n\nque es mas largo que ochenta caracters, si ochenta caracteres!\n'); expect(translationVariables.title).toBe('Este es un titulo en Espanol!'); - await expect(page.locator('.tw-toast:has-text("Incident report 10 updated successfully.")')).toBeVisible(); + await expect(page.getByText('Incident report 10 updated successfully.')).toBeVisible(); }); - test('Should load and update Issue values', async ({ page }) => { - await login(page, config.E2E_ADMIN_USERNAME, config.E2E_ADMIN_PASSWORD); + test('Should load and update Issue values', async ({ page, login }) => { + await login(config.E2E_ADMIN_USERNAME, config.E2E_ADMIN_PASSWORD); await conditionalIntercept( page, @@ -382,7 +381,7 @@ test.describe('Edit report', () => { const now = new Date(); await page.context().addInitScript(`Date = class extends Date { constructor() { super("${now.toISOString()}"); } }`); - await page.locator('button:has-text("Submit")').click(); + await page.getByRole('button', { name: 'Submit' }).click(); const expectedReport = { authors: ['Test Author'], @@ -424,11 +423,11 @@ test.describe('Edit report', () => { expect(translationVariables.plain_text).toBe('Este es texto en espanol\n\nque es mas largo que ochenta caracters, si ochenta caracteres!\n'); expect(translationVariables.title).toBe('Este es un titulo en Espanol!'); - await expect(page.locator('[data-cy="toast"]:has-text("Issue 10 updated successfully")')).toBeVisible(); + await expect(page.getByText('Issue 10 updated successfully')).toBeVisible(); }); - maybeIt('Should delete incident report', async ({ page }) => { - await login(page, config.E2E_ADMIN_USERNAME, config.E2E_ADMIN_PASSWORD); + test('Should delete incident report', async ({ page, login }) => { + await login(config.E2E_ADMIN_USERNAME, config.E2E_ADMIN_PASSWORD); await conditionalIntercept( page, @@ -497,16 +496,17 @@ test.describe('Edit report', () => { report_numbers: [10] }); - await expect(page.locator('[data-cy="toast"]:has-text("Incident report 10 deleted successfully")')).toBeVisible(); + await expect(page.getByText('Incident report 10 deleted successfully')).toBeVisible(); + }); - await page.locator('button:has-text("Delete this report")').click(); + await page.getByText('Delete this report').click(); await page.waitForTimeout(2000); // Needed to wait for the dialog to be accepted }); - maybeIt('Should link a report to another incident', async ({ page }) => { - await login(page, config.E2E_ADMIN_USERNAME, config.E2E_ADMIN_PASSWORD); + test('Should link a report to another incident', async ({ page, login }) => { + await login(config.E2E_ADMIN_USERNAME, config.E2E_ADMIN_PASSWORD); await conditionalIntercept( page, @@ -605,9 +605,9 @@ test.describe('Edit report', () => { await expect(page.locator('form[data-cy="report"]')).toBeVisible(); - const incidentDiv = await page.locator('div:has-text("Incident 1")'); + const incidentDiv = page.locator('div:has-text("Incident 1")'); - await incidentDiv.locator('xpath=following-sibling::button').click(); + await incidentDiv.locator('xpath=following-sibling::button[1]').click(); await page.locator('[name="incident_ids"]').fill('2'); @@ -651,7 +651,7 @@ test.describe('Edit report', () => { 'LinkReportsToIncidents' ); - await page.locator('button:has-text("Submit")').click(); + await page.getByRole('button', { name: 'Submit' }).click(); let now = new Date(); await page.addInitScript(`{ @@ -739,8 +739,8 @@ test.describe('Edit report', () => { await expect(page.locator('[data-cy="toast"]')).toContainText('Incident report 23 updated successfully'); }); - maybeIt('Should convert an incident report to an issue', async ({ page }) => { - await login(page, config.E2E_ADMIN_USERNAME, config.E2E_ADMIN_PASSWORD); + test('Should convert an incident report to an issue', async ({ page, login }) => { + await login(config.E2E_ADMIN_USERNAME, config.E2E_ADMIN_PASSWORD); await conditionalIntercept( page, @@ -819,9 +819,9 @@ test.describe('Edit report', () => { await page.locator('form[data-cy="report"]').waitFor(); - const incidentDiv = await page.locator('div:has-text("Incident 1")'); + const incidentDiv = page.locator('div:has-text("Incident 1")'); - await incidentDiv.locator('xpath=following-sibling::button').click(); + await incidentDiv.locator('xpath=following-sibling::button[1]').click(); await conditionalIntercept( page, @@ -855,7 +855,7 @@ test.describe('Edit report', () => { Date.now = () => ${now.getTime()}; }`); - await page.locator('button:has-text("Submit")').click(); + await page.getByRole('button', { name: 'Submit' }).click(); const expectedReport = { authors: ['Marco Acevedo'], @@ -911,11 +911,11 @@ test.describe('Edit report', () => { report_numbers: [23], }); - await page.locator('[data-cy="toast"]:has-text("Issue 23 updated successfully")', { timeout: 8000 }).waitFor(); + await page.getByText('Issue 23 updated successfully').waitFor(); }); - test('Should display the report image', async ({ page }) => { - await login(page, config.E2E_ADMIN_USERNAME, config.E2E_ADMIN_PASSWORD); + test('Should display the report image', async ({ page, login }) => { + await login(config.E2E_ADMIN_USERNAME, config.E2E_ADMIN_PASSWORD); await page.goto(url);