How to use inaccessible method in storybook-root

Best JavaScript code snippet using storybook-root

removeInaccessibleElements.test.ts

Source:removeInaccessibleElements.test.ts Github

copy

Full Screen

1import {2 ArgumentDefinition,3 FieldDefinition,4 InterfaceType,5 ObjectType,6 UnionType,7} from "../definitions";8import { buildSchema } from "../buildSchema";9import { removeInaccessibleElements } from "../inaccessibleSpec";10import { GraphQLError } from "graphql";11import { errorCauses } from "../error";12describe("removeInaccessibleElements", () => {13 const INACCESSIBLE_V02_HEADER = `14 directive @core(feature: String!, as: String, for: core__Purpose) repeatable on SCHEMA15 enum core__Purpose {16 EXECUTION17 SECURITY18 }19 directive @inaccessible on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION20 schema21 @core(feature: "https://specs.apollo.dev/core/v0.2")22 @core(feature: "https://specs.apollo.dev/inaccessible/v0.2")23 {24 query: Query25 }26 `;27 function getCauses(e: unknown): GraphQLError[] {28 const causes = errorCauses(e as Error);29 expect(causes).toBeDefined();30 expect(Array.isArray(causes)).toBeTruthy();31 for (const cause of causes!) {32 expect(cause instanceof GraphQLError).toBeTruthy();33 }34 return causes!;35 }36 function expectErrors(expectedCauseCount: number, f: () => void): string[] {37 let error: unknown = undefined;38 try {39 f();40 } catch (e) {41 error = e;42 }43 expect(error).toBeDefined();44 const causes = getCauses(error);45 expect(causes).toHaveLength(expectedCauseCount);46 const messages = causes.map((cause) => cause.message);47 for (const message of messages) {48 expect(typeof message === "string").toBeTruthy();49 }50 messages.sort();51 return messages;52 }53 it(`succeeds for no inaccessible spec`, () => {54 const schema = buildSchema(`55 directive @core(feature: String!, as: String, for: core__Purpose) repeatable on SCHEMA56 enum core__Purpose {57 EXECUTION58 SECURITY59 }60 schema61 @core(feature: "https://specs.apollo.dev/core/v0.2")62 {63 query: Query64 }65 type Query {66 someField: String67 }68 `);69 removeInaccessibleElements(schema);70 schema.validate();71 });72 it(`doesn't affect non-core @inaccessible`, () => {73 const schema = buildSchema(`74 directive @core(feature: String!, as: String, for: core__Purpose) repeatable on SCHEMA75 enum core__Purpose {76 EXECUTION77 SECURITY78 }79 schema80 @core(feature: "https://specs.apollo.dev/core/v0.2")81 {82 query: Query83 }84 type Query {85 someField: String @inaccessible86 }87 directive @inaccessible on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION88 `);89 removeInaccessibleElements(schema);90 schema.validate();91 expect(schema.elementByCoordinate("Query.someField")).toBeDefined();92 });93 it(`fails for no @inaccessible definition`, () => {94 const schema = buildSchema(`95 directive @core(feature: String!, as: String, for: core__Purpose) repeatable on SCHEMA96 enum core__Purpose {97 EXECUTION98 SECURITY99 }100 schema101 @core(feature: "https://specs.apollo.dev/core/v0.2")102 @core(feature: "https://specs.apollo.dev/inaccessible/v0.1")103 {104 query: Query105 }106 type Query {107 someField: String108 }109 `);110 const errorMessages = expectErrors(1, () => {111 removeInaccessibleElements(schema);112 });113 expect(errorMessages).toMatchInlineSnapshot(`114 Array [115 "Invalid schema: declares https://specs.apollo.dev/inaccessible/v0.1 spec but does not define a @inaccessible directive.",116 ]117 `);118 });119 it(`fails for incompatible @inaccessible definition`, () => {120 const schema = buildSchema(`121 directive @core(feature: String!, as: String, for: core__Purpose) repeatable on SCHEMA122 enum core__Purpose {123 EXECUTION124 SECURITY125 }126 directive @inaccessible on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION127 schema128 @core(feature: "https://specs.apollo.dev/core/v0.2")129 @core(feature: "https://specs.apollo.dev/inaccessible/v0.1")130 {131 query: Query132 }133 type Query {134 someField: String135 }136 `);137 const errorMessages = expectErrors(1, () => {138 removeInaccessibleElements(schema);139 });140 expect(errorMessages).toMatchInlineSnapshot(`141 Array [142 "Found invalid @inaccessible directive definition. Please ensure the directive definition in your schema's definitions matches the following:143 directive @inaccessible on FIELD_DEFINITION | INTERFACE | OBJECT | UNION",144 ]145 `);146 });147 it(`handles renames of @inaccessible via core "as"`, () => {148 const schema = buildSchema(`149 directive @core(feature: String!, as: String, for: core__Purpose) repeatable on SCHEMA150 enum core__Purpose {151 EXECUTION152 SECURITY153 }154 directive @foo on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION155 schema156 @core(feature: "https://specs.apollo.dev/core/v0.2")157 @core(feature: "https://specs.apollo.dev/inaccessible/v0.2", as: "foo")158 {159 query: Query160 }161 type Query {162 someField: Bar @inaccessible163 privateField: String @foo164 }165 scalar Bar166 directive @inaccessible on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION167 `);168 removeInaccessibleElements(schema);169 schema.validate();170 expect(schema.elementByCoordinate("Query.someField")).toBeDefined();171 expect(schema.elementByCoordinate("Query.privateField")).toBeUndefined();172 });173 it(`handles renames of @inaccessible via import "as"`, () => {174 const schema = buildSchema(`175 directive @link(url: String, as: String, for: link__Purpose, import: [link__Import]) repeatable on SCHEMA176 enum link__Purpose {177 EXECUTION178 SECURITY179 }180 scalar link__Import181 directive @foo on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION182 schema183 @link(url: "https://specs.apollo.dev/link/v1.0")184 @link(url: "https://specs.apollo.dev/inaccessible/v0.2", import: [{name: "@inaccessible", as: "@foo"}])185 {186 query: Query187 }188 type Query {189 someField: Bar @inaccessible190 privateField: String @foo191 }192 scalar Bar193 directive @inaccessible on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION194 `);195 removeInaccessibleElements(schema);196 schema.validate();197 expect(schema.elementByCoordinate("Query.someField")).toBeDefined();198 expect(schema.elementByCoordinate("Query.privateField")).toBeUndefined();199 });200 it(`fails for @inaccessible built-ins`, () => {201 const schema = buildSchema(`202 ${INACCESSIBLE_V02_HEADER}203 type Query {204 someField: String205 }206 # Built-in scalar207 scalar String @inaccessible208 # Built-in directive209 directive @deprecated(210 reason: String = "No longer supported" @inaccessible211 ) on FIELD_DEFINITION | ENUM_VALUE212 `);213 const errorMessages = expectErrors(2, () => {214 removeInaccessibleElements(schema);215 });216 expect(errorMessages).toMatchInlineSnapshot(`217 Array [218 "Built-in directive \\"@deprecated\\" cannot use @inaccessible.",219 "Built-in type \\"String\\" cannot use @inaccessible.",220 ]221 `);222 });223 it(`fails for @inaccessible core feature definitions`, () => {224 const schema = buildSchema(`225 directive @core(feature: String! @inaccessible, as: String, for: core__Purpose) repeatable on SCHEMA226 enum core__Purpose {227 EXECUTION @inaccessible228 SECURITY229 }230 directive @inaccessible on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION231 schema232 @core(feature: "https://specs.apollo.dev/core/v0.2")233 @core(feature: "https://specs.apollo.dev/inaccessible/v0.2")234 @core(feature: "http://localhost/foo/v1.0")235 {236 query: Query237 }238 type Query {239 someField: String!240 }241 # Object type242 type foo__Object1 @inaccessible {243 foo__Field: String!244 }245 # Object field246 type foo__Object2 implements foo__Interface2 {247 foo__Field: foo__Enum1! @inaccessible248 }249 # Object field argument250 type foo__Object3 {251 someField(someArg: foo__Enum1 @inaccessible): foo__Enum2!252 }253 # Interface type254 interface foo__Interface1 @inaccessible {255 foo__Field: String!256 }257 # Interface field258 interface foo__Interface2 {259 foo__Field: foo__Enum1! @inaccessible260 }261 # Interface field argument262 interface foo__Interface3 {263 someField(someArg: foo__InputObject1 @inaccessible): foo__Enum2!264 }265 # Union type266 union foo__Union @inaccessible = foo__Object1 | foo__Object2 | foo__Object3267 # Input object type268 input foo__InputObject1 @inaccessible {269 someField: foo__Enum1270 }271 # Input object field272 input foo__InputObject2 {273 someField: foo__Scalar @inaccessible274 }275 # Enum type276 enum foo__Enum1 @inaccessible {277 someValue278 }279 # Enum value280 enum foo__Enum2 {281 someValue @inaccessible282 }283 # Scalar type284 scalar foo__Scalar @inaccessible285 # Directive argument286 directive @foo(arg: foo__InputObject2 @inaccessible) repeatable on OBJECT287 `);288 // 15 = 6 type kinds + 3 field kinds + 3 argument kinds + 1 enum value + 2 extras on special core elements289 const errorMessages = expectErrors(15, () => {290 removeInaccessibleElements(schema);291 });292 expect(errorMessages).toMatchInlineSnapshot(`293 Array [294 "Core feature directive \\"@core\\" cannot use @inaccessible.",295 "Core feature directive \\"@foo\\" cannot use @inaccessible.",296 "Core feature type \\"core__Purpose\\" cannot use @inaccessible.",297 "Core feature type \\"foo__Enum1\\" cannot use @inaccessible.",298 "Core feature type \\"foo__Enum2\\" cannot use @inaccessible.",299 "Core feature type \\"foo__InputObject1\\" cannot use @inaccessible.",300 "Core feature type \\"foo__InputObject2\\" cannot use @inaccessible.",301 "Core feature type \\"foo__Interface1\\" cannot use @inaccessible.",302 "Core feature type \\"foo__Interface2\\" cannot use @inaccessible.",303 "Core feature type \\"foo__Interface3\\" cannot use @inaccessible.",304 "Core feature type \\"foo__Object1\\" cannot use @inaccessible.",305 "Core feature type \\"foo__Object2\\" cannot use @inaccessible.",306 "Core feature type \\"foo__Object3\\" cannot use @inaccessible.",307 "Core feature type \\"foo__Scalar\\" cannot use @inaccessible.",308 "Core feature type \\"foo__Union\\" cannot use @inaccessible.",309 ]310 `);311 });312 it(`fails for @inaccessible directive definitions that aren't only executable`, () => {313 const schema = buildSchema(`314 ${INACCESSIBLE_V02_HEADER}315 type Query {316 someField: String317 }318 directive @foo(arg1: String @inaccessible) repeatable on OBJECT319 directive @bar(arg2: String, arg3: String @inaccessible) repeatable on SCHEMA | FIELD320 `);321 const errorMessages = expectErrors(2, () => {322 removeInaccessibleElements(schema);323 });324 expect(errorMessages).toMatchInlineSnapshot(`325 Array [326 "Directive \\"@bar\\" cannot use @inaccessible because it may be applied to these type-system locations: SCHEMA.",327 "Directive \\"@foo\\" cannot use @inaccessible because it may be applied to these type-system locations: OBJECT.",328 ]329 `);330 });331 it(`removes @inaccessible object types`, () => {332 const schema = buildSchema(`333 ${INACCESSIBLE_V02_HEADER}334 extend schema {335 mutation: Mutation336 subscription: Subscription337 }338 # Non-inaccessible object type339 type Query {340 someField: String341 }342 # Inaccessible mutation types should be removed343 type Mutation @inaccessible {344 someObject: Object345 }346 # Inaccessible subscription types should be removed347 type Subscription @inaccessible {348 someField: String349 }350 # Inaccessible object type351 type Object @inaccessible {352 someField: String353 }354 # Inaccessible object type referenced by inaccessible object field355 type Referencer1 implements Referencer3 {356 someField: String357 privatefield: Object! @inaccessible358 }359 # Inaccessible object type referenced by non-inaccessible object field360 # with inaccessible parent361 type Referencer2 implements Referencer4 @inaccessible {362 privateField: [Object!]!363 }364 # Inaccessible object type referenced by inaccessible interface field365 interface Referencer3 {366 someField: String367 privatefield: Object @inaccessible368 }369 # Inaccessible object type referenced by non-inaccessible interface field370 # with inaccessible parent371 interface Referencer4 @inaccessible {372 privateField: [Object]373 }374 # Inaccessible object type referenced by union member with375 # non-inaccessible siblings and parent376 union Referencer5 = Query | Object377 # Inaccessible object type referenced by union member with no siblings378 # but with inaccessible parent379 union Referencer6 @inaccessible = Object380 `);381 removeInaccessibleElements(schema);382 schema.validate();383 expect(schema.elementByCoordinate("Query")).toBeDefined();384 expect(schema.elementByCoordinate("Mutation")).toBeUndefined();385 expect(schema.elementByCoordinate("Subscription")).toBeUndefined();386 expect(schema.elementByCoordinate("Object")).toBeUndefined();387 expect(schema.elementByCoordinate("Referencer1.someField")).toBeDefined();388 expect(389 schema.elementByCoordinate("Referencer1.privatefield")390 ).toBeUndefined();391 expect(schema.elementByCoordinate("Referencer2")).toBeUndefined();392 expect(schema.elementByCoordinate("Referencer3.someField")).toBeDefined();393 expect(394 schema.elementByCoordinate("Referencer3.privatefield")395 ).toBeUndefined();396 expect(schema.elementByCoordinate("Referencer4")).toBeUndefined();397 const unionType = schema.elementByCoordinate("Referencer5");398 expect(unionType instanceof UnionType).toBeTruthy();399 expect((unionType as UnionType).hasTypeMember("Query")).toBeTruthy();400 expect((unionType as UnionType).hasTypeMember("Object")).toBeFalsy();401 expect(schema.elementByCoordinate("Referencer6")).toBeUndefined();402 });403 it(`fails to remove @inaccessible object types for breaking removals`, () => {404 const schema = buildSchema(`405 ${INACCESSIBLE_V02_HEADER}406 # Query types can't be inaccessible407 type Query @inaccessible {408 someField: String409 }410 # Inaccessible object type411 type Object @inaccessible {412 someField: String413 }414 # Inaccessible object type can't be referenced by object field in the API415 # schema416 type Referencer1 implements Referencer2 {417 someField: Object!418 }419 # Inaccessible object type can't be referenced by interface field in the420 # API schema421 interface Referencer2 {422 someField: Object423 }424 # Inaccessible object type can't be referenced by union member with a425 # non-inaccessible parent and no non-inaccessible siblings426 union Referencer3 = Object427 `);428 const errorMessages = expectErrors(4, () => {429 removeInaccessibleElements(schema);430 });431 expect(errorMessages).toMatchInlineSnapshot(`432 Array [433 "Type \\"Object\\" is @inaccessible but is referenced by \\"Referencer1.someField\\", which is in the API schema.",434 "Type \\"Object\\" is @inaccessible but is referenced by \\"Referencer2.someField\\", which is in the API schema.",435 "Type \\"Query\\" is @inaccessible but is the root query type, which must be in the API schema.",436 "Type \\"Referencer3\\" is in the API schema but all of its members are @inaccessible.",437 ]438 `);439 });440 it(`removes @inaccessible interface types`, () => {441 const schema = buildSchema(`442 ${INACCESSIBLE_V02_HEADER}443 type Query {444 someField: String445 }446 # Non-inaccessible interface type447 interface VisibleInterface {448 someField: String449 }450 # Inaccessible interface type451 interface Interface @inaccessible {452 someField: String453 }454 # Inaccessible interface type referenced by inaccessible object field455 type Referencer1 implements Referencer3 {456 someField: String457 privatefield: Interface! @inaccessible458 }459 # Inaccessible interface type referenced by non-inaccessible object field460 # with inaccessible parent461 type Referencer2 implements Referencer4 @inaccessible {462 privateField: [Interface!]!463 }464 # Inaccessible interface type referenced by inaccessible interface field465 interface Referencer3 {466 someField: String467 privatefield: Interface @inaccessible468 }469 # Inaccessible interface type referenced by non-inaccessible interface470 # field with inaccessible parent471 interface Referencer4 @inaccessible {472 privateField: [Interface]473 }474 # Inaccessible interface type referenced by object type implements475 type Referencer5 implements VisibleInterface & Interface {476 someField: String477 }478 # Inaccessible interface type referenced by interface type implements479 interface Referencer6 implements VisibleInterface & Interface {480 someField: String481 }482 `);483 removeInaccessibleElements(schema);484 schema.validate();485 expect(schema.elementByCoordinate("VisibleInterface")).toBeDefined();486 expect(schema.elementByCoordinate("Interface")).toBeUndefined();487 expect(schema.elementByCoordinate("Referencer1.someField")).toBeDefined();488 expect(489 schema.elementByCoordinate("Referencer1.privatefield")490 ).toBeUndefined();491 expect(schema.elementByCoordinate("Referencer2")).toBeUndefined();492 expect(schema.elementByCoordinate("Referencer3.someField")).toBeDefined();493 expect(494 schema.elementByCoordinate("Referencer3.privatefield")495 ).toBeUndefined();496 expect(schema.elementByCoordinate("Referencer4")).toBeUndefined();497 const objectType = schema.elementByCoordinate("Referencer5");498 expect(objectType instanceof ObjectType).toBeTruthy();499 expect(500 (objectType as ObjectType).implementsInterface("VisibleInterface")501 ).toBeTruthy();502 expect(503 (objectType as ObjectType).implementsInterface("Interface")504 ).toBeFalsy();505 const interfaceType = schema.elementByCoordinate("Referencer6");506 expect(interfaceType instanceof InterfaceType).toBeTruthy();507 expect(508 (interfaceType as InterfaceType).implementsInterface("VisibleInterface")509 ).toBeTruthy();510 expect(511 (interfaceType as InterfaceType).implementsInterface("Interface")512 ).toBeFalsy();513 });514 it(`fails to remove @inaccessible interface types for breaking removals`, () => {515 const schema = buildSchema(`516 ${INACCESSIBLE_V02_HEADER}517 type Query {518 someField: String519 }520 # Inaccessible interface type521 interface Interface @inaccessible {522 someField: String523 }524 # Inaccessible interface type can't be referenced by object field in the525 # API schema526 type Referencer1 implements Referencer2 {527 someField: [Interface!]!528 }529 # Inaccessible interface type can't be referenced by interface field in530 # the API schema531 interface Referencer2 {532 someField: [Interface]533 }534 `);535 const errorMessages = expectErrors(2, () => {536 removeInaccessibleElements(schema);537 });538 expect(errorMessages).toMatchInlineSnapshot(`539 Array [540 "Type \\"Interface\\" is @inaccessible but is referenced by \\"Referencer1.someField\\", which is in the API schema.",541 "Type \\"Interface\\" is @inaccessible but is referenced by \\"Referencer2.someField\\", which is in the API schema.",542 ]543 `);544 });545 it(`removes @inaccessible union types`, () => {546 const schema = buildSchema(`547 ${INACCESSIBLE_V02_HEADER}548 type Query {549 someField: String550 }551 # Non-inaccessible union type552 union VisibleUnion = Query553 # Inaccessible union type554 union Union @inaccessible = Query555 # Inaccessible union type referenced by inaccessible object field556 type Referencer1 implements Referencer3 {557 someField: String558 privatefield: Union! @inaccessible559 }560 # Inaccessible union type referenced by non-inaccessible object field with561 # inaccessible parent562 type Referencer2 implements Referencer4 @inaccessible {563 privateField: [Union!]!564 }565 # Inaccessible union type referenced by inaccessible interface field566 interface Referencer3 {567 someField: String568 privatefield: Union @inaccessible569 }570 # Inaccessible union type referenced by non-inaccessible interface field571 # with inaccessible parent572 interface Referencer4 @inaccessible {573 privateField: [Union]574 }575 `);576 removeInaccessibleElements(schema);577 schema.validate();578 expect(schema.elementByCoordinate("VisibleUnion")).toBeDefined();579 expect(schema.elementByCoordinate("Union")).toBeUndefined();580 expect(schema.elementByCoordinate("Referencer1.someField")).toBeDefined();581 expect(582 schema.elementByCoordinate("Referencer1.privatefield")583 ).toBeUndefined();584 expect(schema.elementByCoordinate("Referencer2")).toBeUndefined();585 expect(schema.elementByCoordinate("Referencer3.someField")).toBeDefined();586 expect(587 schema.elementByCoordinate("Referencer3.privatefield")588 ).toBeUndefined();589 expect(schema.elementByCoordinate("Referencer4")).toBeUndefined();590 });591 it(`fails to remove @inaccessible union types for breaking removals`, () => {592 const schema = buildSchema(`593 ${INACCESSIBLE_V02_HEADER}594 type Query {595 someField: String596 }597 # Inaccessible union type598 union Union @inaccessible = Query599 # Inaccessible union type can't be referenced by object field in the API600 # schema601 type Referencer1 implements Referencer2 {602 someField: Union!603 }604 # Inaccessible union type can't be referenced by interface field in the605 # API schema606 interface Referencer2 {607 someField: Union608 }609 `);610 const errorMessages = expectErrors(2, () => {611 removeInaccessibleElements(schema);612 });613 expect(errorMessages).toMatchInlineSnapshot(`614 Array [615 "Type \\"Union\\" is @inaccessible but is referenced by \\"Referencer1.someField\\", which is in the API schema.",616 "Type \\"Union\\" is @inaccessible but is referenced by \\"Referencer2.someField\\", which is in the API schema.",617 ]618 `);619 });620 it(`removes @inaccessible input object types`, () => {621 const schema = buildSchema(`622 ${INACCESSIBLE_V02_HEADER}623 type Query {624 someField: String625 }626 # Non-inaccessible input object type627 input VisibleInputObject {628 someField: String629 }630 # Inaccessible input object type631 input InputObject @inaccessible {632 someField: String633 }634 # Inaccessible input object type referenced by inaccessible object field635 # argument636 type Referencer1 implements Referencer4 {637 someField(privateArg: InputObject @inaccessible): String638 }639 # Inaccessible input object type referenced by non-inaccessible object640 # field argument with inaccessible parent641 type Referencer2 implements Referencer5 {642 someField: String643 privateField(privateArg: InputObject!): String @inaccessible644 }645 # Inaccessible input object type referenced by non-inaccessible object646 # field argument with inaccessible grandparent647 type Referencer3 implements Referencer6 @inaccessible {648 privateField(privateArg: InputObject!): String649 }650 # Inaccessible input object type referenced by inaccessible interface651 # field argument652 interface Referencer4 {653 someField(privateArg: InputObject @inaccessible): String654 }655 # Inaccessible input object type referenced by non-inaccessible interface656 # field argument with inaccessible parent657 interface Referencer5 {658 someField: String659 privateField(privateArg: InputObject!): String @inaccessible660 }661 # Inaccessible input object type referenced by non-inaccessible interface662 # field argument with inaccessible grandparent663 interface Referencer6 @inaccessible {664 privateField(privateArg: InputObject!): String665 }666 # Inaccessible input object type referenced by inaccessible input object667 # field668 input Referencer7 {669 someField: String670 privateField: InputObject @inaccessible671 }672 # Inaccessible input object type referenced by non-inaccessible input673 # object field with inaccessible parent674 input Referencer8 @inaccessible {675 privateField: InputObject!676 }677 # Inaccessible input object type referenced by inaccessible directive678 # argument679 directive @referencer9(privateArg: InputObject @inaccessible) on FIELD680 `);681 removeInaccessibleElements(schema);682 schema.validate();683 expect(schema.elementByCoordinate("VisibleInputObject")).toBeDefined();684 expect(schema.elementByCoordinate("InputObject")).toBeUndefined();685 expect(schema.elementByCoordinate("Referencer1.someField")).toBeDefined();686 expect(687 schema.elementByCoordinate("Referencer1.someField(privateArg:)")688 ).toBeUndefined();689 expect(schema.elementByCoordinate("Referencer2.someField")).toBeDefined();690 expect(691 schema.elementByCoordinate("Referencer2.privateField")692 ).toBeUndefined();693 expect(schema.elementByCoordinate("Referencer3")).toBeUndefined();694 expect(schema.elementByCoordinate("Referencer4.someField")).toBeDefined();695 expect(696 schema.elementByCoordinate("Referencer4.someField(privateArg:)")697 ).toBeUndefined();698 expect(schema.elementByCoordinate("Referencer5.someField")).toBeDefined();699 expect(700 schema.elementByCoordinate("Referencer5.privateField")701 ).toBeUndefined();702 expect(schema.elementByCoordinate("Referencer6")).toBeUndefined();703 expect(schema.elementByCoordinate("Referencer7.someField")).toBeDefined();704 expect(705 schema.elementByCoordinate("Referencer7.privatefield")706 ).toBeUndefined();707 expect(schema.elementByCoordinate("Referencer8")).toBeUndefined();708 expect(schema.elementByCoordinate("@referencer9")).toBeDefined();709 expect(710 schema.elementByCoordinate("@referencer9(privateArg:)")711 ).toBeUndefined();712 });713 it(`fails to remove @inaccessible input object types for breaking removals`, () => {714 const schema = buildSchema(`715 ${INACCESSIBLE_V02_HEADER}716 type Query {717 someField: String718 }719 # Inaccessible input object type720 input InputObject @inaccessible {721 someField: String722 }723 # Inaccessible input object type can't be referenced by object field724 # argument in the API schema725 type Referencer1 implements Referencer2 {726 someField(someArg: InputObject): String727 }728 # Inaccessible input object type can't be referenced by interface field729 # argument in the API schema730 interface Referencer2 {731 someField(someArg: InputObject): String732 }733 # Inaccessible input object type can't be referenced by input object field734 # in the API schema735 input Referencer3 {736 someField: InputObject737 }738 # Inaccessible input object type can't be referenced by directive argument739 # in the API schema740 directive @referencer4(someArg: InputObject) on QUERY741 `);742 const errorMessages = expectErrors(4, () => {743 removeInaccessibleElements(schema);744 });745 expect(errorMessages).toMatchInlineSnapshot(`746 Array [747 "Type \\"InputObject\\" is @inaccessible but is referenced by \\"@referencer4(someArg:)\\", which is in the API schema.",748 "Type \\"InputObject\\" is @inaccessible but is referenced by \\"Referencer1.someField(someArg:)\\", which is in the API schema.",749 "Type \\"InputObject\\" is @inaccessible but is referenced by \\"Referencer2.someField(someArg:)\\", which is in the API schema.",750 "Type \\"InputObject\\" is @inaccessible but is referenced by \\"Referencer3.someField\\", which is in the API schema.",751 ]752 `);753 });754 it(`removes @inaccessible enum types`, () => {755 const schema = buildSchema(`756 ${INACCESSIBLE_V02_HEADER}757 type Query {758 someField: String759 }760 # Non-inaccessible enum type761 enum VisibleEnum {762 SOME_VALUE763 }764 # Inaccessible enum type765 enum Enum @inaccessible {766 SOME_VALUE767 }768 # Inaccessible enum type referenced by inaccessible object field769 type Referencer1 implements Referencer3 {770 someField: String771 privatefield: Enum! @inaccessible772 }773 # Inaccessible enum type referenced by non-inaccessible object field with774 # inaccessible parent775 type Referencer2 implements Referencer4 @inaccessible {776 privateField: [Enum!]!777 }778 # Inaccessible enum type referenced by inaccessible interface field779 interface Referencer3 {780 someField: String781 privatefield: Enum @inaccessible782 }783 # Inaccessible enum type referenced by non-inaccessible interface field784 # with inaccessible parent785 interface Referencer4 @inaccessible {786 privateField: [Enum]787 }788 # Inaccessible enum type referenced by inaccessible object field argument789 type Referencer5 implements Referencer8 {790 someField(privateArg: Enum @inaccessible): String791 }792 # Inaccessible enum type referenced by non-inaccessible object field793 # argument with inaccessible parent794 type Referencer6 implements Referencer9 {795 someField: String796 privateField(privateArg: Enum!): String @inaccessible797 }798 # Inaccessible enum type referenced by non-inaccessible object field799 # argument with inaccessible grandparent800 type Referencer7 implements Referencer10 @inaccessible {801 privateField(privateArg: Enum!): String802 }803 # Inaccessible enum type referenced by inaccessible interface field804 # argument805 interface Referencer8 {806 someField(privateArg: Enum @inaccessible): String807 }808 # Inaccessible enum type referenced by non-inaccessible interface field809 # argument with inaccessible parent810 interface Referencer9 {811 someField: String812 privateField(privateArg: Enum!): String @inaccessible813 }814 # Inaccessible enum type referenced by non-inaccessible interface field815 # argument with inaccessible grandparent816 interface Referencer10 @inaccessible {817 privateField(privateArg: Enum!): String818 }819 # Inaccessible enum type referenced by inaccessible input object field820 input Referencer11 {821 someField: String822 privateField: Enum @inaccessible823 }824 # Inaccessible enum type referenced by non-inaccessible input object field825 # with inaccessible parent826 input Referencer12 @inaccessible {827 privateField: Enum!828 }829 # Inaccessible enum type referenced by inaccessible directive argument830 directive @referencer13(privateArg: Enum @inaccessible) on FRAGMENT_DEFINITION831 `);832 removeInaccessibleElements(schema);833 schema.validate();834 expect(schema.elementByCoordinate("VisibleEnum")).toBeDefined();835 expect(schema.elementByCoordinate("Enum")).toBeUndefined();836 expect(schema.elementByCoordinate("Referencer1.someField")).toBeDefined();837 expect(838 schema.elementByCoordinate("Referencer1.privatefield")839 ).toBeUndefined();840 expect(schema.elementByCoordinate("Referencer2")).toBeUndefined();841 expect(schema.elementByCoordinate("Referencer3.someField")).toBeDefined();842 expect(843 schema.elementByCoordinate("Referencer3.privatefield")844 ).toBeUndefined();845 expect(schema.elementByCoordinate("Referencer4")).toBeUndefined();846 expect(schema.elementByCoordinate("Referencer5.someField")).toBeDefined();847 expect(848 schema.elementByCoordinate("Referencer5.someField(privateArg:)")849 ).toBeUndefined();850 expect(schema.elementByCoordinate("Referencer6.someField")).toBeDefined();851 expect(852 schema.elementByCoordinate("Referencer6.privateField")853 ).toBeUndefined();854 expect(schema.elementByCoordinate("Referencer7")).toBeUndefined();855 expect(schema.elementByCoordinate("Referencer8.someField")).toBeDefined();856 expect(857 schema.elementByCoordinate("Referencer8.someField(privateArg:)")858 ).toBeUndefined();859 expect(schema.elementByCoordinate("Referencer9.someField")).toBeDefined();860 expect(861 schema.elementByCoordinate("Referencer9.privateField")862 ).toBeUndefined();863 expect(schema.elementByCoordinate("Referencer10")).toBeUndefined();864 expect(schema.elementByCoordinate("Referencer11.someField")).toBeDefined();865 expect(866 schema.elementByCoordinate("Referencer11.privatefield")867 ).toBeUndefined();868 expect(schema.elementByCoordinate("Referencer12")).toBeUndefined();869 expect(schema.elementByCoordinate("@referencer13")).toBeDefined();870 expect(871 schema.elementByCoordinate("@referencer13(privateArg:)")872 ).toBeUndefined();873 });874 it(`fails to remove @inaccessible enum types for breaking removals`, () => {875 const schema = buildSchema(`876 ${INACCESSIBLE_V02_HEADER}877 type Query {878 someField: String879 }880 # Inaccessible enum type881 enum Enum @inaccessible {882 SOME_VALUE883 }884 # Inaccessible enum type can't be referenced by object field in the API885 # schema886 type Referencer1 implements Referencer2 {887 somefield: [Enum!]!888 }889 # Inaccessible enum type can't be referenced by interface field in the API890 # schema891 interface Referencer2 {892 somefield: [Enum]893 }894 # Inaccessible enum type can't be referenced by object field argument in895 # the API schema896 type Referencer3 implements Referencer4 {897 someField(someArg: Enum): String898 }899 # Inaccessible enum type can't be referenced by interface field argument900 # in the API schema901 interface Referencer4 {902 someField(someArg: Enum): String903 }904 # Inaccessible enum type can't be referenced by input object field in the905 # API schema906 input Referencer5 {907 someField: Enum908 }909 # Inaccessible enum type can't be referenced by directive argument in the910 # API schema911 directive @referencer6(someArg: Enum) on FRAGMENT_SPREAD912 `);913 const errorMessages = expectErrors(6, () => {914 removeInaccessibleElements(schema);915 });916 expect(errorMessages).toMatchInlineSnapshot(`917 Array [918 "Type \\"Enum\\" is @inaccessible but is referenced by \\"@referencer6(someArg:)\\", which is in the API schema.",919 "Type \\"Enum\\" is @inaccessible but is referenced by \\"Referencer1.somefield\\", which is in the API schema.",920 "Type \\"Enum\\" is @inaccessible but is referenced by \\"Referencer2.somefield\\", which is in the API schema.",921 "Type \\"Enum\\" is @inaccessible but is referenced by \\"Referencer3.someField(someArg:)\\", which is in the API schema.",922 "Type \\"Enum\\" is @inaccessible but is referenced by \\"Referencer4.someField(someArg:)\\", which is in the API schema.",923 "Type \\"Enum\\" is @inaccessible but is referenced by \\"Referencer5.someField\\", which is in the API schema.",924 ]925 `);926 });927 it(`removes @inaccessible scalar types`, () => {928 const schema = buildSchema(`929 ${INACCESSIBLE_V02_HEADER}930 type Query {931 someField: String932 }933 # Non-inaccessible scalar type934 scalar VisibleScalar935 # Inaccessible scalar type936 scalar Scalar @inaccessible937 # Inaccessible scalar type referenced by inaccessible object field938 type Referencer1 implements Referencer3 {939 someField: String940 privatefield: Scalar! @inaccessible941 }942 # Inaccessible scalar type referenced by non-inaccessible object field943 # with inaccessible parent944 type Referencer2 implements Referencer4 @inaccessible {945 privateField: [Scalar!]!946 }947 # Inaccessible scalar type referenced by inaccessible interface field948 interface Referencer3 {949 someField: String950 privatefield: Scalar @inaccessible951 }952 # Inaccessible scalar type referenced by non-inaccessible interface field953 # with inaccessible parent954 interface Referencer4 @inaccessible {955 privateField: [Scalar]956 }957 # Inaccessible scalar type referenced by inaccessible object field958 # argument959 type Referencer5 implements Referencer8 {960 someField(privateArg: Scalar @inaccessible): String961 }962 # Inaccessible scalar type referenced by non-inaccessible object field963 # argument with inaccessible parent964 type Referencer6 implements Referencer9 {965 someField: String966 privateField(privateArg: Scalar!): String @inaccessible967 }968 # Inaccessible scalar type referenced by non-inaccessible object field969 # argument with inaccessible grandparent970 type Referencer7 implements Referencer10 @inaccessible {971 privateField(privateArg: Scalar!): String972 }973 # Inaccessible scalar type referenced by inaccessible interface field974 # argument975 interface Referencer8 {976 someField(privateArg: Scalar @inaccessible): String977 }978 # Inaccessible scalar type referenced by non-inaccessible interface field979 # argument with inaccessible parent980 interface Referencer9 {981 someField: String982 privateField(privateArg: Scalar!): String @inaccessible983 }984 # Inaccessible scalar type referenced by non-inaccessible interface field985 # argument with inaccessible grandparent986 interface Referencer10 @inaccessible {987 privateField(privateArg: Scalar!): String988 }989 # Inaccessible scalar type referenced by inaccessible input object field990 input Referencer11 {991 someField: String992 privateField: Scalar @inaccessible993 }994 # Inaccessible scalar type referenced by non-inaccessible input object995 # field with inaccessible parent996 input Referencer12 @inaccessible {997 privateField: Scalar!998 }999 # Inaccessible scalar type referenced by inaccessible directive argument1000 directive @referencer13(privateArg: Scalar @inaccessible) on INLINE_FRAGMENT1001 `);1002 removeInaccessibleElements(schema);1003 schema.validate();1004 expect(schema.elementByCoordinate("VisibleScalar")).toBeDefined();1005 expect(schema.elementByCoordinate("Scalar")).toBeUndefined();1006 expect(schema.elementByCoordinate("Referencer1.someField")).toBeDefined();1007 expect(1008 schema.elementByCoordinate("Referencer1.privatefield")1009 ).toBeUndefined();1010 expect(schema.elementByCoordinate("Referencer2")).toBeUndefined();1011 expect(schema.elementByCoordinate("Referencer3.someField")).toBeDefined();1012 expect(1013 schema.elementByCoordinate("Referencer3.privatefield")1014 ).toBeUndefined();1015 expect(schema.elementByCoordinate("Referencer4")).toBeUndefined();1016 expect(schema.elementByCoordinate("Referencer5.someField")).toBeDefined();1017 expect(1018 schema.elementByCoordinate("Referencer5.someField(privateArg:)")1019 ).toBeUndefined();1020 expect(schema.elementByCoordinate("Referencer6.someField")).toBeDefined();1021 expect(1022 schema.elementByCoordinate("Referencer6.privateField")1023 ).toBeUndefined();1024 expect(schema.elementByCoordinate("Referencer7")).toBeUndefined();1025 expect(schema.elementByCoordinate("Referencer8.someField")).toBeDefined();1026 expect(1027 schema.elementByCoordinate("Referencer8.someField(privateArg:)")1028 ).toBeUndefined();1029 expect(schema.elementByCoordinate("Referencer9.someField")).toBeDefined();1030 expect(1031 schema.elementByCoordinate("Referencer9.privateField")1032 ).toBeUndefined();1033 expect(schema.elementByCoordinate("Referencer10")).toBeUndefined();1034 expect(schema.elementByCoordinate("Referencer11.someField")).toBeDefined();1035 expect(1036 schema.elementByCoordinate("Referencer11.privatefield")1037 ).toBeUndefined();1038 expect(schema.elementByCoordinate("Referencer12")).toBeUndefined();1039 expect(schema.elementByCoordinate("@referencer13")).toBeDefined();1040 expect(1041 schema.elementByCoordinate("@referencer13(privateArg:)")1042 ).toBeUndefined();1043 });1044 it(`fails to remove @inaccessible scalar types for breaking removals`, () => {1045 const schema = buildSchema(`1046 ${INACCESSIBLE_V02_HEADER}1047 type Query {1048 someField: String1049 }1050 # Inaccessible scalar type1051 scalar Scalar @inaccessible1052 # Inaccessible scalar type can't be referenced by object field in the API1053 # schema1054 type Referencer1 implements Referencer2 {1055 somefield: [[Scalar!]!]!1056 }1057 # Inaccessible scalar type can't be referenced by interface field in the1058 # API schema1059 interface Referencer2 {1060 somefield: [[Scalar]]1061 }1062 # Inaccessible scalar type can't be referenced by object field argument in1063 # the API schema1064 type Referencer3 implements Referencer4 {1065 someField(someArg: Scalar): String1066 }1067 # Inaccessible scalar type can't be referenced by interface field argument1068 # in the API schema1069 interface Referencer4 {1070 someField(someArg: Scalar): String1071 }1072 # Inaccessible scalar type can't be referenced by input object field in1073 # the API schema1074 input Referencer5 {1075 someField: Scalar1076 }1077 # Inaccessible scalar type can't be referenced by directive argument in1078 # the API schema1079 directive @referencer6(someArg: Scalar) on MUTATION1080 `);1081 const errorMessages = expectErrors(6, () => {1082 removeInaccessibleElements(schema);1083 });1084 expect(errorMessages).toMatchInlineSnapshot(`1085 Array [1086 "Type \\"Scalar\\" is @inaccessible but is referenced by \\"@referencer6(someArg:)\\", which is in the API schema.",1087 "Type \\"Scalar\\" is @inaccessible but is referenced by \\"Referencer1.somefield\\", which is in the API schema.",1088 "Type \\"Scalar\\" is @inaccessible but is referenced by \\"Referencer2.somefield\\", which is in the API schema.",1089 "Type \\"Scalar\\" is @inaccessible but is referenced by \\"Referencer3.someField(someArg:)\\", which is in the API schema.",1090 "Type \\"Scalar\\" is @inaccessible but is referenced by \\"Referencer4.someField(someArg:)\\", which is in the API schema.",1091 "Type \\"Scalar\\" is @inaccessible but is referenced by \\"Referencer5.someField\\", which is in the API schema.",1092 ]1093 `);1094 });1095 it(`removes @inaccessible object fields`, () => {1096 const schema = buildSchema(`1097 ${INACCESSIBLE_V02_HEADER}1098 extend schema {1099 mutation: Mutation1100 subscription: Subscription1101 }1102 # Inaccessible object field on query type1103 type Query {1104 someField: String1105 privateField: String @inaccessible1106 }1107 # Inaccessible object field on mutation type1108 type Mutation {1109 someField: String1110 privateField: String @inaccessible1111 }1112 # Inaccessible object field on subscription type1113 type Subscription {1114 someField: String1115 privateField: String @inaccessible1116 }1117 # Inaccessible (and non-inaccessible) object field1118 type Object implements Referencer1 & Referencer2 {1119 someField: String1120 privateField: String @inaccessible1121 }1122 # Inaccessible object field referenced by inaccessible interface field1123 interface Referencer1 {1124 someField: String1125 privateField: String @inaccessible1126 }1127 # Inaccessible object field referenced by non-inaccessible interface field1128 # with inaccessible parent1129 interface Referencer2 @inaccessible {1130 privateField: String1131 }1132 # Inaccessible object field with an inaccessible parent and no1133 # non-inaccessible siblings1134 type Referencer3 @inaccessible {1135 privateField: String @inaccessible1136 otherPrivateField: Float @inaccessible1137 }1138 `);1139 removeInaccessibleElements(schema);1140 schema.validate();1141 expect(schema.elementByCoordinate("Query.someField")).toBeDefined();1142 expect(schema.elementByCoordinate("Query.privateField")).toBeUndefined();1143 expect(schema.elementByCoordinate("Mutation.someField")).toBeDefined();1144 expect(schema.elementByCoordinate("Mutation.privateField")).toBeUndefined();1145 expect(schema.elementByCoordinate("Subscription.someField")).toBeDefined();1146 expect(1147 schema.elementByCoordinate("Subscription.privateField")1148 ).toBeUndefined();1149 const objectType = schema.elementByCoordinate("Object");1150 expect(objectType instanceof ObjectType).toBeTruthy();1151 expect(1152 (objectType as ObjectType).implementsInterface("Referencer1")1153 ).toBeTruthy();1154 expect(1155 (objectType as ObjectType).implementsInterface("Referencer2")1156 ).toBeFalsy();1157 expect(schema.elementByCoordinate("Object.someField")).toBeDefined();1158 expect(schema.elementByCoordinate("Object.privateField")).toBeUndefined();1159 expect(schema.elementByCoordinate("Referencer1.someField")).toBeDefined();1160 expect(1161 schema.elementByCoordinate("Referencer1.privatefield")1162 ).toBeUndefined();1163 expect(schema.elementByCoordinate("Referencer2")).toBeUndefined();1164 expect(schema.elementByCoordinate("Referencer3")).toBeUndefined();1165 });1166 it(`fails to remove @inaccessible object fields for breaking removals`, () => {1167 const schema = buildSchema(`1168 ${INACCESSIBLE_V02_HEADER}1169 extend schema {1170 mutation: Mutation1171 subscription: Subscription1172 }1173 # Inaccessible object field can't have a non-inaccessible parent query1174 # type and no non-inaccessible siblings1175 type Query {1176 privateField: String @inaccessible1177 otherPrivateField: Float @inaccessible1178 }1179 # Inaccessible object field can't have a non-inaccessible parent mutation1180 # type and no non-inaccessible siblings1181 type Mutation {1182 privateField: String @inaccessible1183 otherPrivateField: Float @inaccessible1184 }1185 # Inaccessible object field can't have a non-inaccessible parent1186 # subscription type and no non-inaccessible siblings1187 type Subscription {1188 privateField: String @inaccessible1189 otherPrivateField: Float @inaccessible1190 }1191 # Inaccessible object field1192 type Object implements Referencer1 {1193 someField: String1194 privateField: String @inaccessible1195 }1196 # Inaccessible object field can't be referenced by interface field in the1197 # API schema1198 interface Referencer1 {1199 privateField: String1200 }1201 # Inaccessible object field can't have a non-inaccessible parent object1202 # type and no non-inaccessible siblings1203 type Referencer2 {1204 privateField: String @inaccessible1205 otherPrivateField: Float @inaccessible1206 }1207 `);1208 const errorMessages = expectErrors(5, () => {1209 removeInaccessibleElements(schema);1210 });1211 expect(errorMessages).toMatchInlineSnapshot(`1212 Array [1213 "Field \\"Object.privateField\\" is @inaccessible but implements the interface field \\"Referencer1.privateField\\", which is in the API schema.",1214 "Type \\"Mutation\\" is in the API schema but all of its fields are @inaccessible.",1215 "Type \\"Query\\" is in the API schema but all of its fields are @inaccessible.",1216 "Type \\"Referencer2\\" is in the API schema but all of its fields are @inaccessible.",1217 "Type \\"Subscription\\" is in the API schema but all of its fields are @inaccessible.",1218 ]1219 `);1220 });1221 it(`removes @inaccessible interface fields`, () => {1222 const schema = buildSchema(`1223 ${INACCESSIBLE_V02_HEADER}1224 type Query {1225 someField: String1226 }1227 # Inaccessible (and non-inaccessible) interface field1228 interface Interface implements Referencer1 & Referencer2 {1229 someField: String1230 privateField: String @inaccessible1231 }1232 # Inaccessible interface field referenced by inaccessible interface field1233 interface Referencer1 {1234 someField: String1235 privateField: String @inaccessible1236 }1237 # Inaccessible interface field referenced by non-inaccessible interface1238 # field with inaccessible parent1239 interface Referencer2 @inaccessible {1240 privateField: String1241 }1242 # Inaccessible interface field with an inaccessible parent and no1243 # non-inaccessible siblings1244 interface Referencer3 @inaccessible {1245 privateField: String @inaccessible1246 otherPrivateField: Float @inaccessible1247 }1248 `);1249 removeInaccessibleElements(schema);1250 schema.validate();1251 const interfaceType = schema.elementByCoordinate("Interface");1252 expect(interfaceType instanceof InterfaceType).toBeTruthy();1253 expect(1254 (interfaceType as InterfaceType).implementsInterface("Referencer1")1255 ).toBeTruthy();1256 expect(1257 (interfaceType as InterfaceType).implementsInterface("Referencer2")1258 ).toBeFalsy();1259 expect(schema.elementByCoordinate("Interface.someField")).toBeDefined();1260 expect(1261 schema.elementByCoordinate("Interface.privateField")1262 ).toBeUndefined();1263 expect(schema.elementByCoordinate("Referencer1.someField")).toBeDefined();1264 expect(1265 schema.elementByCoordinate("Referencer1.privatefield")1266 ).toBeUndefined();1267 expect(schema.elementByCoordinate("Referencer2")).toBeUndefined();1268 expect(schema.elementByCoordinate("Referencer3")).toBeUndefined();1269 });1270 it(`fails to remove @inaccessible interface fields for breaking removals`, () => {1271 const schema = buildSchema(`1272 ${INACCESSIBLE_V02_HEADER}1273 type Query {1274 someField: String1275 }1276 # Inaccessible interface field1277 interface Interface implements Referencer1 {1278 someField: String1279 privateField: String @inaccessible1280 }1281 # Inaccessible interface field can't be referenced by interface field in1282 # the API schema1283 interface Referencer1 {1284 privateField: String1285 }1286 # Inaccessible interface field can't have a non-inaccessible parent object1287 # type and no non-inaccessible siblings1288 interface Referencer2 {1289 privateField: String @inaccessible1290 otherPrivateField: Float @inaccessible1291 }1292 `);1293 const errorMessages = expectErrors(2, () => {1294 removeInaccessibleElements(schema);1295 });1296 expect(errorMessages).toMatchInlineSnapshot(`1297 Array [1298 "Field \\"Interface.privateField\\" is @inaccessible but implements the interface field \\"Referencer1.privateField\\", which is in the API schema.",1299 "Type \\"Referencer2\\" is in the API schema but all of its fields are @inaccessible.",1300 ]1301 `);1302 });1303 it(`removes @inaccessible object field arguments`, () => {1304 const schema = buildSchema(`1305 ${INACCESSIBLE_V02_HEADER}1306 # Inaccessible object field argument in query type1307 type Query {1308 someField(privateArg: String @inaccessible): String1309 }1310 # Inaccessible object field argument in mutation type1311 type Mutation {1312 someField(privateArg: String @inaccessible): String1313 }1314 # Inaccessible object field argument in subscription type1315 type Subscription {1316 someField(privateArg: String @inaccessible): String1317 }1318 # Inaccessible (and non-inaccessible) object field argument1319 type Object implements Referencer1 & Referencer2 & Referencer3 {1320 someField(1321 someArg: String,1322 privateArg: String @inaccessible1323 ): String1324 someOtherField: Float1325 }1326 # Inaccessible object field argument referenced by inaccessible interface1327 # field argument1328 interface Referencer1 {1329 someField(1330 someArg: String,1331 privateArg: String @inaccessible1332 ): String1333 }1334 # Inaccessible object field argument referenced by non-inaccessible1335 # interface field argument with inaccessible parent1336 interface Referencer2 {1337 someField(1338 someArg: String,1339 privateArg: String1340 ): String @inaccessible1341 someOtherField: Float1342 }1343 # Inaccessible object field argument referenced by non-inaccessible1344 # interface field argument with inaccessible grandparent1345 interface Referencer3 @inaccessible {1346 someField(1347 someArg: String,1348 privateArg: String1349 ): String1350 }1351 # Inaccessible non-nullable object field argument with default1352 type ObjectDefault {1353 someField(privateArg: String! = "default" @inaccessible): String1354 }1355 `);1356 removeInaccessibleElements(schema);1357 schema.validate();1358 expect(schema.elementByCoordinate("Query.someField")).toBeDefined();1359 expect(1360 schema.elementByCoordinate("Query.someField(privateArg:)")1361 ).toBeUndefined();1362 expect(schema.elementByCoordinate("Mutation.someField")).toBeDefined();1363 expect(1364 schema.elementByCoordinate("Mutation.someField(privateArg:)")1365 ).toBeUndefined();1366 expect(schema.elementByCoordinate("Subscription.someField")).toBeDefined();1367 expect(1368 schema.elementByCoordinate("Subscription.someField(privateArg:)")1369 ).toBeUndefined();1370 const objectType = schema.elementByCoordinate("Object");1371 expect(objectType instanceof ObjectType).toBeTruthy();1372 expect(1373 (objectType as ObjectType).implementsInterface("Referencer1")1374 ).toBeTruthy();1375 expect(1376 (objectType as ObjectType).implementsInterface("Referencer2")1377 ).toBeTruthy();1378 expect(1379 (objectType as ObjectType).implementsInterface("Referencer3")1380 ).toBeFalsy();1381 expect(1382 schema.elementByCoordinate("Object.someField(someArg:)")1383 ).toBeDefined();1384 expect(1385 schema.elementByCoordinate("Object.someField(privateArg:)")1386 ).toBeUndefined();1387 expect(schema.elementByCoordinate("Referencer1.someField")).toBeDefined();1388 expect(1389 schema.elementByCoordinate("Referencer1.someField(privateArg:)")1390 ).toBeUndefined();1391 expect(schema.elementByCoordinate("Referencer2")).toBeDefined();1392 expect(schema.elementByCoordinate("Referencer2.someField")).toBeUndefined();1393 expect(schema.elementByCoordinate("Referencer3")).toBeUndefined();1394 expect(schema.elementByCoordinate("ObjectDefault.someField")).toBeDefined();1395 expect(1396 schema.elementByCoordinate("ObjectDefault.someField(privateArg:)")1397 ).toBeUndefined();1398 });1399 it(`fails to remove @inaccessible object field arguments for breaking removals`, () => {1400 const schema = buildSchema(`1401 ${INACCESSIBLE_V02_HEADER}1402 type Query {1403 someField(someArg: String): String1404 }1405 # Inaccessible object field argument1406 type Object implements Referencer1 {1407 someField(privateArg: String @inaccessible): String1408 }1409 # Inaccessible object field argument can't be referenced by interface1410 # field argument in the API schema1411 interface Referencer1 {1412 someField(privateArg: String): String1413 }1414 # Inaccessible object field argument can't be a required argument1415 type ObjectRequired {1416 someField(privateArg: String! @inaccessible): String1417 }1418 `);1419 const errorMessages = expectErrors(2, () => {1420 removeInaccessibleElements(schema);1421 });1422 expect(errorMessages).toMatchInlineSnapshot(`1423 Array [1424 "Argument \\"Object.someField(privateArg:)\\" is @inaccessible but implements the interface argument \\"Referencer1.someField(privateArg:)\\", which is in the API schema.",1425 "Argument \\"ObjectRequired.someField(privateArg:)\\" is @inaccessible but is a required argument of its field.",1426 ]1427 `);1428 });1429 it(`removes @inaccessible interface field arguments`, () => {1430 const schema = buildSchema(`1431 ${INACCESSIBLE_V02_HEADER}1432 type Query {1433 someField: String1434 }1435 # Inaccessible (and non-inaccessible) interface field argument1436 interface Interface implements Referencer1 & Referencer2 & Referencer3 {1437 someField(1438 someArg: String,1439 privateArg: String @inaccessible1440 ): String1441 someOtherField: Float1442 }1443 # Inaccessible interface field argument referenced by inaccessible1444 # interface field argument1445 interface Referencer1 {1446 someField(1447 someArg: String,1448 privateArg: String @inaccessible1449 ): String1450 }1451 # Inaccessible interface field argument referenced by non-inaccessible1452 # interface field argument with inaccessible parent1453 interface Referencer2 {1454 someField(1455 someArg: String,1456 privateArg: String1457 ): String @inaccessible1458 someOtherField: Float1459 }1460 # Inaccessible interface field argument referenced by non-inaccessible1461 # interface field argument with inaccessible grandparent1462 interface Referencer3 @inaccessible {1463 someField(1464 someArg: String,1465 privateArg: String1466 ): String1467 }1468 # Inaccessible non-nullable interface field argument with default1469 interface InterfaceDefault {1470 someField(privateArg: String! = "default" @inaccessible): String1471 }1472 # Inaccessible interface field argument referenced by non-inaccessible1473 # non-required object field argument1474 type Referencer4 implements InterfaceDefault {1475 someField(privateArg: String! = "default"): String1476 }1477 # Inaccessible interface field argument referenced by non-inaccessible1478 # required object field argument with inaccessible grandparent1479 type Referencer5 implements InterfaceDefault @inaccessible {1480 someField(privateArg: String!): String1481 }1482 # Inaccessible interface field argument referenced by non-inaccessible1483 # non-required interface field argument1484 interface Referencer6 implements InterfaceDefault {1485 someField(privateArg: String! = "default"): String1486 }1487 # Inaccessible interface field argument referenced by non-inaccessible1488 # required interface field argument with inaccessible grandparent1489 interface Referencer7 implements InterfaceDefault @inaccessible {1490 someField(privateArg: String!): String1491 }1492 `);1493 removeInaccessibleElements(schema);1494 schema.validate();1495 const interfaceType = schema.elementByCoordinate("Interface");1496 expect(interfaceType instanceof InterfaceType).toBeTruthy();1497 expect(1498 (interfaceType as InterfaceType).implementsInterface("Referencer1")1499 ).toBeTruthy();1500 expect(1501 (interfaceType as InterfaceType).implementsInterface("Referencer2")1502 ).toBeTruthy();1503 expect(1504 (interfaceType as InterfaceType).implementsInterface("Referencer3")1505 ).toBeFalsy();1506 expect(1507 schema.elementByCoordinate("Interface.someField(someArg:)")1508 ).toBeDefined();1509 expect(1510 schema.elementByCoordinate("Interface.someField(privateArg:)")1511 ).toBeUndefined();1512 expect(schema.elementByCoordinate("Referencer1.someField")).toBeDefined();1513 expect(1514 schema.elementByCoordinate("Referencer1.someField(privateArg:)")1515 ).toBeUndefined();1516 expect(schema.elementByCoordinate("Referencer2")).toBeDefined();1517 expect(schema.elementByCoordinate("Referencer2.someField")).toBeUndefined();1518 expect(schema.elementByCoordinate("Referencer3")).toBeUndefined();1519 expect(schema.elementByCoordinate("Interface.someField")).toBeDefined();1520 expect(1521 schema.elementByCoordinate("Interface.someField(privateArg:)")1522 ).toBeUndefined();1523 const objectArg = schema.elementByCoordinate(1524 "Referencer4.someField(privateArg:)"1525 );1526 expect(objectArg instanceof ArgumentDefinition).toBeTruthy();1527 expect(1528 (1529 objectArg as ArgumentDefinition<FieldDefinition<ObjectType>>1530 ).isRequired()1531 ).toBeFalsy();1532 expect(schema.elementByCoordinate("Referencer5")).toBeUndefined();1533 const interfaceArg = schema.elementByCoordinate(1534 "Referencer6.someField(privateArg:)"1535 );1536 expect(interfaceArg instanceof ArgumentDefinition).toBeTruthy();1537 expect(1538 (1539 interfaceArg as ArgumentDefinition<FieldDefinition<InterfaceType>>1540 ).isRequired()1541 ).toBeFalsy();1542 expect(schema.elementByCoordinate("Referencer7")).toBeUndefined();1543 });1544 it(`fails to remove @inaccessible interface field arguments for breaking removals`, () => {1545 const schema = buildSchema(`1546 ${INACCESSIBLE_V02_HEADER}1547 type Query {1548 someField(someArg: String): String1549 }1550 # Inaccessible interface field argument1551 interface Interface implements Referencer1 {1552 someField(privateArg: String! = "default" @inaccessible): String1553 }1554 # Inaccessible interface field argument can't be referenced by interface1555 # field argument in the API schema1556 interface Referencer1 {1557 someField(privateArg: String! = "default"): String1558 }1559 # Inaccessible object field argument can't be a required argument1560 type InterfaceRequired {1561 someField(privateArg: String! @inaccessible): String1562 }1563 # Inaccessible object field argument can't be implemented by a required1564 # object field argument in the API schema1565 type Referencer2 implements Interface & Referencer1 {1566 someField(privateArg: String!): String1567 }1568 # Inaccessible object field argument can't be implemented by a required1569 # interface field argument in the API schema1570 interface Referencer3 implements Interface & Referencer1 {1571 someField(privateArg: String!): String1572 }1573 `);1574 const errorMessages = expectErrors(4, () => {1575 removeInaccessibleElements(schema);1576 });1577 expect(errorMessages).toMatchInlineSnapshot(`1578 Array [1579 "Argument \\"Interface.someField(privateArg:)\\" is @inaccessible but implements the interface argument \\"Referencer1.someField(privateArg:)\\", which is in the API schema.",1580 "Argument \\"Interface.someField(privateArg:)\\" is @inaccessible but is implemented by the required argument \\"Referencer2.someField(privateArg:)\\", which is in the API schema.",1581 "Argument \\"Interface.someField(privateArg:)\\" is @inaccessible but is implemented by the required argument \\"Referencer3.someField(privateArg:)\\", which is in the API schema.",1582 "Argument \\"InterfaceRequired.someField(privateArg:)\\" is @inaccessible but is a required argument of its field.",1583 ]1584 `);1585 });1586 it(`removes @inaccessible input object fields`, () => {1587 const schema = buildSchema(`1588 ${INACCESSIBLE_V02_HEADER}1589 type Query {1590 someField: String1591 }1592 # Inaccessible (and non-inaccessible) input object field1593 input InputObject {1594 someField: String1595 privateField: String @inaccessible1596 }1597 # Inaccessible input object field referenced by default value of1598 # inaccessible object field argument1599 type Referencer1 implements Referencer4 {1600 someField(1601 privateArg: InputObject = { privateField: "" } @inaccessible1602 ): String1603 }1604 # Inaccessible input object field referenced by default value of1605 # non-inaccessible object field argument with inaccessible parent1606 type Referencer2 implements Referencer5 {1607 someField: String1608 privateField(1609 privateArg: InputObject! = { privateField: "" }1610 ): String @inaccessible1611 }1612 # Inaccessible input object field referenced by default value of1613 # non-inaccessible object field argument with inaccessible grandparent1614 type Referencer3 implements Referencer6 @inaccessible {1615 privateField(privateArg: InputObject! = { privateField: "" }): String1616 }1617 # Inaccessible input object field referenced by default value of1618 # inaccessible interface field argument1619 interface Referencer4 {1620 someField(1621 privateArg: InputObject = { privateField: "" } @inaccessible1622 ): String1623 }1624 # Inaccessible input object field referenced by default value of1625 # non-inaccessible interface field argument with inaccessible parent1626 interface Referencer5 {1627 someField: String1628 privateField(1629 privateArg: InputObject! = { privateField: "" }1630 ): String @inaccessible1631 }1632 # Inaccessible input object field referenced by default value of1633 # non-inaccessible interface field argument with inaccessible grandparent1634 interface Referencer6 @inaccessible {1635 privateField(privateArg: InputObject! = { privateField: "" }): String1636 }1637 # Inaccessible input object field referenced by default value of1638 # inaccessible input object field1639 input Referencer7 {1640 someField: String1641 privateField: InputObject = { privateField: "" } @inaccessible1642 }1643 # Inaccessible input object field referenced by default value of1644 # non-inaccessible input object field with inaccessible parent1645 input Referencer8 @inaccessible {1646 privateField: InputObject! = { privateField: "" }1647 }1648 # Inaccessible input object field referenced by default value of1649 # inaccessible directive argument1650 directive @referencer9(1651 privateArg: InputObject = { privateField: "" } @inaccessible1652 ) on SUBSCRIPTION1653 # Inaccessible input object field not referenced (but type is referenced)1654 # by default value of object field argument in the API schema1655 type Referencer10 {1656 someField(privateArg: InputObject = { someField: "" }): String1657 }1658 # Inaccessible input object field with an inaccessible parent and no1659 # non-inaccessible siblings1660 input Referencer11 @inaccessible {1661 privateField: String @inaccessible1662 otherPrivateField: Float @inaccessible1663 }1664 # Inaccessible non-nullable input object field with default1665 input InputObjectDefault {1666 someField: String1667 privateField: String! = "default" @inaccessible1668 }1669 `);1670 removeInaccessibleElements(schema);1671 schema.validate();1672 expect(schema.elementByCoordinate("InputObject.someField")).toBeDefined();1673 expect(1674 schema.elementByCoordinate("InputObject.privateField")1675 ).toBeUndefined();1676 expect(schema.elementByCoordinate("Referencer1.someField")).toBeDefined();1677 expect(1678 schema.elementByCoordinate("Referencer1.someField(privateArg:)")1679 ).toBeUndefined();1680 expect(schema.elementByCoordinate("Referencer2.someField")).toBeDefined();1681 expect(1682 schema.elementByCoordinate("Referencer2.privateField")1683 ).toBeUndefined();1684 expect(schema.elementByCoordinate("Referencer3")).toBeUndefined();1685 expect(schema.elementByCoordinate("Referencer4.someField")).toBeDefined();1686 expect(1687 schema.elementByCoordinate("Referencer4.someField(privateArg:)")1688 ).toBeUndefined();1689 expect(schema.elementByCoordinate("Referencer5.someField")).toBeDefined();1690 expect(1691 schema.elementByCoordinate("Referencer5.privateField")1692 ).toBeUndefined();1693 expect(schema.elementByCoordinate("Referencer6")).toBeUndefined();1694 expect(schema.elementByCoordinate("Referencer7.someField")).toBeDefined();1695 expect(1696 schema.elementByCoordinate("Referencer7.privatefield")1697 ).toBeUndefined();1698 expect(schema.elementByCoordinate("Referencer8")).toBeUndefined();1699 expect(schema.elementByCoordinate("@referencer9")).toBeDefined();1700 expect(1701 schema.elementByCoordinate("@referencer9(privateArg:)")1702 ).toBeUndefined();1703 expect(1704 schema.elementByCoordinate("Referencer10.someField(privateArg:)")1705 ).toBeDefined();1706 expect(schema.elementByCoordinate("Referencer11")).toBeUndefined();1707 expect(1708 schema.elementByCoordinate("InputObjectDefault.someField")1709 ).toBeDefined();1710 expect(1711 schema.elementByCoordinate("InputObjectDefault.privatefield")1712 ).toBeUndefined();1713 });1714 it(`fails to remove @inaccessible input object fields for breaking removals`, () => {1715 const schema = buildSchema(`1716 ${INACCESSIBLE_V02_HEADER}1717 type Query {1718 someField: String1719 }1720 # Inaccessible input object field1721 input InputObject {1722 someField: String1723 privateField: String @inaccessible1724 }1725 # Inaccessible input object field can't be referenced by default value of1726 # object field argument in the API schema1727 type Referencer1 implements Referencer2 {1728 someField(someArg: InputObject = { privateField: "" }): String1729 }1730 # Inaccessible input object field can't be referenced by default value of1731 # interface field argument in the API schema1732 interface Referencer2 {1733 someField(someArg: InputObject = { privateField: "" }): String1734 }1735 # Inaccessible input object field can't be referenced by default value of1736 # input object field in the API schema1737 input Referencer3 {1738 someField: InputObject = { privateField: "" }1739 }1740 # Inaccessible input object field can't be referenced by default value of1741 # directive argument in the API schema1742 directive @referencer4(1743 someArg: InputObject = { privateField: "" }1744 ) on FIELD1745 # Inaccessible input object field can't have a non-inaccessible parent1746 # and no non-inaccessible siblings1747 input Referencer5 {1748 privateField: String @inaccessible1749 otherPrivateField: Float @inaccessible1750 }1751 # Inaccessible input object field can't be a required field1752 input InputObjectRequired {1753 someField: String1754 privateField: String! @inaccessible1755 }1756 `);1757 const errorMessages = expectErrors(6, () => {1758 removeInaccessibleElements(schema);1759 });1760 expect(errorMessages).toMatchInlineSnapshot(`1761 Array [1762 "Input field \\"InputObject.privateField\\" is @inaccessible but is used in the default value of \\"@referencer4(someArg:)\\", which is in the API schema.",1763 "Input field \\"InputObject.privateField\\" is @inaccessible but is used in the default value of \\"Referencer1.someField(someArg:)\\", which is in the API schema.",1764 "Input field \\"InputObject.privateField\\" is @inaccessible but is used in the default value of \\"Referencer2.someField(someArg:)\\", which is in the API schema.",1765 "Input field \\"InputObject.privateField\\" is @inaccessible but is used in the default value of \\"Referencer3.someField\\", which is in the API schema.",1766 "Input field \\"InputObjectRequired.privateField\\" is @inaccessible but is a required input field of its type.",1767 "Type \\"Referencer5\\" is in the API schema but all of its input fields are @inaccessible.",1768 ]1769 `);1770 });1771 it(`removes @inaccessible enum values`, () => {1772 const schema = buildSchema(`1773 ${INACCESSIBLE_V02_HEADER}1774 type Query {1775 someField: String1776 }1777 # Inaccessible (and non-inaccessible) enum value1778 enum Enum {1779 SOME_VALUE1780 PRIVATE_VALUE @inaccessible1781 }1782 # Inaccessible enum value referenced by default value of inaccessible1783 # object field argument1784 type Referencer1 implements Referencer4 {1785 someField(1786 privateArg: Enum = PRIVATE_VALUE @inaccessible1787 ): String1788 }1789 # Inaccessible enum value referenced by default value of non-inaccessible1790 # object field argument with inaccessible parent1791 type Referencer2 implements Referencer5 {1792 someField: String1793 privateField(1794 privateArg: Enum! = PRIVATE_VALUE1795 ): String @inaccessible1796 }1797 # Inaccessible enum value referenced by default value of non-inaccessible1798 # object field argument with inaccessible grandparent1799 type Referencer3 implements Referencer6 @inaccessible {1800 privateField(privateArg: Enum! = PRIVATE_VALUE): String1801 }1802 # Inaccessible enum value referenced by default value of inaccessible1803 # interface field argument1804 interface Referencer4 {1805 someField(1806 privateArg: Enum = PRIVATE_VALUE @inaccessible1807 ): String1808 }1809 # Inaccessible enum value referenced by default value of non-inaccessible1810 # interface field argument with inaccessible parent1811 interface Referencer5 {1812 someField: String1813 privateField(1814 privateArg: Enum! = PRIVATE_VALUE1815 ): String @inaccessible1816 }1817 # Inaccessible enum value referenced by default value of non-inaccessible1818 # interface field argument with inaccessible grandparent1819 interface Referencer6 @inaccessible {1820 privateField(privateArg: Enum! = PRIVATE_VALUE): String1821 }1822 # Inaccessible enum value referenced by default value of inaccessible1823 # input object field1824 input Referencer7 {1825 someField: String1826 privateField: Enum = PRIVATE_VALUE @inaccessible1827 }1828 # Inaccessible enum value referenced by default value of non-inaccessible1829 # input object field with inaccessible parent1830 input Referencer8 @inaccessible {1831 privateField: Enum! = PRIVATE_VALUE1832 }1833 # Inaccessible enum value referenced by default value of inaccessible1834 # directive argument1835 directive @referencer9(1836 privateArg: Enum = PRIVATE_VALUE @inaccessible1837 ) on FRAGMENT_SPREAD1838 # Inaccessible enum value not referenced (but type is referenced) by1839 # default value of object field argument in the API schema1840 type Referencer10 {1841 someField(privateArg: Enum = SOME_VALUE): String1842 }1843 # Inaccessible enum value with an inaccessible parent and no1844 # non-inaccessible siblings1845 enum Referencer11 @inaccessible {1846 PRIVATE_VALUE @inaccessible1847 OTHER_PRIVATE_VALUE @inaccessible1848 }1849 `);1850 removeInaccessibleElements(schema);1851 schema.validate();1852 expect(schema.elementByCoordinate("Enum.SOME_VALUE")).toBeDefined();1853 expect(schema.elementByCoordinate("Enum.PRIVATE_VALUE")).toBeUndefined();1854 expect(schema.elementByCoordinate("Referencer1.someField")).toBeDefined();1855 expect(1856 schema.elementByCoordinate("Referencer1.someField(privateArg:)")1857 ).toBeUndefined();1858 expect(schema.elementByCoordinate("Referencer2.someField")).toBeDefined();1859 expect(1860 schema.elementByCoordinate("Referencer2.privateField")1861 ).toBeUndefined();1862 expect(schema.elementByCoordinate("Referencer3")).toBeUndefined();1863 expect(schema.elementByCoordinate("Referencer4.someField")).toBeDefined();1864 expect(1865 schema.elementByCoordinate("Referencer4.someField(privateArg:)")1866 ).toBeUndefined();1867 expect(schema.elementByCoordinate("Referencer5.someField")).toBeDefined();1868 expect(1869 schema.elementByCoordinate("Referencer5.privateField")1870 ).toBeUndefined();1871 expect(schema.elementByCoordinate("Referencer6")).toBeUndefined();1872 expect(schema.elementByCoordinate("Referencer7.someField")).toBeDefined();1873 expect(1874 schema.elementByCoordinate("Referencer7.privatefield")1875 ).toBeUndefined();1876 expect(schema.elementByCoordinate("Referencer8")).toBeUndefined();1877 expect(schema.elementByCoordinate("@referencer9")).toBeDefined();1878 expect(1879 schema.elementByCoordinate("@referencer9(privateArg:)")1880 ).toBeUndefined();1881 expect(1882 schema.elementByCoordinate("Referencer10.someField(privateArg:)")1883 ).toBeDefined();1884 expect(schema.elementByCoordinate("Referencer11")).toBeUndefined();1885 });1886 it(`fails to remove @inaccessible enum values for breaking removals`, () => {1887 const schema = buildSchema(`1888 ${INACCESSIBLE_V02_HEADER}1889 type Query {1890 someField: String1891 }1892 # Inaccessible enum value1893 enum Enum {1894 SOME_VALUE1895 PRIVATE_VALUE @inaccessible1896 }1897 # Inaccessible enum value can't be referenced by default value of object1898 # field argument in the API schema1899 type Referencer1 implements Referencer2 {1900 someField(someArg: Enum = PRIVATE_VALUE): String1901 }1902 # Inaccessible enum value can't be referenced by default value of1903 # interface field argument in the API schema1904 interface Referencer2 {1905 someField(someArg: Enum = PRIVATE_VALUE): String1906 }1907 # Inaccessible enum value can't be referenced by default value of input1908 # object field in the API schema1909 input Referencer3 {1910 someField: Enum = PRIVATE_VALUE1911 }1912 # Inaccessible input enum value can't be referenced by default value of1913 # directive argument in the API schema1914 directive @referencer4(someArg: Enum = PRIVATE_VALUE) on INLINE_FRAGMENT1915 # Inaccessible enum value can't have a non-inaccessible parent and no1916 # non-inaccessible siblings1917 enum Referencer5 {1918 PRIVATE_VALUE @inaccessible1919 OTHER_PRIVATE_VALUE @inaccessible1920 }1921 `);1922 const errorMessages = expectErrors(5, () => {1923 removeInaccessibleElements(schema);1924 });1925 expect(errorMessages).toMatchInlineSnapshot(`1926 Array [1927 "Enum value \\"Enum.PRIVATE_VALUE\\" is @inaccessible but is used in the default value of \\"@referencer4(someArg:)\\", which is in the API schema.",1928 "Enum value \\"Enum.PRIVATE_VALUE\\" is @inaccessible but is used in the default value of \\"Referencer1.someField(someArg:)\\", which is in the API schema.",1929 "Enum value \\"Enum.PRIVATE_VALUE\\" is @inaccessible but is used in the default value of \\"Referencer2.someField(someArg:)\\", which is in the API schema.",1930 "Enum value \\"Enum.PRIVATE_VALUE\\" is @inaccessible but is used in the default value of \\"Referencer3.someField\\", which is in the API schema.",1931 "Type \\"Referencer5\\" is in the API schema but all of its values are @inaccessible.",1932 ]1933 `);1934 });1935 it(`removes @inaccessible directive arguments`, () => {1936 const schema = buildSchema(`1937 ${INACCESSIBLE_V02_HEADER}1938 type Query {1939 someField: String1940 }1941 # Inaccessible (and non-inaccessible) directive argument1942 directive @directive(1943 someArg: String1944 privateArg: String @inaccessible1945 ) on QUERY1946 # Inaccessible non-nullable directive argument with default1947 directive @directiveDefault(1948 someArg: String1949 privateArg: String! = "default" @inaccessible1950 ) on MUTATION1951 `);1952 removeInaccessibleElements(schema);1953 schema.validate();1954 expect(schema.elementByCoordinate("@directive(someArg:)")).toBeDefined();1955 expect(1956 schema.elementByCoordinate("@directive(privateArg:)")1957 ).toBeUndefined();1958 expect(1959 schema.elementByCoordinate("@directiveDefault(someArg:)")1960 ).toBeDefined();1961 expect(1962 schema.elementByCoordinate("@directiveDefault(privateArg:)")1963 ).toBeUndefined();1964 });1965 it(`fails to remove @inaccessible directive arguments for breaking removals`, () => {1966 const schema = buildSchema(`1967 ${INACCESSIBLE_V02_HEADER}1968 type Query {1969 someField: String1970 }1971 # Inaccessible directive argument1972 directive @directive(privateArg: String @inaccessible) on SUBSCRIPTION1973 # Inaccessible directive argument can't be a required field1974 directive @directiveRequired(1975 someArg: String1976 privateArg: String! @inaccessible1977 ) on FRAGMENT_DEFINITION1978 `);1979 const errorMessages = expectErrors(1, () => {1980 removeInaccessibleElements(schema);1981 });1982 expect(errorMessages).toMatchInlineSnapshot(`1983 Array [1984 "Argument \\"@directiveRequired(privateArg:)\\" is @inaccessible but is a required argument of its directive.",1985 ]1986 `);1987 });1988 it(`handles complex default values`, () => {1989 const schema = buildSchema(`1990 ${INACCESSIBLE_V02_HEADER}1991 type Query {1992 someField(arg1: [[RootInputObject!]]! = [1993 {1994 foo: {1995 # 2 references (with nesting)1996 privateField: [PRIVATE_VALUE]1997 }1998 bar: SOME_VALUE1999 # 0 references since scalar2000 baz: { privateField: PRIVATE_VALUE }2001 },2002 [{2003 foo: [{2004 someField: "foo"2005 }]2006 # 1 reference2007 bar: PRIVATE_VALUE2008 }]2009 ]): String2010 }2011 input RootInputObject {2012 foo: [NestedInputObject]2013 bar: Enum!2014 baz: Scalar! = { default: 4 }2015 }2016 input NestedInputObject {2017 someField: String2018 privateField: [Enum!] @inaccessible2019 }2020 enum Enum {2021 SOME_VALUE2022 PRIVATE_VALUE @inaccessible2023 }2024 scalar Scalar2025 `);2026 const errorMessages = expectErrors(3, () => {2027 removeInaccessibleElements(schema);2028 });2029 expect(errorMessages).toMatchInlineSnapshot(`2030 Array [2031 "Enum value \\"Enum.PRIVATE_VALUE\\" is @inaccessible but is used in the default value of \\"Query.someField(arg1:)\\", which is in the API schema.",2032 "Enum value \\"Enum.PRIVATE_VALUE\\" is @inaccessible but is used in the default value of \\"Query.someField(arg1:)\\", which is in the API schema.",2033 "Input field \\"NestedInputObject.privateField\\" is @inaccessible but is used in the default value of \\"Query.someField(arg1:)\\", which is in the API schema.",2034 ]2035 `);2036 });2037 // It's not GraphQL-spec-compliant to allow a string for an enum value, but2038 // since we're allowing it, we need to make sure this logic keeps working2039 // until we're allowed to make breaking changes and remove it.2040 it(`handles string enum value in default value`, () => {2041 const schema = buildSchema(`2042 ${INACCESSIBLE_V02_HEADER}2043 type Query {2044 someField(arg1: Enum! = "PRIVATE_VALUE"): String2045 }2046 enum Enum {2047 SOME_VALUE2048 PRIVATE_VALUE @inaccessible2049 }2050 `);2051 const errorMessages = expectErrors(1, () => {2052 removeInaccessibleElements(schema);2053 });2054 expect(errorMessages).toMatchInlineSnapshot(`2055 Array [2056 "Enum value \\"Enum.PRIVATE_VALUE\\" is @inaccessible but is used in the default value of \\"Query.someField(arg1:)\\", which is in the API schema.",2057 ]2058 `);2059 });2060 it(`fails to remove @inaccessible non-core feature elements referenced by core feature elements`, () => {2061 const schema = buildSchema(`2062 directive @core(feature: String!, as: String, for: core__Purpose) repeatable on SCHEMA2063 enum core__Purpose {2064 EXECUTION2065 SECURITY2066 }2067 directive @inaccessible on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION2068 schema2069 @core(feature: "https://specs.apollo.dev/core/v0.2")2070 @core(feature: "https://specs.apollo.dev/inaccessible/v0.2")2071 @core(feature: "http://localhost/foo/v1.0")2072 {2073 query: Query2074 }2075 type Query {2076 someField: String2077 }2078 # Inaccessible input object field2079 input InputObject {2080 someField: String2081 privateField: String @inaccessible2082 }2083 # Inaccessible input object field can't be referenced by default value of2084 # directive argument of a core feature element2085 directive @foo__referencer(2086 someArg: InputObject = { privateField: "" }2087 ) on FIELD2088 `);2089 const errorMessages = expectErrors(1, () => {2090 removeInaccessibleElements(schema);2091 });2092 expect(errorMessages).toMatchInlineSnapshot(`2093 Array [2094 "Input field \\"InputObject.privateField\\" is @inaccessible but is used in the default value of \\"@foo__referencer(someArg:)\\", which is in the API schema.",2095 ]2096 `);2097 });...

Full Screen

Full Screen

inaccessibleSpec.ts

Source:inaccessibleSpec.ts Github

copy

Full Screen

1import { CorePurpose, FeatureDefinition, FeatureDefinitions, FeatureUrl, FeatureVersion } from "./coreSpec";2import {3 ArgumentDefinition,4 CoreFeatures,5 DirectiveDefinition,6 EnumType,7 EnumValue,8 ErrGraphQLAPISchemaValidationFailed,9 FieldDefinition,10 InputFieldDefinition,11 InputObjectType,12 InputType,13 InterfaceType,14 isEnumType,15 isInputObjectType,16 isListType,17 isNonNullType,18 isScalarType,19 isTypeSystemDirectiveLocation,20 isVariable,21 NamedType,22 ObjectType,23 ScalarType,24 Schema,25 SchemaDefinition,26 SchemaElement,27 UnionType,28} from "./definitions";29import { GraphQLError, DirectiveLocation } from "graphql";30import { registerKnownFeature } from "./knownCoreFeatures";31import { ERRORS } from "./error";32import { createDirectiveSpecification, DirectiveSpecification } from "./directiveAndTypeSpecification";33import { assert } from "./utils";34export const inaccessibleIdentity = 'https://specs.apollo.dev/inaccessible';35export class InaccessibleSpecDefinition extends FeatureDefinition {36 public readonly inaccessibleLocations: DirectiveLocation[];37 public readonly inaccessibleDirectiveSpec: DirectiveSpecification;38 private readonly printedInaccessibleDefinition: string;39 constructor(version: FeatureVersion) {40 super(new FeatureUrl(inaccessibleIdentity, 'inaccessible', version));41 this.inaccessibleLocations = [42 DirectiveLocation.FIELD_DEFINITION,43 DirectiveLocation.OBJECT,44 DirectiveLocation.INTERFACE,45 DirectiveLocation.UNION,46 ];47 this.printedInaccessibleDefinition = 'directive @inaccessible on FIELD_DEFINITION | INTERFACE | OBJECT | UNION';48 if (!this.isV01()) {49 this.inaccessibleLocations.push(50 DirectiveLocation.ARGUMENT_DEFINITION,51 DirectiveLocation.SCALAR,52 DirectiveLocation.ENUM,53 DirectiveLocation.ENUM_VALUE,54 DirectiveLocation.INPUT_OBJECT,55 DirectiveLocation.INPUT_FIELD_DEFINITION,56 );57 this.printedInaccessibleDefinition = 'directive @inaccessible on FIELD_DEFINITION | INTERFACE | OBJECT | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION';58 }59 this.inaccessibleDirectiveSpec = createDirectiveSpecification({60 name: 'inaccessible',61 locations: this.inaccessibleLocations,62 });63 }64 isV01() {65 return this.version.equals(new FeatureVersion(0, 1));66 }67 addElementsToSchema(schema: Schema): GraphQLError[] {68 return this.addDirectiveSpec(schema, this.inaccessibleDirectiveSpec);69 }70 inaccessibleDirective(schema: Schema): DirectiveDefinition<Record<string, never>> | undefined {71 return this.directive(schema, 'inaccessible');72 }73 checkCompatibleDirective(definition: DirectiveDefinition): GraphQLError | undefined {74 const hasUnknownArguments = Object.keys(definition.arguments()).length > 0;75 const hasRepeatable = definition.repeatable;76 const hasValidLocations = definition.locations.every(loc => this.inaccessibleLocations.includes(loc));77 if (hasUnknownArguments || hasRepeatable || !hasValidLocations) {78 return ERRORS.DIRECTIVE_DEFINITION_INVALID.err(79 `Found invalid @inaccessible directive definition. Please ensure the directive definition in your schema's definitions matches the following:\n\t${this.printedInaccessibleDefinition}`,80 );81 }82 return undefined;83 }84 allElementNames(): string[] {85 return ['@inaccessible'];86 }87 get defaultCorePurpose(): CorePurpose | undefined {88 return 'SECURITY';89 }90}91export const INACCESSIBLE_VERSIONS = new FeatureDefinitions<InaccessibleSpecDefinition>(inaccessibleIdentity)92 .add(new InaccessibleSpecDefinition(new FeatureVersion(0, 1)))93 .add(new InaccessibleSpecDefinition(new FeatureVersion(0, 2)));94registerKnownFeature(INACCESSIBLE_VERSIONS);95export function removeInaccessibleElements(schema: Schema) {96 // Note it doesn't hurt to validate here, since we expect the schema to be97 // validated already, and if it has been, it's cached/inexpensive.98 schema.validate();99 const coreFeatures = schema.coreFeatures;100 if (!coreFeatures) {101 return;102 }103 const inaccessibleFeature = coreFeatures.getByIdentity(inaccessibleIdentity);104 if (!inaccessibleFeature) {105 return;106 }107 const inaccessibleSpec = INACCESSIBLE_VERSIONS.find(108 inaccessibleFeature.url.version109 );110 if (!inaccessibleSpec) {111 throw ErrGraphQLAPISchemaValidationFailed([new GraphQLError(112 `Cannot remove inaccessible elements: the schema uses unsupported` +113 ` inaccessible spec version ${inaccessibleFeature.url.version}` +114 ` (supported versions: ${INACCESSIBLE_VERSIONS.versions().join(', ')})`115 )]);116 }117 const inaccessibleDirective = inaccessibleSpec.inaccessibleDirective(schema);118 if (!inaccessibleDirective) {119 throw ErrGraphQLAPISchemaValidationFailed([new GraphQLError(120 `Invalid schema: declares ${inaccessibleSpec.url} spec but does not` +121 ` define a @inaccessible directive.`122 )]);123 }124 const incompatibleError =125 inaccessibleSpec.checkCompatibleDirective(inaccessibleDirective);126 if (incompatibleError) {127 throw ErrGraphQLAPISchemaValidationFailed([incompatibleError]);128 }129 validateInaccessibleElements(130 schema,131 coreFeatures,132 inaccessibleSpec,133 inaccessibleDirective,134 );135 removeInaccessibleElementsAssumingValid(136 schema,137 inaccessibleDirective,138 )139}140// These are elements that may be hidden, by either @inaccessible or core141// feature definition hiding.142type HideableElement =143 | ObjectType144 | InterfaceType145 | UnionType146 | ScalarType147 | EnumType148 | InputObjectType149 | DirectiveDefinition150 | FieldDefinition<ObjectType | InterfaceType>151 | ArgumentDefinition<152 | DirectiveDefinition153 | FieldDefinition<ObjectType | InterfaceType>>154 | InputFieldDefinition155 | EnumValue156// Validate the applications of @inaccessible in the schema. Some of these may157// technically be caught by Schema.validate() later, but we'd like to give158// clearer error messaging when possible.159function validateInaccessibleElements(160 schema: Schema,161 coreFeatures: CoreFeatures,162 inaccessibleSpec: InaccessibleSpecDefinition,163 inaccessibleDirective: DirectiveDefinition,164): void {165 function isInaccessible(element: SchemaElement<any, any>): boolean {166 return element.hasAppliedDirective(inaccessibleDirective);167 }168 const featureList = [...coreFeatures.allFeatures()];169 function isFeatureDefinition(170 element: NamedType | DirectiveDefinition171 ): boolean {172 return featureList.some((feature) => feature.isFeatureDefinition(element));173 }174 function isInAPISchema(element: HideableElement): boolean {175 // If this element is @inaccessible, it's not in the API schema.176 if (177 !(element instanceof DirectiveDefinition) &&178 isInaccessible(element)179 ) return false;180 if (181 (element instanceof ObjectType) ||182 (element instanceof InterfaceType) ||183 (element instanceof UnionType) ||184 (element instanceof ScalarType) ||185 (element instanceof EnumType) ||186 (element instanceof InputObjectType) ||187 (element instanceof DirectiveDefinition)188 ) {189 // These are top-level elements. If they're not @inaccessible, the only190 // way they won't be in the API schema is if they're definitions of some191 // core feature. However, we do intend on introducing mechanisms for192 // exposing core feature elements in the API schema in the near feature.193 // Because such mechanisms aren't completely nailed down yet, we opt to194 // pretend here that all core feature elements are in the API schema for195 // simplicity sake.196 //197 // This has the effect that if a non-core schema element is referenced by198 // a core schema element, that non-core schema element can't be marked199 // @inaccessible, despite that the core schema element may likely not be200 // in the API schema. This may be relaxed in a later version of the201 // inaccessible spec.202 return true;203 } else if (204 (element instanceof FieldDefinition) ||205 (element instanceof ArgumentDefinition) ||206 (element instanceof InputFieldDefinition) ||207 (element instanceof EnumValue)208 ) {209 // While this element isn't marked @inaccessible, this element won't be in210 // the API schema if its parent isn't.211 return isInAPISchema(element.parent);212 }213 assert(false, "Unreachable code, element is of unknown type.");214 }215 function fetchInaccessibleElementsDeep(216 element: HideableElement217 ): HideableElement[] {218 const inaccessibleElements: HideableElement[] = [];219 if (isInaccessible(element)) {220 inaccessibleElements.push(element);221 }222 if (223 (element instanceof ObjectType) ||224 (element instanceof InterfaceType) ||225 (element instanceof InputObjectType)226 ) {227 for (const field of element.fields()) {228 inaccessibleElements.push(229 ...fetchInaccessibleElementsDeep(field),230 );231 }232 return inaccessibleElements;233 } else if (element instanceof EnumType) {234 for (const enumValue of element.values) {235 inaccessibleElements.push(236 ...fetchInaccessibleElementsDeep(enumValue),237 )238 }239 return inaccessibleElements;240 } else if (241 (element instanceof DirectiveDefinition) ||242 (element instanceof FieldDefinition)243 ) {244 for (const argument of element.arguments()) {245 inaccessibleElements.push(246 ...fetchInaccessibleElementsDeep(argument),247 )248 }249 return inaccessibleElements;250 } else if (251 (element instanceof UnionType) ||252 (element instanceof ScalarType) ||253 (element instanceof ArgumentDefinition) ||254 (element instanceof InputFieldDefinition) ||255 (element instanceof EnumValue)256 ) {257 return inaccessibleElements;258 }259 assert(false, "Unreachable code, element is of unknown type.");260 }261 const errors: GraphQLError[] = [];262 let defaultValueReferencers: Map<263 DefaultValueReference,264 SchemaElementWithDefaultValue[]265 > | undefined = undefined;266 if (!inaccessibleSpec.isV01()) {267 // Note that for inaccessible v0.1, enum values and input fields can't be268 // @inaccessible, so there's no need to compute references (the inaccessible269 // v0.1 spec also doesn't require default values to be valid, so it doesn't270 // make sense to compute them).271 defaultValueReferencers = computeDefaultValueReferencers(schema);272 }273 for (const type of schema.allTypes()) {274 if (hasBuiltInName(type)) {275 // Built-in types (and their descendants) aren't allowed to be276 // @inaccessible, regardless of shadowing.277 const inaccessibleElements = fetchInaccessibleElementsDeep(type);278 if (inaccessibleElements.length > 0) {279 errors.push(ERRORS.DISALLOWED_INACCESSIBLE.err(280 `Built-in type "${type.coordinate}" cannot use @inaccessible.`,281 {282 nodes: type.sourceAST,283 extensions: {284 inaccessible_elements: inaccessibleElements285 .map((element) => element.coordinate),286 inaccessible_referencers: [type.coordinate],287 }288 },289 ));290 }291 } else if (isFeatureDefinition(type)) {292 // Core feature types (and their descendants) aren't allowed to be293 // @inaccessible.294 const inaccessibleElements = fetchInaccessibleElementsDeep(type);295 if (inaccessibleElements.length > 0) {296 errors.push(ERRORS.DISALLOWED_INACCESSIBLE.err(297 `Core feature type "${type.coordinate}" cannot use @inaccessible.`,298 {299 nodes: type.sourceAST,300 extensions: {301 inaccessible_elements: inaccessibleElements302 .map((element) => element.coordinate),303 inaccessible_referencers: [type.coordinate],304 }305 },306 ));307 }308 } else if (isInaccessible(type)) {309 // Types can be referenced by other schema elements in a few ways:310 // 1. Fields, arguments, and input fields may have the type as their base311 // type.312 // 2. Union types may have the type as a member (for object types).313 // 3. Object and interface types may implement the type (for interface314 // types).315 // 4. Schemas may have the type as a root operation type (for object316 // types).317 //318 // When a type is hidden, the referencer must follow certain rules for the319 // schema to be valid. Respectively, these rules are:320 // 1. The field/argument/input field must not be in the API schema.321 // 2. The union type, if empty, must not be in the API schema.322 // 3. No rules are imposed in this case.323 // 4. The root operation type must not be the query type.324 //325 // We validate the 1st and 4th rules above, and leave the 2nd for when we326 // look at accessible union types.327 const referencers = type.referencers();328 for (const referencer of referencers) {329 if (330 referencer instanceof FieldDefinition ||331 referencer instanceof ArgumentDefinition ||332 referencer instanceof InputFieldDefinition333 ) {334 if (isInAPISchema(referencer)) {335 errors.push(ERRORS.REFERENCED_INACCESSIBLE.err(336 `Type "${type.coordinate}" is @inaccessible but is referenced` +337 ` by "${referencer.coordinate}", which is in the API schema.`,338 {339 nodes: type.sourceAST,340 extensions: {341 inaccessible_elements: [type.coordinate],342 inaccessible_referencers: [referencer.coordinate],343 }344 },345 ));346 }347 } else if (referencer instanceof SchemaDefinition) {348 if (type === referencer.rootType('query')) {349 errors.push(ERRORS.QUERY_ROOT_TYPE_INACCESSIBLE.err(350 `Type "${type.coordinate}" is @inaccessible but is the root` +351 ` query type, which must be in the API schema.`,352 {353 nodes: type.sourceAST,354 extensions: {355 inaccessible_elements: [type.coordinate],356 }357 },358 ));359 }360 }361 }362 } else {363 // At this point, we know the type must be in the API schema. For types364 // with children (all types except scalar), we check that at least one of365 // the children is accessible.366 if (367 (type instanceof ObjectType) ||368 (type instanceof InterfaceType) ||369 (type instanceof InputObjectType)370 ) {371 let isEmpty = true;372 for (const field of type.fields()) {373 if (!isInaccessible(field)) isEmpty = false;374 }375 if (isEmpty) {376 errors.push(ERRORS.ONLY_INACCESSIBLE_CHILDREN.err(377 `Type "${type.coordinate}" is in the API schema but all of its` +378 ` ${(type instanceof InputObjectType) ? 'input ' : ''}fields` +379 ` are @inaccessible.`,380 {381 nodes: type.sourceAST,382 extensions: {383 inaccessible_elements: type.fields()384 .map((field) => field.coordinate),385 inaccessible_referencers: [type.coordinate],386 }387 },388 ));389 }390 } else if (type instanceof UnionType) {391 let isEmpty = true;392 for (const member of type.types()) {393 if (!isInaccessible(member)) isEmpty = false;394 }395 if (isEmpty) {396 errors.push(ERRORS.ONLY_INACCESSIBLE_CHILDREN.err(397 `Type "${type.coordinate}" is in the API schema but all of its` +398 ` members are @inaccessible.`,399 {400 nodes: type.sourceAST,401 extensions: {402 inaccessible_elements: type.types()403 .map((type) => type.coordinate),404 inaccessible_referencers: [type.coordinate],405 }406 }407 ));408 }409 } else if (type instanceof EnumType) {410 let isEmpty = true;411 for (const enumValue of type.values) {412 if (!isInaccessible(enumValue)) isEmpty = false;413 }414 if (isEmpty) {415 errors.push(ERRORS.ONLY_INACCESSIBLE_CHILDREN.err(416 `Type "${type.coordinate}" is in the API schema but all of its` +417 ` values are @inaccessible.`,418 {419 nodes: type.sourceAST,420 extensions: {421 inaccessible_elements: type.values422 .map((enumValue) => enumValue.coordinate),423 inaccessible_referencers: [type.coordinate],424 }425 }426 ));427 }428 }429 // Descend into the type's children if needed.430 if (431 (type instanceof ObjectType) ||432 (type instanceof InterfaceType)433 ) {434 const implementedInterfaces = type.interfaces();435 const implementingTypes: (ObjectType | InterfaceType)[] = [];436 if (type instanceof InterfaceType) {437 for (const referencer of type.referencers()) {438 if (439 (referencer instanceof ObjectType) ||440 (referencer instanceof InterfaceType)441 ) {442 implementingTypes.push(referencer);443 }444 }445 }446 for (const field of type.fields()) {447 if (isInaccessible(field)) {448 // Fields can be "referenced" by the corresponding fields of any449 // interfaces their parent type implements. When a field is hidden450 // (but its parent isn't), we check that such implemented fields451 // aren't in the API schema.452 for (const implementedInterface of implementedInterfaces) {453 const implementedField = implementedInterface.field(field.name);454 if (implementedField && isInAPISchema(implementedField)) {455 errors.push(ERRORS.IMPLEMENTED_BY_INACCESSIBLE.err(456 `Field "${field.coordinate}" is @inaccessible but` +457 ` implements the interface field` +458 ` "${implementedField.coordinate}", which is in the API` +459 ` schema.`,460 {461 nodes: field.sourceAST,462 extensions: {463 inaccessible_elements: [field.coordinate],464 inaccessible_referencers: [implementedField.coordinate],465 }466 }467 ));468 }469 }470 } else {471 // Descend into the field's arguments.472 for (const argument of field.arguments()) {473 if (isInaccessible(argument)) {474 // When an argument is hidden (but its ancestors aren't), we475 // check that it isn't a required argument of its field.476 if (argument.isRequired()) {477 errors.push(ERRORS.REQUIRED_INACCESSIBLE.err(478 `Argument "${argument.coordinate}" is @inaccessible but` +479 ` is a required argument of its field.`,480 {481 nodes: argument.sourceAST,482 extensions: {483 inaccessible_elements: [argument.coordinate],484 inaccessible_referencers: [argument.coordinate],485 }486 },487 ));488 }489 // When an argument is hidden (but its ancestors aren't), we490 // check that it isn't a required argument of any implementing491 // fields in the API schema. This is because the GraphQL spec492 // requires that any arguments of an implementing field that493 // aren't in its implemented field are optional.494 //495 // You might be thinking that a required argument in an496 // implementing field would necessitate that the implemented497 // field would also require that argument (and thus the check498 // above would also always error, removing the need for this499 // one), but the GraphQL spec does not enforce this. E.g. it's500 // valid GraphQL for the implementing and implemented arguments501 // to be both non-nullable, but for just the implemented502 // argument to have a default value. Not providing a value for503 // the argument when querying the implemented type succeeds504 // GraphQL operation validation, but results in input coercion505 // failure for the field at runtime.506 for (const implementingType of implementingTypes) {507 const implementingField = implementingType.field(field.name);508 assert(509 implementingField,510 "Schema should have been valid, but an implementing type" +511 " did not implement one of this type's fields."512 );513 const implementingArgument = implementingField514 .argument(argument.name);515 assert(516 implementingArgument,517 "Schema should have been valid, but an implementing type" +518 " did not implement one of this type's field's arguments."519 );520 if (521 isInAPISchema(implementingArgument) &&522 implementingArgument.isRequired()523 ) {524 errors.push(ERRORS.REQUIRED_INACCESSIBLE.err(525 `Argument "${argument.coordinate}" is @inaccessible` +526 ` but is implemented by the required argument` +527 ` "${implementingArgument.coordinate}", which is` +528 ` in the API schema.`,529 {530 nodes: argument.sourceAST,531 extensions: {532 inaccessible_elements: [argument.coordinate],533 inaccessible_referencers: [534 implementingArgument.coordinate,535 ],536 }537 },538 ));539 }540 }541 // Arguments can be "referenced" by the corresponding arguments542 // of any interfaces their parent type implements. When an543 // argument is hidden (but its ancestors aren't), we check that544 // such implemented arguments aren't in the API schema.545 for (const implementedInterface of implementedInterfaces) {546 const implementedArgument = implementedInterface547 .field(field.name)548 ?.argument(argument.name);549 if (550 implementedArgument &&551 isInAPISchema(implementedArgument)552 ) {553 errors.push(ERRORS.IMPLEMENTED_BY_INACCESSIBLE.err(554 `Argument "${argument.coordinate}" is @inaccessible` +555 ` but implements the interface argument` +556 ` "${implementedArgument.coordinate}", which is in` +557 ` the API schema.`,558 {559 nodes: argument.sourceAST,560 extensions: {561 inaccessible_elements: [argument.coordinate],562 inaccessible_referencers: [563 implementedArgument.coordinate,564 ],565 }566 },567 ));568 }569 }570 }571 }572 }573 }574 } else if (type instanceof InputObjectType) {575 for (const inputField of type.fields()) {576 if (isInaccessible(inputField)) {577 // When an input field is hidden (but its parent isn't), we check578 // that it isn't a required argument of its field.579 if (inputField.isRequired()) {580 errors.push(ERRORS.REQUIRED_INACCESSIBLE.err(581 `Input field "${inputField.coordinate}" is @inaccessible` +582 ` but is a required input field of its type.`,583 {584 nodes: inputField.sourceAST,585 extensions: {586 inaccessible_elements: [inputField.coordinate],587 inaccessible_referencers: [inputField.coordinate],588 }589 },590 ));591 }592 // Input fields can be referenced by schema default values. When an593 // input field is hidden (but its parent isn't), we check that the594 // arguments/input fields with such default values aren't in the API595 // schema.596 assert(597 defaultValueReferencers,598 "Input fields can't be @inaccessible in v0.1, but default value" +599 " referencers weren't computed (which is only skipped for v0.1)."600 );601 const referencers = defaultValueReferencers.get(inputField) ?? [];602 for (const referencer of referencers) {603 if (isInAPISchema(referencer)) {604 errors.push(ERRORS.DEFAULT_VALUE_USES_INACCESSIBLE.err(605 `Input field "${inputField.coordinate}" is @inaccessible` +606 ` but is used in the default value of` +607 ` "${referencer.coordinate}", which is in the API schema.`,608 {609 nodes: type.sourceAST,610 extensions: {611 inaccessible_elements: [type.coordinate],612 inaccessible_referencers: [referencer.coordinate],613 }614 },615 ));616 }617 }618 }619 }620 } else if (type instanceof EnumType) {621 for (const enumValue of type.values) {622 if (isInaccessible(enumValue)) {623 // Enum values can be referenced by schema default values. When an624 // enum value is hidden (but its parent isn't), we check that the625 // arguments/input fields with such default values aren't in the API626 // schema.627 assert(628 defaultValueReferencers,629 "Enum values can't be @inaccessible in v0.1, but default value" +630 " referencers weren't computed (which is only skipped for v0.1)."631 );632 const referencers = defaultValueReferencers.get(enumValue) ?? [];633 for (const referencer of referencers) {634 if (isInAPISchema(referencer)) {635 errors.push(ERRORS.DEFAULT_VALUE_USES_INACCESSIBLE.err(636 `Enum value "${enumValue.coordinate}" is @inaccessible` +637 ` but is used in the default value of` +638 ` "${referencer.coordinate}", which is in the API schema.`,639 {640 nodes: type.sourceAST,641 extensions: {642 inaccessible_elements: [type.coordinate],643 inaccessible_referencers: [referencer.coordinate],644 }645 },646 ));647 }648 }649 }650 }651 }652 }653 }654 for (const directive of schema.allDirectives()) {655 const typeSystemLocations = directive.locations.filter((loc) => isTypeSystemDirectiveLocation(loc));656 if (hasBuiltInName(directive)) {657 // Built-in directives (and their descendants) aren't allowed to be658 // @inaccessible, regardless of shadowing.659 const inaccessibleElements =660 fetchInaccessibleElementsDeep(directive);661 if (inaccessibleElements.length > 0) {662 errors.push(ERRORS.DISALLOWED_INACCESSIBLE.err(663 `Built-in directive "${directive.coordinate}" cannot use @inaccessible.`,664 {665 nodes: directive.sourceAST,666 extensions: {667 inaccessible_elements: inaccessibleElements668 .map((element) => element.coordinate),669 inaccessible_referencers: [directive.coordinate],670 }671 },672 ));673 }674 } else if (isFeatureDefinition(directive)) {675 // Core feature directives (and their descendants) aren't allowed to be676 // @inaccessible.677 const inaccessibleElements =678 fetchInaccessibleElementsDeep(directive);679 if (inaccessibleElements.length > 0) {680 errors.push(ERRORS.DISALLOWED_INACCESSIBLE.err(681 `Core feature directive "${directive.coordinate}" cannot use @inaccessible.`,682 {683 nodes: directive.sourceAST,684 extensions: {685 inaccessible_elements: inaccessibleElements686 .map((element) => element.coordinate),687 inaccessible_referencers: [directive.coordinate],688 }689 },690 ));691 }692 } else if (typeSystemLocations.length > 0) {693 // Directives that can appear on type-system locations (and their694 // descendants) aren't allowed to be @inaccessible.695 const inaccessibleElements =696 fetchInaccessibleElementsDeep(directive);697 if (inaccessibleElements.length > 0) {698 errors.push(ERRORS.DISALLOWED_INACCESSIBLE.err(699 `Directive "${directive.coordinate}" cannot use @inaccessible` +700 ` because it may be applied to these type-system locations:` +701 ` ${typeSystemLocations.join(', ')}.`,702 {703 nodes: directive.sourceAST,704 extensions: {705 inaccessible_elements: inaccessibleElements706 .map((element) => element.coordinate),707 inaccessible_referencers: [directive.coordinate],708 }709 },710 ));711 }712 } else {713 // At this point, we know the directive must be in the API schema. Descend714 // into the directive's arguments.715 for (const argument of directive.arguments()) {716 // When an argument is hidden (but its parent isn't), we check that it717 // isn't a required argument of its directive.718 if (argument.isRequired()) {719 if (isInaccessible(argument)) {720 errors.push(ERRORS.REQUIRED_INACCESSIBLE.err(721 `Argument "${argument.coordinate}" is @inaccessible but is a` +722 ` required argument of its directive.`,723 {724 nodes: argument.sourceAST,725 extensions: {726 inaccessible_elements: [argument.coordinate],727 inaccessible_referencers: [argument.coordinate],728 }729 },730 ));731 }732 }733 }734 }735 }736 if (errors.length > 0) {737 throw ErrGraphQLAPISchemaValidationFailed(errors);738 }739}740type DefaultValueReference = InputFieldDefinition | EnumValue;741type SchemaElementWithDefaultValue =742 | ArgumentDefinition<743 | DirectiveDefinition744 | FieldDefinition<ObjectType | InterfaceType>>745 | InputFieldDefinition;746// Default values in a schema may contain references to selectable elements that747// are @inaccessible (input fields and enum values). For a given schema, this748// function returns a map from such selectable elements to the elements with749// default values referencing them. (The default values of built-ins and their750// descendants are skipped.)751//752// This function assumes default values are coercible to their location types753// (see the comments for addValueReferences() for details).754function computeDefaultValueReferencers(755 schema: Schema,756): Map<757 DefaultValueReference,758 SchemaElementWithDefaultValue[]759> {760 const referencers = new Map<761 DefaultValueReference,762 SchemaElementWithDefaultValue[]763 >();764 function addReference(765 reference: DefaultValueReference,766 referencer: SchemaElementWithDefaultValue,767 ) {768 const referencerList = referencers.get(reference) ?? [];769 if (referencerList.length === 0) {770 referencers.set(reference, referencerList);771 }772 referencerList.push(referencer);773 }774 // Note that the fields/arguments/input fields for built-in schema elements775 // can presumably only have types that are built-in types. Since built-ins and776 // their children aren't allowed to be @inaccessible, this means we shouldn't777 // have to worry about references within the default values of arguments and778 // input fields of built-ins, which is why we skip them below.779 for (const type of schema.allTypes()) {780 if (hasBuiltInName(type)) continue;781 // Scan object/interface field arguments.782 if (783 (type instanceof ObjectType) ||784 (type instanceof InterfaceType)785 ) {786 for (const field of type.fields()) {787 for (const argument of field.arguments()) {788 for (789 const reference of computeDefaultValueReferences(argument)790 ) {791 addReference(reference, argument);792 }793 }794 }795 }796 // Scan input object fields.797 if (type instanceof InputObjectType) {798 for (const inputField of type.fields()) {799 for (800 const reference of computeDefaultValueReferences(inputField)801 ) {802 addReference(reference, inputField);803 }804 }805 }806 }807 // Scan directive definition arguments.808 for (const directive of schema.allDirectives()) {809 if (hasBuiltInName(directive)) continue;810 for (const argument of directive.arguments()) {811 for (812 const reference of computeDefaultValueReferences(argument)813 ) {814 addReference(reference, argument);815 }816 }817 }818 return referencers;819}820// For the given element, compute a list of input fields and enum values that821// are referenced in its default value (if any). This function assumes the822// default value is coercible to the element's type (see the comments for823// addValueReferences() for details).824function computeDefaultValueReferences(825 element: SchemaElementWithDefaultValue,826): DefaultValueReference[] {827 const references: DefaultValueReference[] = [];828 addValueReferences(829 element.defaultValue,830 getInputType(element),831 references,832 )833 return references;834}835function getInputType(element: SchemaElementWithDefaultValue): InputType {836 const type = element.type;837 assert(838 type,839 "Schema should have been valid, but argument/input field did not have type."840 );841 return type;842}843// For the given GraphQL input value (represented in the format implicitly844// defined in buildValue()) and its type, add any references to input fields and845// enum values in that input value to the given references list.846//847// Note that this function requires the input value to be coercible to its type,848// similar to the "Values of Correct Type" validation in the GraphQL spec.849// However, there are two noteable differences:850// 1. Variable references are not allowed.851// 2. Scalar values are not required to be coercible (due to machine-specific852// differences in input coercion rules).853//854// As it turns out, building a Schema object validates this (and a bit more)855// already, so in the interests of not duplicating validations/keeping the logic856// centralized, this code assumes the input values it receives satisfy the above857// validations.858//859// Accordingly, this function's code is structured very similarly to the860// valueToString() function, which makes similar assumptions about its given861// value. If any inconsistencies/invalidities are discovered, they will be862// silently ignored.863function addValueReferences(864 value: any,865 type: InputType,866 references: DefaultValueReference[],867): void {868 if (value === undefined || value === null) {869 return;870 }871 if (isNonNullType(type)) {872 return addValueReferences(value, type.ofType, references);873 }874 if (isScalarType(type)) {875 // No need to look at scalar values.876 return;877 }878 if (isVariable(value)) {879 // Values in schemas shouldn't use variables, but we silently ignore it.880 return;881 }882 if (Array.isArray(value)) {883 if (isListType(type)) {884 const itemType = type.ofType;885 for (const item of value) {886 addValueReferences(item, itemType, references);887 }888 } else {889 // At this point a JS array can only be a list type, but we silently890 // ignore when it's not.891 }892 return;893 }894 if (isListType(type)) {895 // Note that GraphQL spec coerces non-list items into single-element lists.896 return addValueReferences(value, type.ofType, references);897 }898 if (typeof value === 'object') {899 if (isInputObjectType(type)) {900 // Silently ignore object keys that aren't in the input object.901 for (const field of type.fields()) {902 const fieldValue = value[field.name];903 if (fieldValue !== undefined) {904 references.push(field);905 addValueReferences(fieldValue, field.type!, references);906 } else {907 // Silently ignore when required input fields are omitted.908 }909 }910 } else {911 // At this point a JS object can only be an input object type, but we912 // silently ignore when it's not.913 }914 return;915 }916 if (typeof value === 'string') {917 if (isEnumType(type)) {918 const enumValue = type.value(value);919 if (enumValue !== undefined) {920 references.push(enumValue);921 } else {922 // Silently ignore enum values that aren't in the enum type.923 }924 } else {925 // At this point a JS string can only be an enum type, but we silently926 // ignore when it's not.927 }928 return;929 }930 // This should be unreachable code, but we silently ignore when it's not.931 return;932}933// Determine whether a given schema element has a built-in's name. Note that934// this is not the same as the isBuiltIn flag, due to shadowing definitions935// (which will not have the flag set).936function hasBuiltInName(element: NamedType | DirectiveDefinition): boolean {937 const schema = element.schema();938 if (939 (element instanceof ObjectType) ||940 (element instanceof InterfaceType) ||941 (element instanceof UnionType) ||942 (element instanceof ScalarType) ||943 (element instanceof EnumType) ||944 (element instanceof InputObjectType)945 ) {946 return schema.builtInTypes(true).some((type) =>947 type.name === element.name948 );949 } else if (element instanceof DirectiveDefinition) {950 return schema.builtInDirectives(true).some((directive) =>951 directive.name === element.name952 );953 }954 assert(false, "Unreachable code, element is of unknown type.")955}956// Remove schema elements marked with @inaccessible in the schema, assuming the957// schema has been validated with validateInaccessibleElements().958//959// Note the schema that results from this may not necessarily be valid GraphQL960// until core feature definitions have been removed by removeFeatureElements().961function removeInaccessibleElementsAssumingValid(962 schema: Schema,963 inaccessibleDirective: DirectiveDefinition,964): void {965 function isInaccessible(element: SchemaElement<any, any>): boolean {966 return element.hasAppliedDirective(inaccessibleDirective);967 }968 for (const type of schema.types()) {969 if (isInaccessible(type)) {970 type.remove();971 } else {972 if ((type instanceof ObjectType) || (type instanceof InterfaceType)) {973 for (const field of type.fields()) {974 if (isInaccessible(field)) {975 field.remove();976 } else {977 for (const argument of field.arguments()) {978 if (isInaccessible(argument)) {979 argument.remove();980 }981 }982 }983 }984 } else if (type instanceof InputObjectType) {985 for (const inputField of type.fields()) {986 if (isInaccessible(inputField)) {987 inputField.remove();988 }989 }990 } else if (type instanceof EnumType) {991 for (const enumValue of type.values) {992 if (isInaccessible(enumValue)) {993 enumValue.remove();994 }995 }996 }997 }998 }999 for (const directive of schema.directives()) {1000 for (const argument of directive.arguments()) {1001 if (isInaccessible(argument)) {1002 argument.remove();1003 }1004 }1005 }...

Full Screen

Full Screen

secret-map.component.ts

Source:secret-map.component.ts Github

copy

Full Screen

1import { style } from '@angular/animations';2import { Component, HostBinding, HostListener, OnInit } from '@angular/core';3import { faCheckCircle, faSearchMinus, faSearchPlus } from '@fortawesome/free-solid-svg-icons';4import { assign, find, forEach } from 'lodash';5import { MAP_SIZE, MAP_URL } from '../../../../shared/constants/map';6import { MapLocation } from '../../../../shared/types/entities/map-location';7import { ApiService } from '../../services/api/api.service';8interface OurMapLocation extends MapLocation {9 available?: boolean;10 inaccessible?: boolean;11 completed?: boolean;12}13@Component({14 selector: 'gdb-secret-map',15 templateUrl: './secret-map.component.html',16 styleUrls: ['./secret-map.component.scss'],17})18export class SecretMapComponent implements OnInit {19 checkmarkIcon = faCheckCircle;20 largerIcon = faSearchPlus;21 smallerIcon = faSearchMinus;22 mapUrlCss = `url('${MAP_URL}')`;23 stickers: OurMapLocation[];24 focusedSticker: OurMapLocation;25 readonly scaleStep = 0.2;26 readonly maxZoom = 10;27 readonly minZoom = 1;28 zoom: number = 5;29 get scale(): number {30 return 1 / (1 + this.scaleStep) ** (11 - this.zoom);31 }32 get transform(): string {33 return `scale(${this.scale})`;34 }35 @HostBinding('style.height')36 @HostBinding('style.width')37 get mapSize(): string {38 return this.scale * MAP_SIZE + 'px';39 }40 constructor(private api: ApiService) {}41 async ngOnInit() {42 this.stickers = await this.api.getMapLocations();43 const onTheBoard: Partial<OurMapLocation>[] = [44 {45 number: 1,46 completed: true,47 available: true,48 inaccessible: false,49 },50 {51 number: 2,52 completed: true,53 available: true,54 inaccessible: false,55 },56 {57 number: 3,58 completed: true,59 available: true,60 inaccessible: false,61 },62 {63 number: 4,64 completed: true,65 available: true,66 inaccessible: false,67 },68 {69 number: 5,70 completed: true,71 available: true,72 inaccessible: false,73 },74 {75 number: 6,76 completed: true,77 available: true,78 inaccessible: false,79 },80 {81 number: 7,82 completed: true,83 available: true,84 inaccessible: false,85 },86 {87 number: 8,88 completed: true,89 available: true,90 inaccessible: false,91 },92 {93 number: 9,94 completed: false,95 available: true,96 inaccessible: true,97 },98 {99 number: 10,100 completed: true,101 available: true,102 inaccessible: false,103 },104 {105 number: 13,106 completed: true,107 available: true,108 inaccessible: false,109 },110 {111 number: 14,112 completed: true,113 available: true,114 inaccessible: false,115 },116 {117 number: 15,118 completed: true,119 available: true,120 inaccessible: false,121 },122 {123 number: 18,124 completed: true,125 available: true,126 inaccessible: false,127 },128 {129 number: 19,130 completed: true,131 available: true,132 inaccessible: false,133 },134 {135 number: 20,136 completed: true,137 available: true,138 inaccessible: false,139 },140 {141 number: 21,142 completed: true,143 available: true,144 inaccessible: false,145 },146 {147 number: 22,148 completed: true,149 available: true,150 inaccessible: false,151 },152 {153 number: 23,154 completed: true,155 available: true,156 inaccessible: false,157 },158 {159 number: 26,160 completed: true,161 available: true,162 inaccessible: false,163 },164 {165 number: 27,166 completed: true,167 available: true,168 inaccessible: false,169 },170 {171 number: 28,172 completed: true,173 available: true,174 inaccessible: false,175 },176 {177 number: 31,178 completed: true,179 available: true,180 inaccessible: false,181 },182 {183 number: 35,184 completed: false,185 available: true,186 inaccessible: true,187 },188 {189 number: 36,190 completed: false,191 available: true,192 inaccessible: true,193 },194 {195 number: 37,196 completed: true,197 available: true,198 inaccessible: false,199 },200 {201 number: 38,202 completed: true,203 available: true,204 inaccessible: false,205 },206 {207 number: 43,208 completed: true,209 available: true,210 inaccessible: false,211 },212 {213 number: 46,214 completed: true,215 available: true,216 inaccessible: false,217 },218 {219 number: 51,220 completed: false,221 available: true,222 inaccessible: true,223 },224 {225 number: 52,226 completed: true,227 available: true,228 inaccessible: false,229 },230 {231 number: 53,232 completed: true,233 available: true,234 inaccessible: false,235 },236 {237 number: 54,238 completed: true,239 available: true,240 inaccessible: false,241 },242 {243 number: 68,244 completed: true,245 available: true,246 inaccessible: false,247 },248 {249 number: 70,250 completed: true,251 available: true,252 inaccessible: false,253 },254 {255 number: 72,256 completed: true,257 available: true,258 inaccessible: false,259 },260 {261 number: 73,262 completed: false,263 available: true,264 inaccessible: false,265 },266 {267 number: 76,268 completed: false,269 available: true,270 inaccessible: false,271 },272 {273 number: 81,274 completed: true,275 available: true,276 inaccessible: false,277 },278 {279 number: 82,280 completed: true,281 available: true,282 inaccessible: false,283 },284 {285 number: 83,286 completed: true,287 available: true,288 inaccessible: false,289 },290 {291 number: 93,292 completed: true,293 available: true,294 inaccessible: false,295 },296 {297 number: 17,298 completed: false,299 available: true,300 inaccessible: false,301 },302 {303 number: 47,304 completed: true,305 available: true,306 inaccessible: false,307 },308 {309 number: 44,310 completed: true,311 available: true,312 inaccessible: false,313 },314 {315 number: 48,316 completed: false,317 available: true,318 inaccessible: false,319 },320 {321 number: 29,322 completed: false,323 available: true,324 inaccessible: false,325 },326 {327 number: 16,328 completed: false,329 available: true,330 inaccessible: false,331 },332 {333 number: 39,334 completed: true,335 available: true,336 inaccessible: false,337 },338 ];339 forEach(this.stickers, (sticker) => assign(sticker, find(onTheBoard, { number: sticker.number })));340 }341 stickerClick(sticker: OurMapLocation) {342 this.focusedSticker = sticker;343 }344 numberClick(sticker: OurMapLocation) {345 sticker.available = !sticker.available;346 }347 checkboxClick(sticker: OurMapLocation) {348 if (sticker.inaccessible) {349 return;350 }351 sticker.completed = !sticker.completed;352 }353 @HostListener('document:keydown.escape')354 defocusStickers() {355 this.focusedSticker = null;356 }357 zoomIn() {358 this.zoom = Math.min(this.zoom + 1, this.maxZoom);359 }360 zoomOut() {361 this.zoom = Math.max(this.zoom - 1, this.minZoom);362 }...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1import { getStorybookUI, configure } from '../storybook';2configure(() => {3 require('./stories');4}, module);5const StorybookUIRoot = getStorybookUI({ port: 7007, host: 'localhost' });6export default StorybookUIRoot;7import React from 'react';8import StorybookUIRoot from './storybook/test';9const App = () => <StorybookUIRoot />;10export default App;11import { getStorybookUI, configure } from '@storybook/react-native';12import { loadStories } from './storyLoader';13configure(loadStories, module);14const StorybookUIRoot = getStorybookUI({ port: 7007, host: 'localhost' });15export default StorybookUIRoot;16import { configure } from '@storybook/react-native';17configure(() => {18 require('../src/stories');19}, module);20import { storiesOf } from '@storybook/react-native';21import React from 'react';22import { Text } from 'react-native';23storiesOf('Button', module).add('with text', ()

Full Screen

Using AI Code Generation

copy

Full Screen

1import { getStorybookUI, configure } from 'storybook-root';2configure(() => {3 require('./stories');4}, module);5const StorybookUI = getStorybookUI({ port: 7007, host: 'localhost' });6export default StorybookUI;7import { getStorybookUI, configure } from '@storybook/react-native';8export { getStorybookUI, configure };9import { getStorybookUI, configure } from '@storybook/react-native';10export { getStorybookUI, configure };11import { getStorybookUI, configure } from '@storybook/react-native';12export { getStorybookUI, configure };13import { getStorybookUI, configure } from '@storybook/react-native';14export { getStorybookUI, configure };15import { getStorybookUI, configure } from '@storybook/react-native';16export { getStorybookUI, configure };17import { getStorybookUI, configure } from '@storybook/react-native';18export { getStorybookUI, configure };19import { getStorybookUI, configure } from '@storybook/react-native';20export { getStorybookUI, configure };21import { getStorybookUI, configure } from '@storybook/react-native';22export { getStorybookUI, configure };23import { getStory

Full Screen

Using AI Code Generation

copy

Full Screen

1import { getStorybookUI } from 'storybook-react-native';2import { getStorybookUI } from 'storybook-react-native';3const StorybookUIRoot = getStorybookUI({ port: 7007, host: 'localhost' });4export default StorybookUIRoot;5import { configure } from '@storybook/react-native';6function loadStories() {7}8configure(loadStories, module);9import { AppRegistry } from 'react-native';10import { getStorybookUI, configure } from '@storybook/react-native';11import './rn-addons';12configure(() => {13 require('./storyLoader');14}, module);15const StorybookUIRoot = getStorybookUI({ port: 7007, host: 'localhost' });16AppRegistry.registerComponent('AwesomeProject', () => StorybookUIRoot);17export default StorybookUIRoot;18import { setOptions } from '@storybook/addon-options';19setOptions({

Full Screen

Using AI Code Generation

copy

Full Screen

1export const accessibleMethod = () => {2}3import { accessibleMethod } from './index.js';4describe('accessibleMethod', () => {5 it('should be accessible', () => {6 expect(accessibleMethod()).toBe('Hello World');7 });8});9import { accessibleMethod } from './index.js';10storiesOf('MyComponent', module).add('accessibleMethod', () => {11 return accessibleMethod();12});13import { accessibleMethod } from './index.js';14describe('accessibleMethod', () => {15 it('should be accessible', () => {16 expect(accessibleMethod()).toBe('Hello World');17 });18});19import { accessibleMethod } from './index.js';20describe('accessibleMethod', () => {21 it('should be accessible', () => {22 expect(accessibleMethod()).toBe('Hello World');23 });24});25import { accessibleMethod } from './index.js';26describe('accessibleMethod', () => {27 it('should be accessible', () => {28 expect(accessibleMethod()).toBe('Hello World');29 });30});31import { accessibleMethod } from './index.js';32describe('accessibleMethod', () => {33 it('should be accessible', () => {34 expect(accessibleMethod()).toBe('Hello World');35 });36});37import { accessibleMethod } from './index.js';38describe('accessibleMethod', () => {39 it('should be accessible', () => {40 expect(accessibleMethod()).toBe('Hello World');41 });42});43import { accessibleMethod } from './index.js';44describe('accessibleMethod', () => {45 it('should be accessible', () => {46 expect(accessibleMethod()).toBe('Hello World');47 });48});49import { accessibleMethod } from './index.js';50describe('accessibleMethod', () => {51 it('should be accessible', () => {52 expect(accessibleMethod()).toBe('Hello World

Full Screen

Using AI Code Generation

copy

Full Screen

1const root = document.querySelector('storybook-root');2const storybook = root.shadowRoot.querySelector('storybook-preview');3const story = storybook.shadowRoot.querySelector('story-component');4const component = story.shadowRoot.querySelector('my-component');5const root = document.querySelector('my-component');6const myComponent = root.shadowRoot.querySelector('my-component');7const root = document.querySelector('my-component');8const myComponent = root.shadowRoot.querySelector('my-component');9const root = document.querySelector('my-component');10const myComponent = root.shadowRoot.querySelector('my-component');11const root = document.querySelector('my-component');12const myComponent = root.shadowRoot.querySelector('my-component');13const root = document.querySelector('my-component');14const myComponent = root.shadowRoot.querySelector('my-component');15const root = document.querySelector('my-component');16const myComponent = root.shadowRoot.querySelector('my-component');17const root = document.querySelector('my-component');18const myComponent = root.shadowRoot.querySelector('my-component');19const root = document.querySelector('my-component');20const myComponent = root.shadowRoot.querySelector('my-component');21const root = document.querySelector('my-component');22const myComponent = root.shadowRoot.querySelector('my-component');23const root = document.querySelector('my-component');24const myComponent = root.shadowRoot.querySelector('my-component');25const root = document.querySelector('my-component');26const myComponent = root.shadowRoot.querySelector('my-component');27const root = document.querySelector('my-component');28const myComponent = root.shadowRoot.querySelector('my-component

Full Screen

Using AI Code Generation

copy

Full Screen

1I’ve been trying to use the .storybook/preview.js file to add a global decorator, but I’m not sure how to do it. I’ve tried using the .addDecorator() method, but I’m not sure how to use it. I’ve tried doing it like this:2import React from 'react';3import { addDecorator } from '@storybook/react';4import { withKnobs } from '@storybook/addon-knobs';5import { withA11y } from '@storybook/addon-a11y';6import { withInfo } from '@storybook/addon-info';7import { withTests } from '@storybook/addon-jest';8import { withPerformance } from 'storybook-addon-performance';9import { ThemeProvider } from 'styled-components';10import { theme } from '../src/styles/theme';11import { GlobalStyle } from '../src/styles/global';12import results from '../.jest-test-results.json';13addDecorator((story, context) => withTests({ results })(story)(context));14addDecorator(withKnobs);15addDecorator(withA11y);16addDecorator(withInfo);17addDecorator(withPerformance);18addDecorator(story => (19 <ThemeProvider theme={theme}>20 {story()}21));22I think the problem is that you are trying to import the addDecorator method from the storybook/react package. However, you need to import it from the storybook/react package. You can do this by adding the following line to the top of your preview.js file:23import { addDecorator } from '@storybook/react';

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run storybook-root automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful