···11+import { graphql } from './graphql';
22+33+const pokemonFragment = graphql(`
44+ fragment PokemonBasicInfo on Pokemon {
55+ id
66+ name
77+ }
88+`);
99+1010+// This query correctly includes the fragment as a dep
1111+const FirstQuery = graphql(
1212+ `
1313+ query FirstQuery {
1414+ pokemons(limit: 1) {
1515+ ...PokemonBasicInfo
1616+ }
1717+ }
1818+ `,
1919+ [pokemonFragment]
2020+);
2121+2222+// This query uses the fragment but DOES NOT include it as a dep
2323+// It should show an error, but currently doesn't because the fragment
2424+// was already added as a dep in FirstQuery above
2525+const SecondQuery = graphql(`
2626+ query SecondQuery {
2727+ pokemons(limit: 2) {
2828+ ...PokemonBasicInfo
2929+ }
3030+ }
3131+`);
3232+3333+export { FirstQuery, SecondQuery };
+71
test/e2e/tada.test.ts
···619619 `);
620620 }, 30000);
621621});
622622+623623+describe('Fragment dependencies - Issue #494', () => {
624624+ const projectPath = path.resolve(__dirname, 'fixture-project-tada');
625625+ const outfileMissingFragmentDep = path.join(
626626+ projectPath,
627627+ 'missing-fragment-dep.ts'
628628+ );
629629+630630+ let server: TSServer;
631631+ beforeAll(async () => {
632632+ server = new TSServer(projectPath, { debugLog: false });
633633+634634+ server.sendCommand('open', {
635635+ file: outfileMissingFragmentDep,
636636+ fileContent: '// empty',
637637+ scriptKindName: 'TS',
638638+ } satisfies ts.server.protocol.OpenRequestArgs);
639639+640640+ server.sendCommand('updateOpen', {
641641+ openFiles: [
642642+ {
643643+ file: outfileMissingFragmentDep,
644644+ fileContent: fs.readFileSync(
645645+ path.join(projectPath, 'fixtures/missing-fragment-dep.ts'),
646646+ 'utf-8'
647647+ ),
648648+ },
649649+ ],
650650+ } satisfies ts.server.protocol.UpdateOpenRequestArgs);
651651+652652+ server.sendCommand('saveto', {
653653+ file: outfileMissingFragmentDep,
654654+ tmpfile: outfileMissingFragmentDep,
655655+ } satisfies ts.server.protocol.SavetoRequestArgs);
656656+ });
657657+658658+ afterAll(() => {
659659+ try {
660660+ fs.unlinkSync(outfileMissingFragmentDep);
661661+ } catch {}
662662+ });
663663+664664+ it('warns about missing fragment dep even when fragment is used in another query in same file', async () => {
665665+ await server.waitForResponse(
666666+ e =>
667667+ e.type === 'event' &&
668668+ e.event === 'semanticDiag' &&
669669+ e.body?.file === outfileMissingFragmentDep
670670+ );
671671+672672+ const res = server.responses.filter(
673673+ resp =>
674674+ resp.type === 'event' &&
675675+ resp.event === 'semanticDiag' &&
676676+ resp.body?.file === outfileMissingFragmentDep
677677+ );
678678+679679+ // Should have a diagnostic about the unknown fragment in SecondQuery
680680+ expect(res.length).toBeGreaterThan(0);
681681+ expect(res[0].body.diagnostics.length).toBeGreaterThan(0);
682682+683683+ const fragmentError = res[0].body.diagnostics.find((diag: any) =>
684684+ diag.text.includes('PokemonBasicInfo')
685685+ );
686686+687687+ expect(fragmentError).toBeDefined();
688688+ expect(fragmentError.text).toBe('Unknown fragment "PokemonBasicInfo".');
689689+ expect(fragmentError.code).toBe(52001);
690690+ expect(fragmentError.category).toBe('error');
691691+ }, 30000);
692692+});