// Arup Guha
// 3/10/2016
// Solution to 2016 UCF HS Contest Problem: Chessboard Construction

import java.util.*;

public class chessboard {

	// Useful constants.
	final public static int NUM_SQUARES = 64;
	final public static int SIZE = 8;
	final public static int NUM_ROTATIONS = 4;

	// To store pieces.
	public static int n;
	public static boolean[][][] pieces;

	public static void main(String[] args) {

		Scanner stdin = new Scanner(System.in);
		int numCases = stdin.nextInt();

		// Process each case.
		for (int loop=1; loop<=numCases; loop++) {

			// Read in the first board.
			n = stdin.nextInt();
			pieces = new boolean[NUM_ROTATIONS][n][];
			for (int i=0; i<n; i++)
				pieces[0][i] = convert(stdin.next().trim());

			// Fix first piece.
			pieces[0] = fix(pieces[0]);

			// Calculate rotations.
			for (int i=1; i<NUM_ROTATIONS; i++) {
				pieces[i] = rotate(pieces[i-1]);
				pieces[i] = fix(pieces[i]);
			}

			// Solve and output.
			boolean res = solve();
			if (res)
				System.out.println("Piece #"+loop+": YES");
			else
				System.out.println("Piece #"+loop+": NO");
		}
	}

	// Converts the string s into an equivalent boolean array ('*' = true)
	public static boolean[] convert(String s) {
		boolean[] res = new boolean[s.length()];
		for (int i=0; i<res.length; i++)
			res[i] = s.charAt(i) == '*' ? true : false;
		return res;
	}

	// Returns a right 90 degree rotation or orig.
	public static boolean[][] rotate(boolean[][] orig) {
		boolean[][] res = new boolean[orig.length][orig.length];
		for (int i=0; i<orig.length; i++)
			for (int j=0; j<orig.length; j++)
				res[j][orig.length-1-i] = orig[i][j];
		return res;
	}

	public static boolean[][] fix(boolean[][] orig) {

		// Set the first row and first column with a star.
		int firstR = orig.length, firstC = orig.length;
		for (int i=0; i<orig.length; i++) {
			for (int j=0; j<orig.length; j++) {
				if (orig[i][j]) {
					firstR = Math.min(firstR, i);
					firstC = Math.min(firstC, j);
				}
			}
		}

		// Copy with the offset.
		boolean[][] res = new boolean[orig.length][orig.length];
		for (int i=firstR; i<res.length; i++)
			for (int j=firstC; j<res.length; j++)
				res[i-firstR][j-firstC] = orig[i][j];

		return res;
	}

	public static boolean solve() {

		// Take care of some easy cases.
		if (NUM_SQUARES%n != 0) return false;
		if (n == 1 || n == 2) return true;

		// This is the brute force solution, starting at the top.
		return solveRec(new boolean[8][8], 0, 0);
	}

	// Returns whether true iff a solution exists for board where everything has been filled up until
	// row x, col y (in row major order.)
	public static boolean solveRec(boolean[][] board, int x, int y) {

		// Easy base case!
		if (x == SIZE) return true;

		// Try adding each piece next.
		for (int i=0; i<NUM_ROTATIONS; i++) {
			if (canAdd(board, pieces[i], x, y)) {
				change(board, pieces[i], x, y, true);
				int openPos = findOpenPos(board);

				// Now, recursively solve this board - return immediately if it works!
				boolean temp = solveRec(board, openPos/SIZE, openPos%SIZE);
				if (temp) return true;

				// This is important.
				change(board, pieces[i], x, y, false);
			}
		}

		// If we make it here, we can't do it.
		return false;
	}

	public static boolean canAdd(boolean[][] board, boolean[][] item, int x, int y) {

		// Find the first column on row one with a '*'.
		int firstC = item.length;
		for (int i=0; i<item.length; i++) {
			if (item[0][i]) {
				firstC = i;
				break;
			}
		}

		// Go through trying to place each cell of item on board, offset by (x,y)
		for (int i=0; i<item.length; i++) {
			for (int j=0; j<item.length; j++) {

				// Where this cell belongs on board.
				int boardX =  x + i;
				int boardY = y + j - firstC;

				// We only care about cells that are on.
				if (item[i][j]) {

					// Can't turn on an out of bounds square.
					if (boardX < 0 || boardX >= SIZE || boardY < 0 || boardY >= SIZE) return false;

					// Can't place a piece on top of one that exists.
					if (board[boardX][boardY]) return false;
				}
			}
		}

		// If we get here, it's possible.
		return true;
	}

	public static void change(boolean[][] board, boolean[][] item, int x, int y, boolean state) {

		// Find the first column on row one with a '*'.
		int firstC = item.length;
		for (int i=0; i<item.length; i++) {
			if (item[0][i]) {
				firstC = i;
				break;
			}
		}

		// Go through and place each cell of item on board, offset by (x,y)
		for (int i=0; i<item.length; i++) {
			for (int j=0; j<item.length; j++) {

				// Where this cell belongs on board.
				int boardX =  x + i;
				int boardY = y + j - firstC;

				// We only care about cells that are on.
				if (item[i][j]) board[boardX][boardY] = state;
			}
		}
	}

	public static int findOpenPos(boolean[][] board) {

		// Look for first false square('.') and return.
		for (int i=0; i<SIZE; i++)
			for (int j=0; j<SIZE; j++)
				if (!board[i][j])
					return SIZE*i+j;

		// Indicates nothing was found.
		return SIZE*SIZE;
	}
}