Ejemplo n.º 1
0
describe('Counter example API works', () => {
  let server, apollo;

  before(() => {
    server = getServer();
    apollo = getApollo();
  });

  step('Has GraphiQL endpoint', () => {
    return chai
      .request(server)
      .get('/graphiql')
      .end((err, res) => {
        res.status.should.be(200);
        res.body.should.be('{}');
      });
  });

  step('Responds to counter get GraphQL query', async () => {
    let result = await apollo.query({ query: COUNTER_QUERY });

    result.data.should.deep.equal({
      counter: { amount: 5, __typename: 'Counter' }
    });
  });

  step('Increments counter on GraphQL mutation', async () => {
    let result = await apollo.mutate({
      mutation: ADD_COUNTER,
      variables: { amount: 2 }
    });

    result.data.should.deep.equal({
      addCounter: { amount: 7, __typename: 'Counter' }
    });
  });

  step('Triggers subscription on GraphQL mutation', done => {
    apollo.mutate({ mutation: ADD_COUNTER, variables: { amount: 1 } });

    apollo
      .subscribe({
        query: COUNTER_SUBSCRIPTION,
        variables: {}
      })
      .subscribe({
        next(data) {
          data.should.deep.equal({
            data: { counterUpdated: { amount: 8, __typename: 'Counter' } }
          });
          done();
        }
      });
  });
});
Ejemplo n.º 2
0
describe('User UI works', () => {
  const renderer = new Renderer({});
  let app;
  let content;

  step('User page renders on mount', () => {
    app = renderer.mount(Routes);
    renderer.history.push('/profile');
    content = app.find('#content');
    expect(content).to.not.be.empty;
  });
});
Ejemplo n.º 3
0
describe('Upload API works', () => {
  let server, apollo;

  before(() => {
    server = getServer();
    apollo = getApollo();
  });

  step('Has GraphiQL endpoint', () => {
    return chai
      .request(server)
      .get('/graphiql')
      .end((err, res) => {
        res.status.should.be(200);
        res.body.should.be('{}');
      });
  });
});
Ejemplo n.º 4
0
describe('Post and comments example API works', () => {
  let apollo;

  before(() => {
    apollo = getApollo();
  });

  step('Query post list works', async () => {
    let result = await apollo.query({
      query: POSTS_QUERY,
      variables: { limit: 1, after: 0 }
    });

    expect(result.data).to.deep.equal({
      posts: {
        totalCount: 20,
        edges: [
          {
            cursor: 20,
            node: {
              id: 20,
              title: 'Post title 20',
              content: 'Post content 20',
              __typename: 'Post'
            },
            __typename: 'PostEdges'
          }
        ],
        pageInfo: {
          endCursor: 20,
          hasNextPage: true,
          __typename: 'PostPageInfo'
        },
        __typename: 'Posts'
      }
    });
  });

  step('Query single post with comments works', async () => {
    let result = await apollo.query({ query: POST_QUERY, variables: { id: 1 } });

    expect(result.data).to.deep.equal({
      post: {
        id: 1,
        title: 'Post title 1',
        content: 'Post content 1',
        __typename: 'Post',
        comments: [
          {
            id: 1,
            content: 'Comment title 1 for post 1',
            __typename: 'Comment'
          },
          {
            id: 2,
            content: 'Comment title 2 for post 1',
            __typename: 'Comment'
          }
        ]
      }
    });
  });

  step('Publishes post on add', done => {
    apollo.mutate({
      mutation: ADD_POST,
      variables: {
        input: {
          title: 'New post 1',
          content: 'New post content 1'
        }
      }
    });

    let subscription;

    subscription = apollo
      .subscribe({
        query: POSTS_SUBSCRIPTION,
        variables: { endCursor: 10 }
      })
      .subscribe({
        next(data) {
          expect(data).to.deep.equal({
            data: {
              postsUpdated: {
                mutation: 'CREATED',
                node: {
                  id: 21,
                  title: 'New post 1',
                  content: 'New post content 1',
                  __typename: 'Post'
                },
                __typename: 'UpdatePostPayload'
              }
            }
          });
          subscription.unsubscribe();
          done();
        }
      });
  });

  step('Adding post works', async () => {
    let result = await apollo.query({
      query: POSTS_QUERY,
      variables: { limit: 1, after: 0 },
      fetchPolicy: 'network-only'
    });
    expect(result.data.posts).to.have.property('totalCount', 21);
    expect(result.data.posts).to.have.nested.property('edges[0].node.title', 'New post 1');
    expect(result.data.posts).to.have.nested.property('edges[0].node.content', 'New post content 1');
  });

  step('Publishes post on update', done => {
    apollo.mutate({
      mutation: EDIT_POST,
      variables: {
        input: {
          id: 21,
          title: 'New post 2',
          content: 'New post content 2'
        }
      }
    });

    let subscription;

    subscription = apollo
      .subscribe({
        query: POSTS_SUBSCRIPTION,
        variables: { endCursor: 10 }
      })
      .subscribe({
        next(data) {
          expect(data).to.deep.equal({
            data: {
              postsUpdated: {
                mutation: 'UPDATED',
                node: {
                  id: 21,
                  title: 'New post 2',
                  content: 'New post content 2',
                  __typename: 'Post'
                },
                __typename: 'UpdatePostPayload'
              }
            }
          });
          subscription.unsubscribe();
          done();
        }
      });
  });

  step('Updating post works', async () => {
    let result = await apollo.query({
      query: POSTS_QUERY,
      variables: { limit: 1, after: 0 },
      fetchPolicy: 'network-only'
    });
    expect(result.data.posts).to.have.property('totalCount', 21);
    expect(result.data.posts).to.have.nested.property('edges[0].node.title', 'New post 2');
    expect(result.data.posts).to.have.nested.property('edges[0].node.content', 'New post content 2');
  });

  step('Publishes post on removal', done => {
    apollo.mutate({
      mutation: DELETE_POST,
      variables: { id: '21' }
    });

    let subscription;

    subscription = apollo
      .subscribe({
        query: POSTS_SUBSCRIPTION,
        variables: { endCursor: 10 }
      })
      .subscribe({
        next(data) {
          expect(data).to.deep.equal({
            data: {
              postsUpdated: {
                mutation: 'DELETED',
                node: {
                  id: 21,
                  title: 'New post 2',
                  content: 'New post content 2',
                  __typename: 'Post'
                },
                __typename: 'UpdatePostPayload'
              }
            }
          });
          subscription.unsubscribe();
          done();
        }
      });
  });

  step('Deleting post works', async () => {
    let result = await apollo.query({
      query: POSTS_QUERY,
      variables: { limit: 2, after: 0 },
      fetchPolicy: 'network-only'
    });
    expect(result.data.posts).to.have.property('totalCount', 20);
    expect(result.data.posts).to.have.nested.property('edges[0].node.title', 'Post title 20');
    expect(result.data.posts).to.have.nested.property('edges[0].node.content', 'Post content 20');
  });
});
Ejemplo n.º 5
0
describe('Posts and comments example UI works', () => {
  const renderer = new Renderer(mocks, {});
  let app;
  let content;

  beforeEach(() => {
    // Reset spy mutations on each step
    Object.keys(mutations).forEach(key => delete mutations[key]);
    if (app) {
      app.update();
      content = app.find('#content').last();
    }
  });

  step('Posts page renders without data', () => {
    app = renderer.mount();
    content = app.find('#content').last();
    renderer.history.push('/posts');

    content.text().should.equal('Loading...');
  });

  step('Posts page renders with data', () => {
    expect(content.text()).to.include('Post title 1');
    expect(content.text()).to.include('Post title 2');
    expect(content.text()).to.include('2 / 4');
  });

  step('Clicking load more works', () => {
    const loadMoreButton = content.find('#load-more').last();
    loadMoreButton.simulate('click');
  });

  step('Clicking load more loads more posts', () => {
    expect(content.text()).to.include('Post title 3');
    expect(content.text()).to.include('Post title 4');
    expect(content.text()).to.include('4 / 4');
  });

  step('Check subscribed to post list updates', () => {
    expect(renderer.getSubscriptions(POSTS_SUBSCRIPTION)).has.lengthOf(1);
  });

  step('Updates post list on post delete from subscription', () => {
    const subscription = renderer.getSubscriptions(POSTS_SUBSCRIPTION)[0];
    subscription.next({
      data: {
        postsUpdated: {
          mutation: 'DELETED',
          node: createNode(2),
          __typename: 'UpdatePostPayload'
        }
      }
    });

    expect(content.text()).to.not.include('Post title 2');
    expect(content.text()).to.include('3 / 3');
  });

  step('Updates post list on post create from subscription', () => {
    const subscription = renderer.getSubscriptions(POSTS_SUBSCRIPTION)[0];
    subscription.next(
      _.cloneDeep({
        data: {
          postsUpdated: {
            mutation: 'CREATED',
            node: createNode(2),
            __typename: 'UpdatePostPayload'
          }
        }
      })
    );

    expect(content.text()).to.include('Post title 2');
    expect(content.text()).to.include('4 / 4');
  });

  step('Clicking delete optimistically removes post', () => {
    mutations.deletePost = (obj, { id }) => {
      return createNode(id);
    };

    const deleteButtons = content.find('.delete-button');
    expect(deleteButtons).has.lengthOf(12);
    deleteButtons.last().simulate('click');

    expect(content.text()).to.not.include('Post title 4');
    expect(content.text()).to.include('3 / 3');
  });

  step('Clicking delete removes the post', () => {
    expect(content.text()).to.include('Post title 3');
    expect(content.text()).to.not.include('Post title 4');
    expect(content.text()).to.include('3 / 3');
  });

  step('Clicking on post works', () => {
    const postLinks = content.find('.post-link');
    postLinks.last().simulate('click', { button: 0 });
  });

  step('Clicking on post opens post form', () => {
    const postForm = content.find('form[name="post"]');

    expect(content.text()).to.include('Edit Post');
    expect(
      postForm
        .find('[name="title"]')
        .last()
        .instance().value
    ).to.equal('Post title 3');
    expect(
      postForm
        .find('[name="content"]')
        .last()
        .instance().value
    ).to.equal('Post content 3');
  });

  step('Check subscribed to post updates', () => {
    expect(renderer.getSubscriptions(POST_SUBSCRIPTION)).has.lengthOf(1);
  });

  step('Updates post form on post updated from subscription', () => {
    const subscription = renderer.getSubscriptions(POST_SUBSCRIPTION)[0];
    subscription.next({
      data: {
        postUpdated: {
          id: '3',
          title: 'Post title 203',
          content: 'Post content 204',
          __typename: 'Post'
        }
      }
    });
    const postForm = content.find('form[name="post"]');
    expect(
      postForm
        .find('[name="title"]')
        .last()
        .instance().value
    ).to.equal('Post title 203');
    expect(
      postForm
        .find('[name="content"]')
        .last()
        .instance().value
    ).to.equal('Post content 204');
  });

  step('Post editing form works', done => {
    mutations.editPost = (obj, { input }) => {
      expect(input.id).to.equal(3);
      expect(input.title).to.equal('Post title 33');
      expect(input.content).to.equal('Post content 33');
      done();
      return input;
    };

    const postForm = app.find('form[name="post"]').last();
    postForm
      .find('[name="title"]')
      .last()
      .simulate('change', { target: { name: 'title', value: 'Post title 33' } });
    postForm
      .find('[name="content"]')
      .last()
      .simulate('change', { target: { name: 'content', value: 'Post content 33' } });
    postForm.simulate('submit');
  });

  step('Check opening post by URL', () => {
    renderer.history.push('/post/3');
  });

  step('Opening post by URL works', () => {
    const postForm = content.find('form[name="post"]');

    expect(content.text()).to.include('Edit Post');
    expect(
      postForm
        .find('[name="title"]')
        .last()
        .instance().value
    ).to.equal('Post title 33');
    expect(
      postForm
        .find('[name="content"]')
        .last()
        .instance().value
    ).to.equal('Post content 33');
    expect(content.text()).to.include('Edit Post');
  });

  step('Comment adding works', done => {
    mutations.addComment = (obj, { input }) => {
      expect(input.postId).to.equal(3);
      expect(input.content).to.equal('Post comment 24');
      done();
      return input;
    };

    const commentForm = content.find('form[name="comment"]');
    commentForm
      .find('[name="content"]')
      .last()
      .simulate('change', { target: { name: 'content', value: 'Post comment 24' } });
    commentForm.last().simulate('submit');
  });

  step('Comment adding works after submit', () => {
    expect(content.text()).to.include('Post comment 24');
  });

  step('Updates comment form on comment added got from subscription', () => {
    const subscription = renderer.getSubscriptions(COMMENT_SUBSCRIPTION)[0];
    subscription.next({
      data: {
        commentUpdated: {
          mutation: 'CREATED',
          id: 3003,
          postId: 3,
          node: {
            id: 3003,
            content: 'Post comment 3',
            __typename: 'Comment'
          },
          __typename: 'UpdateCommentPayload'
        }
      }
    });

    expect(content.text()).to.include('Post comment 3');
  });

  step('Updates comment form on comment deleted got from subscription', () => {
    const subscription = renderer.getSubscriptions(COMMENT_SUBSCRIPTION)[0];
    subscription.next({
      data: {
        commentUpdated: {
          mutation: 'DELETED',
          id: 3003,
          postId: 3,
          node: {
            id: 3003,
            content: 'Post comment 3',
            __typename: 'Comment'
          },
          __typename: 'UpdateCommentPayload'
        }
      }
    });
    expect(content.text()).to.not.include('Post comment 3');
  });

  step('Comment deleting optimistically removes comment', () => {
    const deleteButtons = content.find('.delete-comment');
    expect(deleteButtons).has.lengthOf(9);
    deleteButtons.last().simulate('click');

    app.update();
    content = app.find('#content').last();
    expect(content.text()).to.not.include('Post comment 24');
    expect(content.find('.delete-comment')).has.lengthOf(6);
  });

  step('Clicking comment delete removes the comment', () => {
    expect(content.text()).to.not.include('Post comment 24');
    expect(content.find('.delete-comment')).has.lengthOf(6);
  });

  step('Comment editing works', async done => {
    mutations.editComment = (obj, { input }) => {
      expect(input.postId).to.equal(3);
      expect(input.content).to.equal('Edited comment 2');
      done();
      return input;
    };
    const editButtons = content.find('.edit-comment');
    expect(editButtons).has.lengthOf(6);
    editButtons.last().simulate('click');
    editButtons.last().simulate('click');
    const commentForm = content.find('form[name="comment"]');
    expect(
      commentForm
        .find('[name="content"]')
        .last()
        .instance().value
    ).to.equal('Post comment 2');
    commentForm
      .find('[name="content"]')
      .last()
      .simulate('change', { target: { name: 'content', value: 'Edited comment 2' } });
    commentForm.simulate('submit');
  });

  step('Comment editing works', () => {
    expect(content.text()).to.include('Edited comment 2');
  });

  step('Clicking back button takes to post list', () => {
    expect(content.text()).to.include('Edited comment 2');
    const backButton = content.find('#back-button');
    backButton.last().simulate('click', { button: 0 });
    app.update();
    content = app.find('#content').last();
    expect(content.text()).to.include('Post title 3');
  });
});