Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Caching doesn't seem to work in specs #1653

Open
MarcusRiemer opened this issue Mar 31, 2021 · 2 comments
Open

Caching doesn't seem to work in specs #1653

MarcusRiemer opened this issue Mar 31, 2021 · 2 comments
Labels
needs triage source of problem is not clear yet. the reproduction might help

Comments

@MarcusRiemer
Copy link
Contributor

MarcusRiemer commented Mar 31, 2021

Describe the bug

I am effectively trying to call cache.writeQuery and cache.readQuery as part of an Angular Spec file. The item is always written to the cache (I have log messages that at least indicate so), but for whatever reason reading it back doesn't work at all.

To Reproduce

The following code is ripped out of my application as condensed version and is also available as a Jasmine-Test on StackBlitz that immediatly shows the error and the log output.

// The query to execute
export const NameBlockLanguageDocument = gql`
  query FullBlockLanguage($id: ID!) {
    blockLanguage(id: $id) {
      id
      name
      grammarId
      sidebars
      editorBlocks
    }
  }
`;

// Some data that should end up in the cache
const DEFAULT_EMPTY_BLOCKLANGUAGE = Object.freeze({
  __typename: "BlockLanguage",
  id: "96659508-e006-4290-926e-0734e7dd061a",
  name: "Empty Spec Block Language",
  grammarId: "2ca79350-c734-4f61-a44b-cca25cf3a122",
  sidebars: [],
  editorBlocks: [],
});

// Utility function to write something into the cache and log it.
export function cacheFullBlockLanguage(apollo: Apollo, blockLangDesc: any) {
  // Make the block language available to the rendered trees
  const queryData: any = {
    blockLanguage: Object.assign(
      { __typename: "BlockLanguage" },
      blockLangDesc
    ),
  };
  // Don't need to provide explicitly linked ID as it is contained
  // in the given ID and the __typename
  apollo.client.cache.writeQuery({
    query: NameBlockLanguageDocument,
    data: queryData,
    variables: { id: blockLangDesc.id },
  });

  console.log("Explicitly added to GraphQL Cache:", blockLangDesc);
}

// The actual test
describe("GQL Cache", () => {
  async function createModule() {
    await TestBed.configureTestingModule({
      imports: [ApolloTestingModule],
      providers: [],
    }).compileComponents();

    const apollo = TestBed.inject(Apollo);

    return { apollo };
  }

  it(`Stores and reads a block language`, async () => {
    const t = await createModule();

    const b = DEFAULT_EMPTY_BLOCKLANGUAGE;

    cacheFullBlockLanguage(t.apollo, b);

    const cache = t.apollo.client.cache;
    const res = cache.readQuery({
      query: NameBlockLanguageDocument,
      variables: {
        id: b.id,
      },
    });

    console.log("Cache state", (cache as any).data.data);

    expect(res["name"]).toEqual(b.name);
  });
});

The first log entry strongly indicates that the item is indeed added to the cache and well formed:

Explicitly added to GraphQL Cache: 
Object { __typename: "BlockLanguage", id: "96659508-e006-4290-926e-0734e7dd061a", name: "Empty Spec Block Language", sidebars: [], editorBlocks: [], grammarId: "2ca79350-c734-4f61-a44b-cca25cf3a122" }

And if I dig into the private state of the cache, I can find the entry there as well:

Cache state {…}
"BlockLanguage:96659508-e006-4290-926e-0734e7dd061a": Object { id: "96659508-e006-4290-926e-0734e7dd061a", __typename: "BlockLanguage", name: "Empty Spec Block Language", … }
ROOT_QUERY: Object { __typename: "Query", "blockLanguage({\"id\":\"96659508-e006-4290-926e-0734e7dd061a\"})": {…} }

Nevertheless the spec (and therefore the cache read) fails with res being undefined instead of properly mirroring DEFAULT_EMPTY_BLOCKLANGUAGE.

Expected behavior

I would expect that the item is retrieved from the cache and therefore the test passes.

Environment:

  • @apollo/client: 3.3.11
  • apollo-angular: 2.4.0
  • graphql: 15.5.0
  • @angular/core: 11.2.5
  • @angular/cli: 11.2.4
  • typescript: 4.1.3

Additional context

I also asked this over on StackOverflow but I didn't get a response yet. The more I am digging around this the more I am suspecting I might be hitting a bug.

@MarcusRiemer
Copy link
Contributor Author

I now also tried adding addTypename: true to my specs (as hinted by the testing documentation):

{
  provide: APOLLO_TESTING_CACHE,
  useValue: {
    addTypename: true,
  },
},

This leads to runtime-errors in the form of this._apollo.client.cache.readQuery is not a function which makes me believe that the documentation is incorrect and actually expects a "normal" cache instance and not a configuration object?

@MarcusRiemer
Copy link
Contributor Author

My real issue seems to be elsewhere, but when looking at the code the documentation mentioned above seems to be wrong indeed:

function createOptions(name: string, c?: ApolloCache<any> | null) {
return {
link: new ApolloLink((operation) =>
backend.handle(addClient(name, operation)),
),
cache:
c ||
new InMemoryCache({
addTypename: false,
}),
};
}

@fetis fetis added the needs triage source of problem is not clear yet. the reproduction might help label May 18, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs triage source of problem is not clear yet. the reproduction might help
Projects
None yet
Development

No branches or pull requests

2 participants