Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ You can find and compare releases at the [GitHub release page](https://github.co

## Unreleased

### Fixed

- Detect `REQUIRED_ARG_ADDED` in `BreakingChangesFinder::findArgChanges()` when the old field had no prior arguments https://github.com/webonyx/graphql-php/pull/1976

## v15.37.2

### Changed
Expand Down
47 changes: 24 additions & 23 deletions src/Utils/BreakingChangesFinder.php
Original file line number Diff line number Diff line change
Expand Up @@ -535,33 +535,34 @@ public static function findArgChanges(
'description' => "{$typeName}.{$fieldName} arg {$oldArgDef->name} was removed",
];
}
}

// Check if arg was added to the field
foreach ($newTypeFields[$fieldName]->args as $newTypeFieldArgDef) {
$oldArgDef = null;
foreach ($oldTypeFields[$fieldName]->args as $oldArg) {
if ($oldArg->name === $newTypeFieldArgDef->name) {
$oldArgDef = $oldArg;
}
// Check if arg was added to the field. This must run even when the old
// field had zero args, so it lives outside the loop over $oldField->args.
foreach ($newTypeFields[$fieldName]->args as $newTypeFieldArgDef) {
$oldArgDef = null;
foreach ($oldTypeFields[$fieldName]->args as $oldArg) {
if ($oldArg->name === $newTypeFieldArgDef->name) {
$oldArgDef = $oldArg;
}
}

if ($oldArgDef !== null) {
continue;
}
if ($oldArgDef !== null) {
continue;
}

$newTypeName = $newType->name;
$newArgName = $newTypeFieldArgDef->name;
if ($newTypeFieldArgDef->isRequired()) {
$breakingChanges[] = [
'type' => self::BREAKING_CHANGE_REQUIRED_ARG_ADDED,
'description' => "A required arg {$newArgName} on {$newTypeName}.{$fieldName} was added",
];
} else {
$dangerousChanges[] = [
'type' => self::DANGEROUS_CHANGE_OPTIONAL_ARG_ADDED,
'description' => "An optional arg {$newArgName} on {$newTypeName}.{$fieldName} was added",
];
}
$newTypeName = $newType->name;
$newArgName = $newTypeFieldArgDef->name;
if ($newTypeFieldArgDef->isRequired()) {
$breakingChanges[] = [
'type' => self::BREAKING_CHANGE_REQUIRED_ARG_ADDED,
'description' => "A required arg {$newArgName} on {$newTypeName}.{$fieldName} was added",
];
} else {
$dangerousChanges[] = [
'type' => self::DANGEROUS_CHANGE_OPTIONAL_ARG_ADDED,
'description' => "An optional arg {$newArgName} on {$newTypeName}.{$fieldName} was added",
];
}
}
}
Expand Down
42 changes: 42 additions & 0 deletions tests/Utils/BreakingChangesFinderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,48 @@ public function testShouldDetectIfANonNullFieldArgumentWasAdded(): void
);
}

public function testShouldDetectIfANonNullFieldArgumentWasAddedToAFieldWithNoPriorArgs(): void
{
$oldType = new ObjectType([
'name' => 'Type1',
'fields' => [
'field1' => [
'type' => Type::string(),
'args' => [],
],
],
]);
$newType = new ObjectType([
'name' => 'Type1',
'fields' => [
'field1' => [
'type' => Type::string(),
'args' => [
'newRequiredArg' => Type::nonNull(Type::string()),
],
],
],
]);
$oldSchema = new Schema([
'query' => $this->queryType,
'types' => [$oldType],
]);
$newSchema = new Schema([
'query' => $this->queryType,
'types' => [$newType],
]);

self::assertSame(
[
[
'type' => BreakingChangesFinder::BREAKING_CHANGE_REQUIRED_ARG_ADDED,
'description' => 'A required arg newRequiredArg on Type1.field1 was added',
],
],
BreakingChangesFinder::findArgChanges($oldSchema, $newSchema)['breakingChanges']
);
}

/** @see it('should not flag args with the same type signature as breaking') */
public function testShouldNotFlagArgsWithTheSameTypeSignatureAsBreaking(): void
{
Expand Down
Loading