Skip to content

Commit

Permalink
Merge branch 'staging' into feature/3-translations-graphql-api-refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
pdcp1 committed Jan 21, 2025
2 parents 806ff8a + 00971cc commit bf61419
Show file tree
Hide file tree
Showing 33 changed files with 546 additions and 226 deletions.
6 changes: 5 additions & 1 deletion site/gatsby-site/i18n/locales/es/validation.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,9 @@
"Alleged implicated AI Systems can't be longer than 200 characters": "Los sistemas implicados no pueden tener más de 200 caracteres",
"*Alleged Implicated AI Systems is required": "Se requieren los sistemas de IA presuntamente implicados",
"Implicated AI systems must have at least 3 characters": "Los sistemas de IA implicados deben tener al menos 3 caracteres",
"Implicated AI systems can't be longer than 200 characters": "Los sistemas de IA implicados no pueden tener más de 200 caracteres"
"Implicated AI systems can't be longer than 200 characters": "Los sistemas de IA implicados no pueden tener más de 200 caracteres",
"Each alleged Developer must have at least 3 characters and less than 200": "Cada desarrollador presunto debe tener al menos 3 caracteres y menos de 200",
"Each alleged Deployer must have at least 3 characters and less than 200": "Cada implementador presunto debe tener al menos 3 caracteres y menos de 200",
"Each alleged Harmed parties must have at least 3 characters and less than 200": "Cada parte perjudicada presunta debe tener al menos 3 caracteres y menos de 200",
"Each alleged Implicated AI system must have at least 3 characters and less than 200": "Cada sistema de IA implicado presunto debe tener al menos 3 caracteres y menos de 200"
}
6 changes: 5 additions & 1 deletion site/gatsby-site/i18n/locales/fr/validation.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,9 @@
"Some data is missing.": "Certaines données manquent.",
"Please review. Some data is missing.": "Veuillez vérifier. Certaines données manquent.",
"Implicated Systems must have at least 3 characters": "Les systèmes impliqués doivent comporter au moins 3 caractères",
"Implicated Systems can't be longer than 200 characters": "Les systèmes impliqués ne peuvent pas comporter plus de 200 caractères"
"Implicated Systems can't be longer than 200 characters": "Les systèmes impliqués ne peuvent pas comporter plus de 200 caractères",
"Each alleged Developer must have at least 3 characters and less than 200": "Chaque développeur présumé doit comporter au moins 3 caractères et moins de 200",
"Each alleged Deployer must have at least 3 characters and less than 200": "Chaque implémenteur présumé doit comporter au moins 3 caractères et moins de 200",
"Each alleged Harmed parties must have at least 3 characters and less than 200": "Chaque partie lésée présumée doit comporter au moins 3 caractères et moins de 200",
"Each alleged Implicated AI system must have at least 3 characters and less than 200": "Chaque système d'IA impliqué présumé doit comporter au moins 3 caractères et moins de 200"
}
6 changes: 5 additions & 1 deletion site/gatsby-site/i18n/locales/ja/validation.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,9 @@
"*Incident Date required": "*インシデント日は必須です",
"*Incident ID(s) must be a number": "*インシデントIDは数字でなければいけません",
"Implicated Systems must have at least 3 characters": "関連システムは3文字以上でなければいけません",
"Implicated Systems can't be longer than 200 characters": "関連システムは200文字を超えることはできません"
"Implicated Systems can't be longer than 200 characters": "関連システムは200文字を超えることはできません",
"Each alleged Developer must have at least 3 characters and less than 200": "推定される開発者は3文字以上200文字以下でなければいけません",
"Each alleged Deployer must have at least 3 characters and less than 200": "推定されるデプロイヤーは3文字以上200文字以下でなければいけません",
"Each alleged Harmed parties must have at least 3 characters and less than 200": "推定される被害グループは3文字以上200文字以下でなければいけません",
"Each alleged Implicated AI system must have at least 3 characters and less than 200": "推定される関連AIシステムは3文字以上200文字以下でなければいけません"
}
195 changes: 195 additions & 0 deletions site/gatsby-site/playwright/e2e-full/submit.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,18 @@ test.describe('The Submit form', () => {
);


test('Should **not** show a list of related reports if no data entered', async ({ page, skipOnEmptyEnvironment }) => {

await page.goto(url);

const parentLocator = page.locator(`[data-cy="related-reports"]`);

const childrenCount = await parentLocator.locator('> *').count();

await expect(childrenCount).toBe(0);

}
);

test('Should *not* show a list of related reports', async ({ page, skipOnEmptyEnvironment }) => {

Expand Down Expand Up @@ -1523,4 +1535,187 @@ test.describe('The Submit form', () => {
await expect(page.locator('.tw-toast:has-text("Report successfully added to review queue. You can see your submission")')).toBeVisible();
await expect(page.locator(':text("Please review. Some data is missing.")')).not.toBeVisible();
});

test('Should show an error for inputs with two or fewer characters in developers, deployers, harmed_parties, and implicated_systems', async ({ page }) => {
await conditionalIntercept(
page,
'**/parseNews**',
() => true,
parseNews,
'parseNews'
);

await trackRequest(
page,
'**/graphql',
(req) => req.postDataJSON().operationName == 'FindSubmissions',
'findSubmissions'
);

await page.goto(url);

await waitForRequest('findSubmissions');

await page.locator('input[name="url"]').fill(
`https://www.arstechnica.com/gadgets/2017/11/youtube-to-crack-down-on-inappropriate-content-masked-as-kids-cartoons/`
);

await page.locator('button:has-text("Fetch info")').click();

await waitForRequest('parseNews');

await page.locator('[name="incident_date"]').fill('2020-01-01');

await expect(page.locator('.form-has-errors')).not.toBeVisible();

await page.locator('[data-cy="to-step-2"]').click();

await page.locator('[data-cy="to-step-3"]').click();

await page.locator('input[name="developers"]').fill('ab');
await page.keyboard.press('Enter');
await expect(page.locator('text=Each alleged Developer must have at least 3 characters and less than 200')).toBeVisible();
await page.locator('[data-testid="developers-input"] .rbt-close').click();

await page.locator('input[name="developers"]').fill('NewDev');
await page.keyboard.press('Enter');
await expect(page.locator('text=Each alleged Developer must have at least 3 characters and less than 200')).not.toBeVisible();

// Check for deployers field
await page.locator('input[name="deployers"]').fill('cd');
await page.keyboard.press('Enter');
await expect(page.locator('text=Each alleged Deployer must have at least 3 characters and less than 200')).toBeVisible();
await page.locator('[data-testid="deployers-input"] .rbt-close').click();

await page.locator('input[name="deployers"]').fill('NewDep');
await page.keyboard.press('Enter');
await expect(page.locator('text=Each alleged Deployer must have at least 3 characters and less than 200')).not.toBeVisible();

// Check for harmed_parties field
await page.locator('input[name="harmed_parties"]').fill('ef');
await page.keyboard.press('Enter');
await expect(page.locator('text=Each alleged Harmed parties must have at least 3 characters and less than 200')).toBeVisible();
await page.locator('[data-testid="harmed_parties-input"] .rbt-close').click();

await page.locator('input[name="harmed_parties"]').fill('NewHarmed');
await page.keyboard.press('Enter');
await expect(page.locator('text=Each alleged Harmed parties must have at least 3 characters and less than 200')).not.toBeVisible();

await page.locator('input[name="implicated_systems"]').fill('gh');
await page.keyboard.press('Enter');
await expect(page.locator('text=Each alleged Implicated AI system must have at least 3 characters and less than 200')).toBeVisible();
await page.locator('[data-testid="implicated_systems-input"] .rbt-close').click();

await page.locator('input[name="implicated_systems"]').fill('NewSystem');
await page.keyboard.press('Enter');
await expect(page.locator('text=Each alleged Implicated AI system must have at least 3 characters and less than 200')).not.toBeVisible();

// Check for "New selection" behavior
await page.locator('input[name="developers"]').fill('xy');
await page.locator('#developers-tags .dropdown-item:has-text("New selection: xy")').click();
await expect(page.locator('text=Each alleged Developer must have at least 3 characters and less than 200')).toBeVisible();
await page.locator('div').filter({ hasText: /^xy×Remove$/ }).getByLabel('Remove').click();

await page.locator('input[name="developers"]').fill('ValidDev');
await page.locator('#developers-tags .dropdown-item:has-text("New selection: ValidDev")').click();
await expect(page.locator('text=Each alleged Developer must have at least 3 characters and less than 200')).not.toBeVisible();

// Submit to ensure the form does not proceed with errors
await page.locator('button[type="submit"]').click();
await expect(page.locator('.tw-toast:has-text("Report successfully added to review queue. You can see your submission")')).toBeVisible();
await expect(page.locator(':text("Please review. Some data is missing.")')).not.toBeVisible();
});

test('Should show an error for inputs with 200 or more characters in developers, deployers, harmed_parties, and implicated_systems', async ({ page }) => {
await init();
await conditionalIntercept(
page,
'**/parseNews**',
() => true,
parseNews,
'parseNews'
);

await trackRequest(
page,
'**/graphql',
(req) => req.postDataJSON().operationName == 'FindSubmissions',
'findSubmissions'
);

await page.goto(url);

await waitForRequest('findSubmissions');

await page.locator('input[name="url"]').fill(
`https://www.arstechnica.com/gadgets/2017/11/youtube-to-crack-down-on-inappropriate-content-masked-as-kids-cartoons/`
);

await page.locator('button:has-text("Fetch info")').click();

await waitForRequest('parseNews');

await page.locator('[name="incident_date"]').fill('2020-01-01');

await expect(page.locator('.form-has-errors')).not.toBeVisible();

await page.locator('[data-cy="to-step-2"]').click();

await page.locator('[data-cy="to-step-3"]').click();

await page.locator('input[name="developers"]').fill('This test input text is designed to have precisely two hundred characters total so it works perfectly for checking HTML input validation to ensure that anything this length or longer should show error');
await page.keyboard.press('Enter');
await expect(page.locator('text=Each alleged Developer must have at least 3 characters and less than 200')).toBeVisible();
await page.locator('[data-testid="developers-input"] .rbt-close').click();

await page.locator('input[name="developers"]').fill('NewDev');
await page.keyboard.press('Enter');
await expect(page.locator('text=Each alleged Developer must have at least 3 characters and less than 200')).not.toBeVisible();

// Check for deployers field
await page.locator('input[name="deployers"]').fill('This test input text is designed to have precisely two hundred characters total so it works perfectly for checking HTML input validation to ensure that anything this length or longer should show error');
await page.keyboard.press('Enter');
await expect(page.locator('text=Each alleged Deployer must have at least 3 characters and less than 200')).toBeVisible();
await page.locator('[data-testid="deployers-input"] .rbt-close').click();

await page.locator('input[name="deployers"]').fill('NewDep');
await page.keyboard.press('Enter');
await expect(page.locator('text=Each alleged Deployer must have at least 3 characters and less than 200')).not.toBeVisible();

// Check for harmed_parties field
await page.locator('input[name="harmed_parties"]').fill('This test input text is designed to have precisely two hundred characters total so it works perfectly for checking HTML input validation to ensure that anything this length or longer should show error');
await page.keyboard.press('Enter');
await expect(page.locator('text=Each alleged Harmed parties must have at least 3 characters and less than 200')).toBeVisible();
await page.locator('[data-testid="harmed_parties-input"] .rbt-close').click();

await page.locator('input[name="harmed_parties"]').fill('NewHarmed');
await page.keyboard.press('Enter');
await expect(page.locator('text=Each alleged Harmed parties must have at least 3 characters and less than 200')).not.toBeVisible();

await page.locator('input[name="implicated_systems"]').fill('This test input text is designed to have precisely two hundred characters total so it works perfectly for checking HTML input validation to ensure that anything this length or longer should show error');
await page.keyboard.press('Enter');
await expect(page.locator('text=Each alleged Implicated AI system must have at least 3 characters and less than 200')).toBeVisible();
await page.locator('[data-testid="implicated_systems-input"] .rbt-close').click();

await page.locator('input[name="implicated_systems"]').fill('NewSystem');
await page.keyboard.press('Enter');
await expect(page.locator('text=Each alleged Implicated AI system must have at least 3 characters and less than 200')).not.toBeVisible();

// Check for "New selection" behavior
await page.locator('input[name="developers"]').fill('This test input text is designed to have precisely two hundred characters total so it works perfectly for checking HTML input validation to ensure that anything this length or longer should show error');
await page.locator('#developers-tags .dropdown-item:has-text("New selection: This test input text is designed to have precisely two hundred characters total so it works perfectly for checking HTML input validation to ensure that anything this length or longer should show error")').click();
await expect(page.locator('text=Each alleged Developer must have at least 3 characters and less than 200')).toBeVisible();
await page.locator('div').filter({ hasText: /^This test input text is designed to have precisely two hundred characters total so it works perfectly for checking HTML input validation to ensure that anything this length or longer should show error×Remove$/ }).getByLabel('Remove').click();

await page.locator('input[name="developers"]').fill('ValidDev');
await page.locator('#developers-tags .dropdown-item:has-text("New selection: ValidDev")').click();
await expect(page.locator('text=Each alleged Developer must have at least 3 characters and less than 200')).not.toBeVisible();

// Submit to ensure the form does not proceed with errors
await page.locator('button[type="submit"]').click();
await expect(page.locator('.tw-toast:has-text("Report successfully added to review queue. You can see your submission")')).toBeVisible();
await expect(page.locator(':text("Please review. Some data is missing.")')).not.toBeVisible();
});


});
4 changes: 4 additions & 0 deletions site/gatsby-site/server/fields/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ export const createNotificationsOnNewIncident = async (fullDocument: DBIncident,
type: 'new-incidents',
incident_id: incidentId,
processed: false,
created_at: new Date(),
});

