|
5 | 5 | "errors" |
6 | 6 | "strconv" |
7 | 7 | "testing" |
| 8 | + "time" |
8 | 9 |
|
9 | 10 | "github.com/99designs/gqlgen/client" |
10 | 11 | "github.com/99designs/gqlgen/graphql/handler" |
@@ -1577,6 +1578,352 @@ func TestUserResolver_TotalPoints(t *testing.T) { |
1577 | 1578 | }) |
1578 | 1579 | } |
1579 | 1580 |
|
| 1581 | +func TestUserResolver_Cheating(t *testing.T) { |
| 1582 | + t.Run("user with no cheat records", func(t *testing.T) { |
| 1583 | + entClient := testhelper.NewEntSqliteClient(t) |
| 1584 | + |
| 1585 | + // Create test group |
| 1586 | + group, err := createTestGroup(t, entClient) |
| 1587 | + require.NoError(t, err) |
| 1588 | + |
| 1589 | + // Create a test user with no cheat records |
| 1590 | + user, err := entClient.User.Create(). |
| 1591 | + SetName("testuser"). |
| 1592 | + SetEmail("test@example.com"). |
| 1593 | + SetGroup(group). |
| 1594 | + Save(context.Background()) |
| 1595 | + require.NoError(t, err) |
| 1596 | + |
| 1597 | + // Setup test resolver |
| 1598 | + resolver := NewTestResolver(t, entClient, &mockAuthStorage{}) |
| 1599 | + |
| 1600 | + // Create test server with scope directive |
| 1601 | + cfg := Config{ |
| 1602 | + Resolvers: resolver, |
| 1603 | + Directives: DirectiveRoot{Scope: directive.ScopeDirective}, |
| 1604 | + } |
| 1605 | + srv := handler.New(NewExecutableSchema(cfg)) |
| 1606 | + srv.AddTransport(transport.POST{}) |
| 1607 | + gqlClient := client.New(srv) |
| 1608 | + |
| 1609 | + // Execute query |
| 1610 | + var resp struct { |
| 1611 | + User struct { |
| 1612 | + Cheating bool |
| 1613 | + } |
| 1614 | + } |
| 1615 | + err = gqlClient.Post(`query { user(id: `+strconv.Itoa(user.ID)+`) { cheating } }`, &resp, func(bd *client.Request) { |
| 1616 | + bd.HTTP = bd.HTTP.WithContext(auth.WithUser(bd.HTTP.Context(), auth.TokenInfo{ |
| 1617 | + UserID: 1, |
| 1618 | + Scopes: []string{"user:read"}, |
| 1619 | + })) |
| 1620 | + }) |
| 1621 | + |
| 1622 | + // Verify response |
| 1623 | + require.NoError(t, err) |
| 1624 | + require.False(t, resp.User.Cheating) |
| 1625 | + }) |
| 1626 | + |
| 1627 | + t.Run("user with unresolved cheat record", func(t *testing.T) { |
| 1628 | + entClient := testhelper.NewEntSqliteClient(t) |
| 1629 | + |
| 1630 | + // Create test group |
| 1631 | + group, err := createTestGroup(t, entClient) |
| 1632 | + require.NoError(t, err) |
| 1633 | + |
| 1634 | + // Create a test user |
| 1635 | + user, err := entClient.User.Create(). |
| 1636 | + SetName("testuser"). |
| 1637 | + SetEmail("test@example.com"). |
| 1638 | + SetGroup(group). |
| 1639 | + Save(context.Background()) |
| 1640 | + require.NoError(t, err) |
| 1641 | + |
| 1642 | + // Create an unresolved cheat record |
| 1643 | + _, err = entClient.CheatRecord.Create(). |
| 1644 | + SetUser(user). |
| 1645 | + SetReason("Suspected cheating"). |
| 1646 | + Save(context.Background()) |
| 1647 | + require.NoError(t, err) |
| 1648 | + |
| 1649 | + // Setup test resolver |
| 1650 | + resolver := NewTestResolver(t, entClient, &mockAuthStorage{}) |
| 1651 | + |
| 1652 | + // Create test server with scope directive |
| 1653 | + cfg := Config{ |
| 1654 | + Resolvers: resolver, |
| 1655 | + Directives: DirectiveRoot{Scope: directive.ScopeDirective}, |
| 1656 | + } |
| 1657 | + srv := handler.New(NewExecutableSchema(cfg)) |
| 1658 | + srv.AddTransport(transport.POST{}) |
| 1659 | + gqlClient := client.New(srv) |
| 1660 | + |
| 1661 | + // Execute query |
| 1662 | + var resp struct { |
| 1663 | + User struct { |
| 1664 | + Cheating bool |
| 1665 | + } |
| 1666 | + } |
| 1667 | + err = gqlClient.Post(`query { user(id: `+strconv.Itoa(user.ID)+`) { cheating } }`, &resp, func(bd *client.Request) { |
| 1668 | + bd.HTTP = bd.HTTP.WithContext(auth.WithUser(bd.HTTP.Context(), auth.TokenInfo{ |
| 1669 | + UserID: 1, |
| 1670 | + Scopes: []string{"user:read"}, |
| 1671 | + })) |
| 1672 | + }) |
| 1673 | + |
| 1674 | + // Verify response |
| 1675 | + require.NoError(t, err) |
| 1676 | + require.True(t, resp.User.Cheating) |
| 1677 | + }) |
| 1678 | + |
| 1679 | + t.Run("user with only resolved cheat records", func(t *testing.T) { |
| 1680 | + entClient := testhelper.NewEntSqliteClient(t) |
| 1681 | + |
| 1682 | + // Create test group |
| 1683 | + group, err := createTestGroup(t, entClient) |
| 1684 | + require.NoError(t, err) |
| 1685 | + |
| 1686 | + // Create a test user |
| 1687 | + user, err := entClient.User.Create(). |
| 1688 | + SetName("testuser"). |
| 1689 | + SetEmail("test@example.com"). |
| 1690 | + SetGroup(group). |
| 1691 | + Save(context.Background()) |
| 1692 | + require.NoError(t, err) |
| 1693 | + |
| 1694 | + // Create a resolved cheat record |
| 1695 | + _, err = entClient.CheatRecord.Create(). |
| 1696 | + SetUser(user). |
| 1697 | + SetReason("Suspected cheating"). |
| 1698 | + SetResolvedAt(time.Now()). |
| 1699 | + SetResolvedReason("False alarm"). |
| 1700 | + Save(context.Background()) |
| 1701 | + require.NoError(t, err) |
| 1702 | + |
| 1703 | + // Setup test resolver |
| 1704 | + resolver := NewTestResolver(t, entClient, &mockAuthStorage{}) |
| 1705 | + |
| 1706 | + // Create test server with scope directive |
| 1707 | + cfg := Config{ |
| 1708 | + Resolvers: resolver, |
| 1709 | + Directives: DirectiveRoot{Scope: directive.ScopeDirective}, |
| 1710 | + } |
| 1711 | + srv := handler.New(NewExecutableSchema(cfg)) |
| 1712 | + srv.AddTransport(transport.POST{}) |
| 1713 | + gqlClient := client.New(srv) |
| 1714 | + |
| 1715 | + // Execute query |
| 1716 | + var resp struct { |
| 1717 | + User struct { |
| 1718 | + Cheating bool |
| 1719 | + } |
| 1720 | + } |
| 1721 | + err = gqlClient.Post(`query { user(id: `+strconv.Itoa(user.ID)+`) { cheating } }`, &resp, func(bd *client.Request) { |
| 1722 | + bd.HTTP = bd.HTTP.WithContext(auth.WithUser(bd.HTTP.Context(), auth.TokenInfo{ |
| 1723 | + UserID: 1, |
| 1724 | + Scopes: []string{"user:read"}, |
| 1725 | + })) |
| 1726 | + }) |
| 1727 | + |
| 1728 | + // Verify response |
| 1729 | + require.NoError(t, err) |
| 1730 | + require.False(t, resp.User.Cheating) |
| 1731 | + }) |
| 1732 | + |
| 1733 | + t.Run("user with multiple unresolved cheat records", func(t *testing.T) { |
| 1734 | + entClient := testhelper.NewEntSqliteClient(t) |
| 1735 | + |
| 1736 | + // Create test group |
| 1737 | + group, err := createTestGroup(t, entClient) |
| 1738 | + require.NoError(t, err) |
| 1739 | + |
| 1740 | + // Create a test user |
| 1741 | + user, err := entClient.User.Create(). |
| 1742 | + SetName("testuser"). |
| 1743 | + SetEmail("test@example.com"). |
| 1744 | + SetGroup(group). |
| 1745 | + Save(context.Background()) |
| 1746 | + require.NoError(t, err) |
| 1747 | + |
| 1748 | + // Create multiple unresolved cheat records |
| 1749 | + reasons := []string{"First violation", "Second violation", "Third violation"} |
| 1750 | + for _, reason := range reasons { |
| 1751 | + _, err = entClient.CheatRecord.Create(). |
| 1752 | + SetUser(user). |
| 1753 | + SetReason(reason). |
| 1754 | + Save(context.Background()) |
| 1755 | + require.NoError(t, err) |
| 1756 | + } |
| 1757 | + |
| 1758 | + // Setup test resolver |
| 1759 | + resolver := NewTestResolver(t, entClient, &mockAuthStorage{}) |
| 1760 | + |
| 1761 | + // Create test server with scope directive |
| 1762 | + cfg := Config{ |
| 1763 | + Resolvers: resolver, |
| 1764 | + Directives: DirectiveRoot{Scope: directive.ScopeDirective}, |
| 1765 | + } |
| 1766 | + srv := handler.New(NewExecutableSchema(cfg)) |
| 1767 | + srv.AddTransport(transport.POST{}) |
| 1768 | + gqlClient := client.New(srv) |
| 1769 | + |
| 1770 | + // Execute query |
| 1771 | + var resp struct { |
| 1772 | + User struct { |
| 1773 | + Cheating bool |
| 1774 | + } |
| 1775 | + } |
| 1776 | + err = gqlClient.Post(`query { user(id: `+strconv.Itoa(user.ID)+`) { cheating } }`, &resp, func(bd *client.Request) { |
| 1777 | + bd.HTTP = bd.HTTP.WithContext(auth.WithUser(bd.HTTP.Context(), auth.TokenInfo{ |
| 1778 | + UserID: 1, |
| 1779 | + Scopes: []string{"user:read"}, |
| 1780 | + })) |
| 1781 | + }) |
| 1782 | + |
| 1783 | + // Verify response |
| 1784 | + require.NoError(t, err) |
| 1785 | + require.True(t, resp.User.Cheating) |
| 1786 | + }) |
| 1787 | + |
| 1788 | + t.Run("user with mixed resolved and unresolved cheat records", func(t *testing.T) { |
| 1789 | + entClient := testhelper.NewEntSqliteClient(t) |
| 1790 | + |
| 1791 | + // Create test group |
| 1792 | + group, err := createTestGroup(t, entClient) |
| 1793 | + require.NoError(t, err) |
| 1794 | + |
| 1795 | + // Create a test user |
| 1796 | + user, err := entClient.User.Create(). |
| 1797 | + SetName("testuser"). |
| 1798 | + SetEmail("test@example.com"). |
| 1799 | + SetGroup(group). |
| 1800 | + Save(context.Background()) |
| 1801 | + require.NoError(t, err) |
| 1802 | + |
| 1803 | + // Create a resolved cheat record |
| 1804 | + _, err = entClient.CheatRecord.Create(). |
| 1805 | + SetUser(user). |
| 1806 | + SetReason("Resolved violation"). |
| 1807 | + SetResolvedAt(time.Now()). |
| 1808 | + SetResolvedReason("False alarm"). |
| 1809 | + Save(context.Background()) |
| 1810 | + require.NoError(t, err) |
| 1811 | + |
| 1812 | + // Create an unresolved cheat record |
| 1813 | + _, err = entClient.CheatRecord.Create(). |
| 1814 | + SetUser(user). |
| 1815 | + SetReason("Unresolved violation"). |
| 1816 | + Save(context.Background()) |
| 1817 | + require.NoError(t, err) |
| 1818 | + |
| 1819 | + // Setup test resolver |
| 1820 | + resolver := NewTestResolver(t, entClient, &mockAuthStorage{}) |
| 1821 | + |
| 1822 | + // Create test server with scope directive |
| 1823 | + cfg := Config{ |
| 1824 | + Resolvers: resolver, |
| 1825 | + Directives: DirectiveRoot{Scope: directive.ScopeDirective}, |
| 1826 | + } |
| 1827 | + srv := handler.New(NewExecutableSchema(cfg)) |
| 1828 | + srv.AddTransport(transport.POST{}) |
| 1829 | + gqlClient := client.New(srv) |
| 1830 | + |
| 1831 | + // Execute query |
| 1832 | + var resp struct { |
| 1833 | + User struct { |
| 1834 | + Cheating bool |
| 1835 | + } |
| 1836 | + } |
| 1837 | + err = gqlClient.Post(`query { user(id: `+strconv.Itoa(user.ID)+`) { cheating } }`, &resp, func(bd *client.Request) { |
| 1838 | + bd.HTTP = bd.HTTP.WithContext(auth.WithUser(bd.HTTP.Context(), auth.TokenInfo{ |
| 1839 | + UserID: 1, |
| 1840 | + Scopes: []string{"user:read"}, |
| 1841 | + })) |
| 1842 | + }) |
| 1843 | + |
| 1844 | + // Verify response - should be true because there's at least one unresolved record |
| 1845 | + require.NoError(t, err) |
| 1846 | + require.True(t, resp.User.Cheating) |
| 1847 | + }) |
| 1848 | + |
| 1849 | + t.Run("direct resolver method call", func(t *testing.T) { |
| 1850 | + entClient := testhelper.NewEntSqliteClient(t) |
| 1851 | + |
| 1852 | + // Create test group |
| 1853 | + group, err := createTestGroup(t, entClient) |
| 1854 | + require.NoError(t, err) |
| 1855 | + |
| 1856 | + // Create a test user |
| 1857 | + user, err := entClient.User.Create(). |
| 1858 | + SetName("testuser"). |
| 1859 | + SetEmail("test@example.com"). |
| 1860 | + SetGroup(group). |
| 1861 | + Save(context.Background()) |
| 1862 | + require.NoError(t, err) |
| 1863 | + |
| 1864 | + // Create an unresolved cheat record |
| 1865 | + _, err = entClient.CheatRecord.Create(). |
| 1866 | + SetUser(user). |
| 1867 | + SetReason("Direct test violation"). |
| 1868 | + Save(context.Background()) |
| 1869 | + require.NoError(t, err) |
| 1870 | + |
| 1871 | + // Test the resolver method directly |
| 1872 | + resolver := NewTestResolver(t, entClient, &mockAuthStorage{}) |
| 1873 | + userResolver := &userResolver{resolver} |
| 1874 | + |
| 1875 | + cheating, err := userResolver.Cheating(context.Background(), user) |
| 1876 | + require.NoError(t, err) |
| 1877 | + require.True(t, cheating) |
| 1878 | + }) |
| 1879 | + |
| 1880 | + t.Run("user isolation - cheating status doesn't leak between users", func(t *testing.T) { |
| 1881 | + entClient := testhelper.NewEntSqliteClient(t) |
| 1882 | + |
| 1883 | + // Create test group |
| 1884 | + group, err := createTestGroup(t, entClient) |
| 1885 | + require.NoError(t, err) |
| 1886 | + |
| 1887 | + // Create two test users |
| 1888 | + user1, err := entClient.User.Create(). |
| 1889 | + SetName("user1"). |
| 1890 | + SetEmail("user1@example.com"). |
| 1891 | + SetGroup(group). |
| 1892 | + Save(context.Background()) |
| 1893 | + require.NoError(t, err) |
| 1894 | + |
| 1895 | + user2, err := entClient.User.Create(). |
| 1896 | + SetName("user2"). |
| 1897 | + SetEmail("user2@example.com"). |
| 1898 | + SetGroup(group). |
| 1899 | + Save(context.Background()) |
| 1900 | + require.NoError(t, err) |
| 1901 | + |
| 1902 | + // Create unresolved cheat record for user1 |
| 1903 | + _, err = entClient.CheatRecord.Create(). |
| 1904 | + SetUser(user1). |
| 1905 | + SetReason("User 1 violation"). |
| 1906 | + Save(context.Background()) |
| 1907 | + require.NoError(t, err) |
| 1908 | + |
| 1909 | + // user2 has no cheat records |
| 1910 | + |
| 1911 | + // Test the resolver method directly for both users |
| 1912 | + resolver := NewTestResolver(t, entClient, &mockAuthStorage{}) |
| 1913 | + userResolver := &userResolver{resolver} |
| 1914 | + |
| 1915 | + // Check user1 cheating status |
| 1916 | + cheating1, err := userResolver.Cheating(context.Background(), user1) |
| 1917 | + require.NoError(t, err) |
| 1918 | + require.True(t, cheating1) |
| 1919 | + |
| 1920 | + // Check user2 cheating status |
| 1921 | + cheating2, err := userResolver.Cheating(context.Background(), user2) |
| 1922 | + require.NoError(t, err) |
| 1923 | + require.False(t, cheating2) |
| 1924 | + }) |
| 1925 | +} |
| 1926 | + |
1580 | 1927 | func TestMutationResolver_CreateCheatRecord(t *testing.T) { |
1581 | 1928 | t.Run("success - create for self", func(t *testing.T) { |
1582 | 1929 | entClient := testhelper.NewEntSqliteClient(t) |
|
0 commit comments