123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- import * as anchor from '@project-serum/anchor';
- import { AnchorError, Program } from '@project-serum/anchor';
- import { TicTacToe } from '../target/types/tic_tac_toe';
- import chai from 'chai';
- import chaiAsPromised from 'chai-as-promised';
- import { expect } from 'chai';
- chai.use(chaiAsPromised);
- async function play(program: Program<TicTacToe>, game, player, tile, expectedTurn, expectedGameState, expectedBoard) {
- await program.methods
- .play(tile)
- .accounts({
- player: player.publicKey,
- game
- })
- .signers(player instanceof (anchor.Wallet as any) ? [] : [player])
- .rpc();
- const gameState = await program.account.game.fetch(game);
- expect(gameState.turn).to.equal(expectedTurn);
- expect(gameState.state).to.eql(expectedGameState);
- expect(gameState.board)
- .to
- .eql(expectedBoard);
- }
- describe('tic-tac-toe', () => {
- // Configure the client to use the local cluster.
- anchor.setProvider(anchor.AnchorProvider.env());
- const program = anchor.workspace.TicTacToe as Program<TicTacToe>;
- const programProvider = program.provider as anchor.AnchorProvider;
- it('setup game!', async() => {
- const gameKeypair = anchor.web3.Keypair.generate();
- const playerOne = programProvider.wallet;
- const playerTwo = anchor.web3.Keypair.generate();
- await program.methods
- .setupGame(playerTwo.publicKey)
- .accounts({
- game: gameKeypair.publicKey,
- playerOne: playerOne.publicKey,
- })
- .signers([gameKeypair])
- .rpc();
- let gameState = await program.account.game.fetch(gameKeypair.publicKey);
- expect(gameState.turn).to.equal(1);
- expect(gameState.players)
- .to
- .eql([playerOne.publicKey, playerTwo.publicKey]);
- expect(gameState.state).to.eql({ active: {} });
- expect(gameState.board)
- .to
- .eql([[null,null,null],[null,null,null],[null,null,null]]);
- });
- it('player one wins!', async () => {
- const gameKeypair = anchor.web3.Keypair.generate();
- const playerOne = programProvider.wallet;
- const playerTwo = anchor.web3.Keypair.generate();
- await program.methods
- .setupGame(playerTwo.publicKey)
- .accounts({
- game: gameKeypair.publicKey,
- playerOne: playerOne.publicKey,
- })
- .signers([gameKeypair])
- .rpc();
- let gameState = await program.account.game.fetch(gameKeypair.publicKey);
- expect(gameState.turn).to.equal(1);
- expect(gameState.players)
- .to
- .eql([playerOne.publicKey, playerTwo.publicKey]);
- expect(gameState.state).to.eql({ active: {} });
- expect(gameState.board)
- .to
- .eql([[null,null,null],[null,null,null],[null,null,null]]);
- await play(
- program,
- gameKeypair.publicKey,
- playerOne,
- {row: 0, column: 0},
- 2,
- { active: {}, },
- [
- [{x:{}},null,null],
- [null,null,null],
- [null,null,null]
- ]
- );
- try {
- await play(
- program,
- gameKeypair.publicKey,
- playerOne, // same player in subsequent turns
- // change sth about the tx because
- // duplicate tx that come in too fast
- // after each other may get dropped
- {row: 1, column: 0},
- 2,
- { active: {}, },
- [
- [{x:{}},null,null],
- [null,null,null],
- [null,null,null]
- ]
- );
- chai.assert(false, "should've failed but didn't ");
- } catch (_err) {
- expect(_err).to.be.instanceOf(AnchorError);
- const err: AnchorError = _err;
- expect(err.error.errorCode.code).to.equal("NotPlayersTurn");
- expect(err.error.errorCode.number).to.equal(6003);
- expect(err.program.equals(program.programId)).is.true;
- expect(err.error.comparedValues).to.deep.equal([playerTwo.publicKey, playerOne.publicKey]);
- }
- await play(
- program,
- gameKeypair.publicKey,
- playerTwo,
- {row: 1, column: 0},
- 3,
- { active: {}, },
- [
- [{x:{}},null,null],
- [{o:{}},null,null],
- [null,null,null]
- ]
- );
- await play(
- program,
- gameKeypair.publicKey,
- playerOne,
- {row: 0, column: 1},
- 4,
- { active: {}, },
- [
- [{x:{}},{x: {}},null],
- [{o:{}},null,null],
- [null,null,null]
- ]
- );
- try {
- await play(
- program,
- gameKeypair.publicKey,
- playerTwo,
- {row: 5, column: 1}, // out of bounds row
- 4,
- { active: {}, },
- [
- [{x:{}},{x: {}},null],
- [{o:{}},null,null],
- [null,null,null]
- ]
- );
- chai.assert(false, "should've failed but didn't ");
- } catch (_err) {
- expect(_err).to.be.instanceOf(AnchorError);
- const err: AnchorError = _err;
- expect(err.error.errorCode.number).to.equal(6000);
- expect(err.error.errorCode.code).to.equal("TileOutOfBounds");
- }
- await play(
- program,
- gameKeypair.publicKey,
- playerTwo,
- {row: 1, column: 1},
- 5,
- { active: {}, },
- [
- [{x:{}},{x: {}},null],
- [{o:{}},{o:{}},null],
- [null,null,null]
- ]
- );
- try {
- await play(
- program,
- gameKeypair.publicKey,
- playerOne,
- {row: 0, column: 0},
- 5,
- { active: {}, },
- [
- [{x:{}},{x: {}},null],
- [{o:{}},{o:{}},null],
- [null,null,null]
- ]
- );
- chai.assert(false, "should've failed but didn't ");
- } catch (_err) {
- expect(_err).to.be.instanceOf(AnchorError);
- const err: AnchorError = _err;
- expect(err.error.errorCode.number).to.equal(6001);
- }
- await play(
- program,
- gameKeypair.publicKey,
- playerOne,
- {row: 0, column: 2},
- 5,
- { won: { winner: playerOne.publicKey }, },
- [
- [{x:{}},{x: {}},{x: {}}],
- [{o:{}},{o:{}},null],
- [null,null,null]
- ]
- );
- try {
- await play(
- program,
- gameKeypair.publicKey,
- playerOne,
- {row: 0, column: 2},
- 5,
- { won: { winner: playerOne.publicKey }, },
- [
- [{x:{}},{x: {}},{x: {}}],
- [{o:{}},{o:{}},null],
- [null,null,null]
- ]
- );
- chai.assert(false, "should've failed but didn't ");
- } catch (_err) {
- expect(_err).to.be.instanceOf(AnchorError);
- const err: AnchorError = _err;
- expect(err.error.errorCode.number).to.equal(6002);
- }
- })
- it('tie', async () => {
- const gameKeypair = anchor.web3.Keypair.generate();
- const playerOne = programProvider.wallet;
- const playerTwo = anchor.web3.Keypair.generate();
- await program.methods
- .setupGame(playerTwo.publicKey)
- .accounts({
- game: gameKeypair.publicKey,
- playerOne: playerOne.publicKey,
- })
- .signers([gameKeypair])
- .rpc();
- let gameState = await program.account.game.fetch(gameKeypair.publicKey);
- expect(gameState.turn).to.equal(1);
- expect(gameState.players)
- .to
- .eql([playerOne.publicKey, playerTwo.publicKey]);
- expect(gameState.state).to.eql({ active: {} });
- expect(gameState.board)
- .to
- .eql([[null,null,null],[null,null,null],[null,null,null]]);
- await play(
- program,
- gameKeypair.publicKey,
- playerOne,
- {row: 0, column: 0},
- 2,
- { active: {}, },
- [
- [{x:{}},null,null],
- [null,null,null],
- [null,null,null]
- ]
- );
- await play(
- program,
- gameKeypair.publicKey,
- playerTwo,
- {row: 1, column: 1},
- 3,
- { active: {}, },
- [
- [{x:{}},null,null],
- [null,{o:{}},null],
- [null,null,null]
- ]
- );
- await play(
- program,
- gameKeypair.publicKey,
- playerOne,
- {row: 2, column: 0},
- 4,
- { active: {}, },
- [
- [{x:{}},null,null],
- [null,{o:{}},null],
- [{x:{}},null,null]
- ]
- );
- await play(
- program,
- gameKeypair.publicKey,
- playerTwo,
- {row: 1, column: 0},
- 5,
- { active: {}, },
- [
- [{x:{}},null,null],
- [{o:{}},{o:{}},null],
- [{x:{}},null,null]
- ]
- );
- await play(
- program,
- gameKeypair.publicKey,
- playerOne,
- {row: 1, column: 2},
- 6,
- { active: {}, },
- [
- [{x:{}},null,null],
- [{o:{}},{o:{}},{x:{}}],
- [{x:{}},null,null]
- ]
- );
- await play(
- program,
- gameKeypair.publicKey,
- playerTwo,
- {row: 0, column: 1},
- 7,
- { active: {}, },
- [
- [{x:{}},{o:{}},null],
- [{o:{}},{o:{}},{x:{}}],
- [{x:{}},null,null]
- ]
- );
- await play(
- program,
- gameKeypair.publicKey,
- playerOne,
- {row: 2, column: 1},
- 8,
- { active: {}, },
- [
- [{x:{}},{o:{}},null],
- [{o:{}},{o:{}},{x:{}}],
- [{x:{}},{x:{}},null]
- ]
- );
- await play(
- program,
- gameKeypair.publicKey,
- playerTwo,
- {row: 2, column: 2},
- 9,
- { active: {}, },
- [
- [{x:{}},{o:{}},null],
- [{o:{}},{o:{}},{x:{}}],
- [{x:{}},{x:{}},{o:{}}]
- ]
- );
- await play(
- program,
- gameKeypair.publicKey,
- playerOne,
- {row: 0, column: 2},
- 9,
- { tie: {}, },
- [
- [{x:{}},{o:{}},{x:{}}],
- [{o:{}},{o:{}},{x:{}}],
- [{x:{}},{x:{}},{o:{}}]
- ]
- );
- })
- });
|