const entityFields: (keyof DBIncident)[] = [
Expand Down Expand Up @@ -239,6 +240,7 @@ export const createNotificationsOnNewIncident = async (fullDocument: DBIncident,
incident_id: incidentId,
entity_id: entityId,
processed: false,
created_at: new Date(),
});
}
}
Expand Down Expand Up @@ -363,6 +365,7 @@ export const logReportHistory = async (updated: DBReport, context: Context) => {
const reportHistory: DBReportHistory = {
...updated,
modifiedBy: context.user?.id ?? '',
created_at: new Date(),
_id: undefined,
}

Expand All @@ -376,6 +379,7 @@ export const logIncidentHistory = async (updated: DBIncident, context: Context)
const incidentHistory: DBIncidentHistory = {
...updated,
modifiedBy: context.user?.id ?? '',
created_at: new Date(),
_id: undefined,
}

Expand Down
12 changes: 8 additions & 4 deletions site/gatsby-site/server/fields/reports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { generateMutationFields, generateQueryFields, getQueryResolver } from ".
import { isRole } from "../rules";
import { linkReportsToIncidents, logReportHistory } from "./common";
import { ReportType } from "../types/report";
import { Context, DBReport } from "../interfaces";


export const queryFields: GraphQLFieldConfigMap<any, any> = {
Expand Down Expand Up @@ -206,18 +207,20 @@ export const mutationFields: GraphQLFieldConfigMap<any, any> = {
type: new GraphQLNonNull(CreateVariantInput),
},
},
resolve: async (source, { input }, context) => {
resolve: async (source, { input }, context: Context) => {

const incidents = context.client.db('aiidprod').collection("incidents");
const reports = context.client.db('aiidprod').collection("reports");
const reports = context.client.db('aiidprod').collection<DBReport>("reports");

const parentIncident = await incidents.findOne({ incident_id: input.incidentId });

if (!parentIncident) {
throw `Incident ${input.incidentId} not found`;
}

const report_number = (await reports.find({}).sort({ report_number: -1 }).limit(1).next()).report_number + 1;
const lastReport = await reports.find({}).sort({ report_number: -1 }).limit(1).next();

const report_number = lastReport ? lastReport.report_number + 1 : 1;

const now = new Date();

Expand Down Expand Up @@ -246,9 +249,10 @@ export const mutationFields: GraphQLFieldConfigMap<any, any> = {
language: 'en',
tags: ['variant:unreviewed'],
inputs_outputs: input.variant.inputs_outputs,
user: context.user?.id ?? '',
};

await reports.insertOne({ ...newReport, report_number: newReport.report_number });
await reports.insertOne({ ...newReport, report_number: newReport.report_number, created_at: new Date() });

const incident_ids = [input.incidentId];
const report_numbers = [newReport.report_number];
Expand Down
Loading

0 comments on commit bf61419

Please sign in to comment.